diff --git a/example.vsh b/example.vsh index 8e11978..29cf324 100644 --- a/example.vsh +++ b/example.vsh @@ -2,10 +2,10 @@ ; Also serves as an example of picasso syntax ; Uniforms -.uniform projMtx[4], mdlvMtx[4] +.fvec projMtx[4], mdlvMtx[4] ; Constants -.const myconst(0.0, 1.0, -1.0, 0.0) +.constf myconst(0.0, 1.0, -1.0, 0.0) .alias zeros myconst.xxxx .alias ones myconst.yyyy .alias negones myconst.zzzz diff --git a/source/picasso.h b/source/picasso.h index cea688c..e046ea0 100644 --- a/source/picasso.h +++ b/source/picasso.h @@ -44,6 +44,7 @@ enum #define OPDESC_MASK_D12 OPDESC_MAKE(0xF, 0x1FF, 0x1FF, 0) #define OPDESC_MASK_D1 OPDESC_MAKE(0xF, 0x1FF, 0, 0) #define OPDESC_MASK_1 OPDESC_MAKE(0, 0x1FF, 0, 0) +#define OPDESC_MASK_12 OPDESC_MAKE(0, 0x1FF, 0x1FF, 0) typedef std::vector outputBufType; typedef outputBufType::iterator outputBufIter; @@ -77,10 +78,18 @@ extern int g_opdescTable[MAX_OPDESC]; extern int g_opdeskMasks[MAX_OPDESC]; // used to keep track of used bits extern int g_opdescCount; +enum +{ + UTYPE_BOOL = 0, + UTYPE_IVEC, + UTYPE_FVEC, +}; + struct Uniform { const char* name; int pos, size; + int type; }; #define MAX_UNIFORM 0x60 @@ -103,12 +112,18 @@ extern int g_outputCount; struct Constant { int regId; - float param[4]; + int type; + union + { + float fparam[4]; + u8 iparam[4]; + }; }; #define MAX_CONSTANT 0x60 extern Constant g_constantTable[MAX_CONSTANT]; extern int g_constantCount; +extern size_t g_constantSize; typedef std::pair procedure; // position, size typedef std::pair relocation; diff --git a/source/picasso_assembler.cpp b/source/picasso_assembler.cpp index de086ba..3fd6ee6 100644 --- a/source/picasso_assembler.cpp +++ b/source/picasso_assembler.cpp @@ -18,10 +18,13 @@ int g_opdescMasks[MAX_OPDESC]; Uniform g_uniformTable[MAX_UNIFORM]; int g_uniformCount; -static int uniformPos = 0x20; +static int fvecUnifPos = 0x20; +static int ivecUnifPos = 0x80; +static int boolUnifPos = 0x88; Constant g_constantTable[MAX_CONSTANT]; int g_constantCount; +size_t g_constantSize; u64 g_outputTable[MAX_OUTPUT]; int g_outputCount; @@ -253,11 +256,14 @@ typedef struct { #name, cmd_##fun, MAESTRO_##name } #define DEF_DIRECTIVE(name) \ - static int dir_##name(const char* cmdName, int _unused) + static int dir_##name(const char* cmdName, int dirParam) #define DEC_DIRECTIVE(name) \ { #name, dir_##name, 0 } +#define DEC_DIRECTIVE2(name, fun, opc) \ + { #name, dir_##fun, opc } + static int ensureNoMoreArgs() { return nextArg() ? throwError("too many parameters\n") : 0; @@ -390,7 +396,7 @@ static int findOrAddOpdesc(int& out, int opdesc, int mask) static inline bool isregp(int x) { x = tolower(x); - return x=='o' || x=='v' || x=='r' || x=='c'; + return x=='o' || x=='v' || x=='r' || x=='c' || x=='i' || x=='b'; } static inline int convertIdxRegName(const char* reg) @@ -492,10 +498,20 @@ static int parseReg(char* pos, int& outReg, int& outSw, int* idxType = NULL) if (outReg < 0x10 || outReg >= 0x20) return throwError("invalid temporary register: %s(%d)\n", pos); break; - case 'c': // Vector uniform registers + case 'c': // Floating-point vector uniform registers outReg += 0x20; if (outReg < 0x20 || outReg >= 0x80) - return throwError("invalid vector uniform register: %s(%d)\n", pos); + return throwError("invalid floating-point vector uniform register: %s(%d)\n", pos); + break; + case 'i': // Integer vector uniforms + outReg += 0x80; + if (outReg < 0x80 || outReg >= 0x88) + return throwError("invalid integer vector uniform register: %s(%d)\n", pos); + break; + case 'b': // Boolean uniforms + outReg += 0x88; + if (outReg < 0x88 || outReg >= 0x98) + return throwError("invalid boolean uniform register: %s(%d)\n", pos); break; } outReg += regOffset; @@ -696,8 +712,22 @@ DEF_DIRECTIVE(alias) return 0; } +static inline int& getAllocVar(int type, int& bound) +{ + switch (type) + { + default: + case UTYPE_FVEC: bound = 0x80; return fvecUnifPos; + case UTYPE_IVEC: bound = 0x88; return ivecUnifPos; + case UTYPE_BOOL: bound = 0x98; return boolUnifPos; + } +} + DEF_DIRECTIVE(uniform) { + int bound; + int& uniformPos = getAllocVar(dirParam, bound); + for (;;) { char* argText = nextArg(); @@ -719,7 +749,7 @@ DEF_DIRECTIVE(uniform) } if (!validateIdentifier(argText)) return throwError("invalid uniform name: %s\n", argText); - if ((uniformPos+uSize) >= 0x80) + 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); @@ -730,6 +760,7 @@ DEF_DIRECTIVE(uniform) uniform.name = argText; uniform.pos = uniformPos; uniform.size = uSize; + uniform.type = dirParam; uniformPos += uSize; g_aliases.insert( std::pair(argText, uniform.pos | (DEFAULT_OPSRC<<8)) ); @@ -742,6 +773,9 @@ DEF_DIRECTIVE(uniform) DEF_DIRECTIVE(const) { + int bound; + int& uniformPos = getAllocVar(dirParam, bound); + NEXT_ARG_CPAREN(constName); NEXT_ARG(arg0Text); NEXT_ARG(arg1Text); @@ -753,7 +787,7 @@ DEF_DIRECTIVE(const) *parenPos = 0; arg3Text = trim_whitespace(arg3Text); - if (g_constantCount == MAX_CONSTANT || uniformPos>=0x80) + if (g_constantCount == MAX_CONSTANT || uniformPos>=bound) return throwError("not enough space for constant\n"); if (g_aliases.find(constName) != g_aliases.end()) @@ -761,15 +795,30 @@ DEF_DIRECTIVE(const) Constant& ct = g_constantTable[g_constantCount++]; ct.regId = uniformPos++; - ct.param[0] = atof(arg0Text); - ct.param[1] = atof(arg1Text); - ct.param[2] = atof(arg2Text); - ct.param[3] = atof(arg3Text); + ct.type = dirParam; + if (dirParam == UTYPE_FVEC) + { + ct.fparam[0] = atof(arg0Text); + ct.fparam[1] = atof(arg1Text); + ct.fparam[2] = atof(arg2Text); + ct.fparam[3] = atof(arg3Text); + g_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; + } g_aliases.insert( std::pair(constName, ct.regId | (DEFAULT_OPSRC<<8)) ); #ifdef DEBUG - printf("constant %s(%f, %f, %f, %f) @ d%02X\n", constName, ct.param[0], ct.param[1], ct.param[2], ct.param[3], ct.regId); + if (dirParam == UTYPE_FVEC) + printf("constant %s(%f, %f, %f, %f) @ d%02X\n", constName, ct.fparam[0], ct.fparam[1], ct.fparam[2], ct.fparam[3], ct.regId); + else if (dirParam == UTYPE_IVEC) + printf("constant %s(%u, %u, %u, %u) @ d%02X\n", constName, ct.iparam[0], ct.iparam[1], ct.iparam[2], ct.iparam[3], ct.regId); #endif return 0; }; @@ -834,8 +883,11 @@ static const cmdTableType dirTable[] = DEC_DIRECTIVE(proc), DEC_DIRECTIVE(end), DEC_DIRECTIVE(alias), - DEC_DIRECTIVE(uniform), - DEC_DIRECTIVE(const), + DEC_DIRECTIVE2(fvec, uniform, UTYPE_FVEC), + DEC_DIRECTIVE2(ivec, uniform, UTYPE_IVEC), + DEC_DIRECTIVE2(bool, uniform, UTYPE_BOOL), + DEC_DIRECTIVE2(constf, const, UTYPE_FVEC), + DEC_DIRECTIVE2(consti, const, UTYPE_IVEC), DEC_DIRECTIVE(out), { NULL, NULL }, }; diff --git a/source/picasso_frontend.cpp b/source/picasso_frontend.cpp index 8f6ca01..f71a365 100644 --- a/source/picasso_frontend.cpp +++ b/source/picasso_frontend.cpp @@ -112,7 +112,7 @@ int main(int argc, char* argv[]) f.WriteWord(0); // ??? f.WriteWord(paramStart); // offset to constant table f.WriteWord(g_constantCount); // size of constant table - paramStart += g_constantCount*0x14; + 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 @@ -141,11 +141,18 @@ int main(int argc, char* argv[]) for (int i = 0; i < g_constantCount; i ++) { Constant& ct = g_constantTable[i]; - f.WriteHword(0); - f.WriteByte(ct.regId-0x20); - f.WriteByte(0); - for (int j = 0; j < 4; j ++) - f.WriteWord(f32tof24(ct.param[j])); + f.WriteHword(ct.type); + if (ct.type == UTYPE_FVEC) + { + f.WriteHword(ct.regId-0x20); + for (int j = 0; j < 4; j ++) + f.WriteWord(f32tof24(ct.fparam[j])); + } else if (ct.type == UTYPE_IVEC) + { + f.WriteHword(ct.regId-0x80); + for (int j = 0; j < 4; j ++) + f.WriteByte(ct.iparam[j]); + } } // Write outputs