WIP multi-shader support, see details:

- picasso now accepts several input files, which are each compiled
  into DVLE objects inside the .shbin
- Uniform allocation is shared amongst all DVLEs.
- Constant allocation is private to each DVLE.
- Header file generation is temporarily disabled.
- New directives:
  .nodvle
    Disables the generation of a DVLE object for the current input file.
    This allows sharing code amongst shaders.
  .entry entryName
    Specifies the name of the entrypoint procedure of the current DVLE.
    By default it's 'main'.
This commit is contained in:
fincs 2015-08-13 21:46:08 +02:00
parent b250513be0
commit e152f4e626
4 changed files with 383 additions and 207 deletions

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_INIT([picasso],[1.0.0],[fincs.alt1@gmail.com])
AC_INIT([picasso],[2.0.0],[fincs.alt1@gmail.com])
AC_CONFIG_SRCDIR([source/picasso_frontend.cpp])
AM_INIT_AUTOMAKE([1.10])

View File

@ -58,10 +58,13 @@ enum
COND_UNK2,
};
//-----------------------------------------------------------------------------
// Global data
//-----------------------------------------------------------------------------
// Output buffer
typedef std::vector<u32> outputBufType;
typedef outputBufType::iterator outputBufIter;
extern bool g_isGeoShader;
extern outputBufType g_outputBuf;
enum
@ -87,6 +90,7 @@ struct StackEntry
extern StackEntry g_stack[MAX_STACK];
extern int g_stackPos;
// Operand descriptor stuff.
#define MAX_OPDESC 128
extern int g_opdescTable[MAX_OPDESC];
extern int g_opdeskMasks[MAX_OPDESC]; // used to keep track of used bits
@ -106,10 +110,45 @@ struct Uniform
int type;
};
// List of uniforms
#define MAX_UNIFORM 0x60
extern Uniform g_uniformTable[MAX_UNIFORM];
extern int g_uniformCount;
struct DVLEData; // Forward declaration
typedef std::pair<size_t, size_t> procedure; // position, size
typedef std::pair<size_t, std::string> relocation; // position, name
typedef std::map<std::string, procedure> procTableType;
typedef std::map<std::string, size_t> labelTableType;
typedef std::map<std::string, int> aliasTableType;
typedef std::vector<relocation> relocTableType;
typedef std::list<DVLEData> dvleTableType;
typedef procTableType::iterator procTableIter;
typedef labelTableType::iterator labelTableIter;
typedef aliasTableType::iterator aliasTableIter;
typedef relocTableType::iterator relocTableIter;
typedef dvleTableType::iterator dvleTableIter;
extern procTableType g_procTable;
extern dvleTableType g_dvleTable;
extern relocTableType g_procRelocTable;
extern int g_totalDvleCount;
// The following are cleared before each file is processed
extern labelTableType g_labels;
extern relocTableType g_labelRelocTable;
extern aliasTableType g_aliases;
int AssembleString(char* str, const char* initialFilename);
int RelocateProduct(void);
//-----------------------------------------------------------------------------
// Local data
//-----------------------------------------------------------------------------
enum
{
OUTTYPE_POS = 0,
@ -123,10 +162,6 @@ enum
OUTTYPE_VIEW,
};
#define MAX_OUTPUT 8
extern u64 g_outputTable[MAX_OUTPUT];
extern int g_outputCount;
struct Constant
{
int regId;
@ -138,33 +173,32 @@ struct Constant
};
};
#define MAX_CONSTANT 0x60
extern Constant g_constantTable[MAX_CONSTANT];
extern int g_constantCount;
extern size_t g_constantSize;
struct Relocation
struct DVLEData
{
size_t instPos;
const char* target;
bool isProc;
// General config
std::string filename;
std::string entrypoint;
size_t entryStart, entryEnd;
bool nodvle, isGeoShader;
// Uniforms
Uniform uniformTable[MAX_UNIFORM];
int uniformCount;
size_t symbolSize;
// Constants
#define MAX_CONSTANT 0x60
Constant constantTable[MAX_CONSTANT];
int constantCount;
size_t constantSize;
// Outputs
#define MAX_OUTPUT 8
u64 outputTable[MAX_OUTPUT];
int outputCount;
DVLEData(const char* filename) :
filename(filename), entrypoint("main"),
nodvle(false), isGeoShader(false),
uniformCount(0), symbolSize(0), constantCount(0), constantSize(0), outputCount(0) { }
};
typedef std::pair<size_t, size_t> procedure; // position, size
typedef std::map<std::string, procedure> procTableType;
typedef std::map<std::string, size_t> labelTableType;
typedef std::map<std::string, int> aliasTableType;
typedef std::vector<Relocation> relocTableType;
typedef procTableType::iterator procTableIter;
typedef labelTableType::iterator labelTableIter;
typedef aliasTableType::iterator aliasTableIter;
typedef relocTableType::iterator relocTableIter;
extern procTableType g_procTable;
extern labelTableType g_labels;
extern aliasTableType g_aliases;
extern relocTableType g_relocs;
int AssembleString(char* str, const char* initialFilename);

View File

@ -19,21 +19,63 @@ int g_opdescMasks[MAX_OPDESC];
Uniform g_uniformTable[MAX_UNIFORM];
int g_uniformCount;
static int fvecUnifPos = 0x20;
static int ivecUnifPos = 0x80;
static int boolUnifPos = 0x88;
Constant g_constantTable[MAX_CONSTANT];
int g_constantCount;
size_t g_constantSize;
class UniformAlloc
{
int start, end, bound, tend;
public:
UniformAlloc(int start, int end) : start(start), end(end), bound(end), tend(end) { }
void ClearLocal(void) { end = tend; }
int AllocGlobal(int size)
{
if ((start+size) > bound) return -1;
int ret = start;
start += size;
return ret;
}
int AllocLocal(int size)
{
int pos = end - size;
if (pos < start) return -1;
bound = pos < bound ? pos : bound;
return pos;
}
};
u64 g_outputTable[MAX_OUTPUT];
int g_outputCount;
static UniformAlloc fvecAlloc(0x20, 0x80), ivecAlloc(0x80, 0x84), boolAlloc(0x88, 0x98);
procTableType g_procTable;
dvleTableType g_dvleTable;
relocTableType g_procRelocTable;
int g_totalDvleCount;
labelTableType g_labels;
relocTableType g_labelRelocTable;
aliasTableType g_aliases;
relocTableType g_relocs;
static DVLEData* curDvle;
static void ClearStatus(void)
{
fvecAlloc.ClearLocal();
ivecAlloc.ClearLocal();
boolAlloc.ClearLocal();
g_labels.clear();
g_labelRelocTable.clear();
g_aliases.clear();
curDvle = NULL;
}
static DVLEData* GetDvleData(void)
{
if (!curDvle)
{
g_dvleTable.push_back( DVLEData(curFile) );
curDvle = &g_dvleTable.back();
g_totalDvleCount ++;
}
return curDvle;
}
static char* mystrtok_pos;
static char* mystrtok(char* str, const char* delim)
@ -126,13 +168,15 @@ static int parseInt(char* pos, int& out, long long min, long long max)
} while(0)
static int ProcessCommand(const char* cmd);
static int FixupRelocations();
static int FixupLabelRelocations();
int AssembleString(char* str, const char* initialFilename)
{
curFile = initialFilename;
curLine = 1;
ClearStatus();
int nextLineIncr = 0;
char* nextStr = NULL;
for (; str; str = nextStr, curLine += nextLineIncr)
@ -192,35 +236,55 @@ int AssembleString(char* str, const char* initialFilename)
if (g_stackPos)
return throwError("unclosed block(s)\n");
safe_call(FixupRelocations());
safe_call(FixupLabelRelocations());
return 0;
}
int FixupRelocations()
int FixupLabelRelocations()
{
for (relocTableIter it = g_relocs.begin(); it != g_relocs.end(); ++it)
for (relocTableIter it = g_labelRelocTable.begin(); it != g_labelRelocTable.end(); ++it)
{
Relocation& r = *it;
u32& inst = BUF[r.instPos];
if (r.isProc)
{
procTableIter proc = g_procTable.find(r.target);
if (proc == g_procTable.end())
return throwError("procedure '%s' is undefined\n", r.target);
u32 dst = proc->second.first;
u32 num = proc->second.second;
inst &= ~0x3FFFFF;
inst |= num | (dst << 10);
} else
{
labelTableIter lbl = g_labels.find(r.target);
relocation& r = *it;
u32& inst = BUF[r.first];
labelTableIter lbl = g_labels.find(r.second);
if (lbl == g_labels.end())
return throwError("label '%s' is undefined\n", r.target);
return throwError("label '%s' is undefined\n", r.second.c_str());
u32 dst = lbl->second;
inst &= ~(0xFFF << 10);
inst |= dst << 10;
}
return 0;
}
int RelocateProduct()
{
for (relocTableIter it = g_procRelocTable.begin(); it != g_procRelocTable.end(); ++it)
{
relocation& r = *it;
u32& inst = BUF[r.first];
procTableIter proc = g_procTable.find(r.second);
if (proc == g_procTable.end())
return throwError("procedure '%s' is undefined\n", r.second.c_str());
u32 dst = proc->second.first;
u32 num = proc->second.second;
inst &= ~0x3FFFFF;
inst |= num | (dst << 10);
}
if (g_totalDvleCount == 0)
return throwError("no DVLEs can be generated from the given input file(s)\n");
for (dvleTableIter it = g_dvleTable.begin(); it != g_dvleTable.end(); ++it)
{
if (it->nodvle) continue;
curFile = it->filename.c_str();
curLine = 1;
procTableIter mainIt = g_procTable.find(it->entrypoint);
if (mainIt == g_procTable.end())
return throwError("entrypoint '%s' is undefined\n", it->entrypoint.c_str());
it->entryStart = mainIt->second.first;
it->entryEnd = it->entryStart + mainIt->second.second;
}
return 0;
}
@ -422,12 +486,16 @@ static int parseSwizzling(const char* b)
return out<<1;
}
static int maskFromSwizzling(int sw)
static int maskFromSwizzling(int sw, bool reverse = true)
{
sw >>= 1; // get rid of negation bit
int out = 0;
for (int i = 0; i < 4; i ++)
out |= BIT(3-((sw>>(i*2))&3));
{
int bitid = (sw>>(i*2))&3;
if (reverse) bitid = 3 - bitid;
out |= BIT(bitid);
}
return out;
}
@ -841,10 +909,10 @@ DEF_COMMAND(formatsetemit)
safe_call(parseSetEmitFlags(flagStr, isPrim, isInv));
#ifdef DEBUG
printf("%s:%02X vtx%d, %s, %s\n", cmdName, opcode, vtxId, isPrim?"true":"false", isInv=?"true":"false");
printf("%s:%02X vtx%d, %s, %s\n", cmdName, opcode, vtxId, isPrim?"true":"false", isInv?"true":"false");
#endif
BUF.push_back(FMT_OPCODE(opcode) | ((u32)isInv<<22) | ((u32)isPrim<<23) | (vtxId<<24));
g_isGeoShader = true;
GetDvleData()->isGeoShader = true;
return 0;
}
@ -856,11 +924,7 @@ DEF_COMMAND(formatcall)
ARG_TARGET(procName);
Relocation r;
r.instPos = BUF.size();
r.target = procName;
r.isProc = true;
g_relocs.push_back(r);
g_procRelocTable.push_back( std::make_pair(BUF.size(), procName) );
BUF.push_back(FMT_OPCODE(opcode));
@ -919,11 +983,8 @@ DEF_COMMAND(format2)
ARG_TARGET(targetName);
Relocation r;
r.instPos = BUF.size();
r.target = targetName;
r.isProc = opcode==MAESTRO_CALLC;
g_relocs.push_back(r);
relocTableType& rt = opcode==MAESTRO_CALLC ? g_procRelocTable : g_labelRelocTable;
rt.push_back( std::make_pair(BUF.size(), targetName) );
#ifdef DEBUG
printf("%s:%02X %s, %s\n", cmdName, opcode, condExp, targetName);
@ -971,11 +1032,8 @@ DEF_COMMAND(format3)
ARG_TARGET(targetName);
Relocation r;
r.instPos = BUF.size();
r.target = targetName;
r.isProc = opcode==MAESTRO_CALLU;
g_relocs.push_back(r);
relocTableType& rt = opcode==MAESTRO_CALLU ? g_procRelocTable : g_labelRelocTable;
rt.push_back( std::make_pair(BUF.size(), targetName) );
#ifdef DEBUG
printf("%s:%02X d%02X, %s\n", cmdName, opcode, regId, targetName);
@ -1185,21 +1243,20 @@ DEF_DIRECTIVE(alias)
return 0;
}
static inline int& getAllocVar(int type, int& bound)
static inline UniformAlloc& getAlloc(int type)
{
switch (type)
{
default:
case UTYPE_FVEC: bound = 0x80; return fvecUnifPos;
case UTYPE_IVEC: bound = 0x84; return ivecUnifPos;
case UTYPE_BOOL: bound = 0x98; return boolUnifPos;
case UTYPE_FVEC: return fvecAlloc;
case UTYPE_IVEC: return ivecAlloc;
case UTYPE_BOOL: return boolAlloc;
}
}
DEF_DIRECTIVE(uniform)
{
int bound;
int& uniformPos = getAllocVar(dirParam, bound);
UniformAlloc& alloc = getAlloc(dirParam);
for (;;)
{
@ -1222,19 +1279,55 @@ DEF_DIRECTIVE(uniform)
}
if (!validateIdentifier(argText))
return throwError("invalid uniform name: %s\n", argText);
if ((uniformPos+uSize) >= bound)
return throwError("not enough uniform registers: %s[%d]\n", argText, uSize);
if (g_uniformCount == MAX_UNIFORM)
return throwError("too many uniforms: %s[%d]\n", argText, uSize);
if (g_aliases.find(argText) != g_aliases.end())
return duplicateIdentifier(argText);
int uniformPos = -1;
// Find the uniform in the table
int i;
for (i = 0; i < g_uniformCount; i ++)
{
Uniform& uniform = g_uniformTable[i];
if (uniform.name == argText)
{
if (uniform.type != dirParam)
return throwError("mismatched uniform type: %s\n", argText);
if (uniform.size != uSize)
return throwError("uniform '%s' previously declared as having size %d\n", argText, uniform.size);
break;
}
}
// If not found, create it
if (i == g_uniformCount && uniformPos < 0)
{
if (g_uniformCount == MAX_UNIFORM)
return throwError("too many global uniforms: %s\n", argText);
uniformPos = alloc.AllocGlobal(uSize);
if (uniformPos < 0)
return throwError("not enough uniform space: %s[%d]\n", argText, uSize);
}
Uniform& uniform = g_uniformTable[g_uniformCount++];
uniform.name = argText;
uniform.pos = uniformPos;
uniform.size = uSize;
uniform.type = dirParam;
uniformPos += uSize;
if (*argText != '_')
{
DVLEData* dvle = GetDvleData();
// Add the uniform to the table
if (dvle->uniformCount == MAX_UNIFORM)
return throwError("too many referenced uniforms: %s\n", argText);
dvle->uniformTable[dvle->uniformCount++] = uniform; // Copy constructor
dvle->symbolSize += strlen(argText)+1;
}
g_aliases.insert( std::pair<std::string,int>(argText, uniform.pos | (DEFAULT_OPSRC<<8)) );
#ifdef DEBUG
@ -1246,8 +1339,8 @@ DEF_DIRECTIVE(uniform)
DEF_DIRECTIVE(const)
{
int bound;
int& uniformPos = getAllocVar(dirParam, bound);
DVLEData* dvle = GetDvleData();
UniformAlloc& alloc = getAlloc(dirParam);
NEXT_ARG_CPAREN(constName);
NEXT_ARG(arg0Text);
@ -1260,14 +1353,18 @@ DEF_DIRECTIVE(const)
*parenPos = 0;
arg3Text = trim_whitespace(arg3Text);
if (g_constantCount == MAX_CONSTANT || uniformPos>=bound)
return throwError("not enough space for constant\n");
if (g_aliases.find(constName) != g_aliases.end())
return duplicateIdentifier(constName);
Constant& ct = g_constantTable[g_constantCount++];
ct.regId = uniformPos++;
int uniformPos = alloc.AllocLocal(1);
if (uniformPos < 0)
return throwError("not enough space for local constant '%s'\n", constName);
if (dvle->constantCount == MAX_CONSTANT)
return throwError("too many local constants\n");
Constant& ct = dvle->constantTable[dvle->constantCount++];
ct.regId = uniformPos;
ct.type = dirParam;
if (dirParam == UTYPE_FVEC)
{
@ -1275,14 +1372,14 @@ DEF_DIRECTIVE(const)
ct.fparam[1] = atof(arg1Text);
ct.fparam[2] = atof(arg2Text);
ct.fparam[3] = atof(arg3Text);
g_constantSize += 4 + 4*4;
dvle->constantSize += 4 + 4*4;
} else if (dirParam == UTYPE_IVEC)
{
ct.iparam[0] = atoi(arg0Text) & 0xFF;
ct.iparam[1] = atoi(arg1Text) & 0xFF;
ct.iparam[2] = atoi(arg2Text) & 0xFF;
ct.iparam[3] = atoi(arg3Text) & 0xFF;
g_constantSize += 4 + 4;
dvle->constantSize += 4 + 4;
}
g_aliases.insert( std::pair<std::string,int>(constName, ct.regId | (DEFAULT_OPSRC<<8)) );
@ -1321,6 +1418,8 @@ static int parseOutType(const char* text)
DEF_DIRECTIVE(out)
{
DVLEData* dvle = GetDvleData();
NEXT_ARG_SPC(outName);
NEXT_ARG_SPC(outType);
ENSURE_NO_MORE_ARGS();
@ -1337,28 +1436,54 @@ DEF_DIRECTIVE(out)
if (sw < 0)
return throwError("invalid output mask: %s\n", dotPos);
}
int mask = maskFromSwizzling(sw);
int mask = maskFromSwizzling(sw, false);
int type = parseOutType(outType);
if (type < 0)
return throwError("invalid output type: %s\n", outType);
if (g_outputCount==MAX_OUTPUT)
if (dvle->outputCount==MAX_OUTPUT)
return throwError("too many outputs\n");
if (g_aliases.find(outName) != g_aliases.end())
return duplicateIdentifier(outName);
int oid = g_outputCount;
int oid = dvle->outputCount;
#ifdef DEBUG
printf("output %s <- o%d (%d:%X)\n", outName, oid, type, mask);
#endif
g_outputTable[g_outputCount++] = OUTPUT_MAKE(type, oid, mask);
dvle->outputTable[dvle->outputCount++] = OUTPUT_MAKE(type, oid, mask);
g_aliases.insert( std::pair<std::string,int>(outName, oid | (sw<<8)) );
return 0;
}
DEF_DIRECTIVE(entry)
{
DVLEData* dvle = GetDvleData();
NEXT_ARG_SPC(entrypoint);
ENSURE_NO_MORE_ARGS();
if (!validateIdentifier(entrypoint))
return throwError("invalid identifier: %s\n", entrypoint);
dvle->entrypoint = entrypoint;
return 0;
}
DEF_DIRECTIVE(nodvle)
{
DVLEData* dvle = GetDvleData();
ENSURE_NO_MORE_ARGS();
if (!dvle->nodvle)
{
dvle->nodvle = true;
g_totalDvleCount --;
}
}
static const cmdTableType dirTable[] =
{
DEC_DIRECTIVE(proc),
@ -1371,6 +1496,8 @@ static const cmdTableType dirTable[] =
DEC_DIRECTIVE2(constf, const, UTYPE_FVEC),
DEC_DIRECTIVE2(consti, const, UTYPE_IVEC),
DEC_DIRECTIVE(out),
DEC_DIRECTIVE(entry),
DEC_DIRECTIVE(nodvle),
{ NULL, NULL },
};

View File

@ -33,44 +33,49 @@ int usage(const char* prog)
{
fprintf(stderr,
"Usage:\n\n"
"%s shbinFile vshFile [hFile]\n", prog);
"%s output.shbin input1.pica input2.pica ...\n", prog);
return 0;
}
int main(int argc, char* argv[])
{
if (argc < 3 || argc > 4)
if (argc < 3)
return usage(argv[0]);
char* shbinFile = argv[1];
char* vshFile = argv[2];
char* hFile = argc > 3 ? argv[3] : NULL;
//char* hFile = argc > 3 ? argv[3] : NULL;
#ifdef WIN32
FixMinGWPath(shbinFile);
//FixMinGWPath(hFile);
#endif
int rc = 0;
for (int i = 2; i < argc; i ++)
{
char* vshFile = argv[i];
#ifdef WIN32
FixMinGWPath(vshFile);
FixMinGWPath(hFile);
#endif
char* sourceCode = StringFromFile(vshFile);
if (!sourceCode)
{
fprintf(stderr, "Cannot open input file!\n");
fprintf(stderr, "error: cannot open input file: %s\n");
return 1;
}
int rc = AssembleString(sourceCode, vshFile);
rc = AssembleString(sourceCode, vshFile);
free(sourceCode);
if (rc != 0)
return rc;
procTableIter mainIt = g_procTable.find("main");
if (mainIt == g_procTable.end())
{
fprintf(stderr, "Error: main proc not defined\n");
return 1;
}
rc = RelocateProduct();
if (rc != 0)
return rc;
FileClass f(shbinFile, "wb");
if (f.openerror())
@ -79,54 +84,39 @@ int main(int argc, char* argv[])
return 1;
}
u32 progSize = g_outputBuf.size();
u32 dvlpSize = 10*4 + progSize*4 + g_opdescCount*8;
// Write DVLB header
f.WriteWord(0x424C5644); // DVLB
f.WriteWord(1); // 1 DVLE
f.WriteWord(3*4 + 0x28); // offset to DVLE
f.WriteWord(g_totalDvleCount); // Number of DVLEs
u32 dvlpStart = f.Tell();
u32 shaderSize = g_outputBuf.size();
u32 paramStart = 0x28 + 0x40;
// Calculate and write DVLE offsets
u32 curOff = 2*4 + g_totalDvleCount*4 + dvlpSize;
for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end(); ++dvle)
{
if (dvle->nodvle) continue;
f.WriteWord(curOff);
curOff += 16*4; // Header
curOff += dvle->constantSize;
curOff += dvle->outputCount*8;
curOff += dvle->uniformCount*8;
curOff += dvle->symbolSize;
}
// Write DVLP header
f.WriteWord(0x504C5644); // DVLP
f.WriteWord(0); // version
f.WriteWord(paramStart); // offset to shader binary blob
f.WriteWord(shaderSize); // size of shader binary blob
paramStart += shaderSize*4;
f.WriteWord(paramStart); // offset to opdesc table
f.WriteWord(10*4); // offset to shader binary blob
f.WriteWord(progSize); // size of shader binary blob
f.WriteWord(10*4 + progSize*4); // offset to opdesc table
f.WriteWord(g_opdescCount); // number of opdescs
paramStart += g_opdescCount*8;
f.WriteWord(paramStart); // offset to symtable (TODO)
f.WriteWord(dvlpSize); // offset to symtable (TODO)
f.WriteWord(0); // ????
f.WriteWord(0); // ????
f.WriteWord(0); // ????
u32 dvleStart = f.Tell();
paramStart -= dvleStart - dvlpStart;
f.WriteWord(0x454C5644); // DVLE
f.WriteHword(0); // padding?
f.WriteHword(g_isGeoShader ? 1 : 0); // Shader type
f.WriteWord(mainIt->second.first); // offset to main
f.WriteWord(mainIt->second.first+mainIt->second.second); // offset to end of main
f.WriteWord(0); // ???
f.WriteWord(0); // ???
f.WriteWord(paramStart); // offset to constant table
f.WriteWord(g_constantCount); // size of constant table
paramStart += g_constantSize;
f.WriteWord(paramStart); // offset to label table (TODO)
f.WriteWord(0); // size of label table (TODO)
f.WriteWord(paramStart); // offset to output table
f.WriteWord(g_outputCount); // size of output table
paramStart += g_outputCount*8;
f.WriteWord(paramStart); // offset to uniform table
f.WriteWord(g_uniformCount); // size of uniform table
paramStart += g_uniformCount*8;
f.WriteWord(paramStart); // offset to symbol table
u32 temp = f.Tell();
f.WriteWord(0); // size of symbol table
// Write program
//for (u32 p : g_outputBuf)
for (outputBufIter it = g_outputBuf.begin(); it != g_outputBuf.end(); ++it)
f.WriteWord(*it);
@ -134,10 +124,38 @@ int main(int argc, char* argv[])
for (int i = 0; i < g_opdescCount; i ++)
f.WriteDword(g_opdescTable[i]);
// Write constants
for (int i = 0; i < g_constantCount; i ++)
// Write DVLEs
for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end(); ++dvle)
{
Constant& ct = g_constantTable[i];
if (dvle->nodvle) continue;
curOff = 16*4;
f.WriteWord(0x454C5644); // DVLE
f.WriteHword(0); // padding?
f.WriteHword(dvle->isGeoShader ? 1 : 0); // Shader type
f.WriteWord(dvle->entryStart); // offset to main
f.WriteWord(dvle->entryEnd); // offset to end of main
f.WriteWord(0); // ???
f.WriteWord(0); // ???
f.WriteWord(curOff); // offset to constant table
f.WriteWord(dvle->constantCount); // size of constant table
curOff += dvle->constantSize;
f.WriteWord(curOff); // offset to label table (TODO)
f.WriteWord(0); // size of label table (TODO)
f.WriteWord(curOff); // offset to output table
f.WriteWord(dvle->outputCount); // size of output table
curOff += dvle->outputCount*8;
f.WriteWord(curOff); // offset to uniform table
f.WriteWord(dvle->uniformCount); // size of uniform table
curOff += dvle->uniformCount*8;
f.WriteWord(curOff); // offset to symbol table
u32 temp = f.Tell();
f.WriteWord(dvle->symbolSize); // size of symbol table
// Write constants
for (int i = 0; i < dvle->constantCount; i ++)
{
Constant& ct = dvle->constantTable[i];
f.WriteHword(ct.type);
if (ct.type == UTYPE_FVEC)
{
@ -153,34 +171,30 @@ int main(int argc, char* argv[])
}
// Write outputs
for (int i = 0; i < g_outputCount; i ++)
f.WriteDword(g_outputTable[i]);
for (int i = 0; i < dvle->outputCount; i ++)
f.WriteDword(dvle->outputTable[i]);
// Write uniforms
size_t sp = 0;
for (int i = 0; i < g_uniformCount; i ++)
for (int i = 0; i < dvle->uniformCount; i ++)
{
Uniform& u = g_uniformTable[i];
Uniform& u = dvle->uniformTable[i];
size_t l = u.name.length()+1;
f.WriteWord(sp); sp += l;
f.WriteHword(u.pos-0x10);
f.WriteHword(u.pos+u.size-1-0x10);
}
// Write size of symbol table
u32 temp2 = f.Tell();
f.Seek(temp, SEEK_SET);
f.WriteWord(sp);
f.Seek(temp2, SEEK_SET);
// Write symbols
for (int i = 0; i < g_uniformCount; i ++)
for (int i = 0; i < dvle->uniformCount; i ++)
{
std::string& u = g_uniformTable[i].name;
std::string& u = dvle->uniformTable[i].name;
size_t l = u.length()+1;
f.WriteRaw(u.c_str(), l);
}
}
#if 0
if (hFile)
{
FILE* f2 = fopen(hFile, "w");
@ -213,6 +227,7 @@ int main(int argc, char* argv[])
fclose(f2);
}
#endif
return 0;
}