From 2d3e8a4c8489e3c6d8f159c2c6897abf1c098beb Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 31 May 2011 16:01:10 -0400 Subject: [PATCH] Filled in and fixed some stuff in the Effect parser. This code is all nasty, because I'm planning to rewrite it later. --- mojoshader.h | 18 ++++++ mojoshader_effects.c | 138 ++++++++++++++++++++++++++++++++----------- utils/testparse.c | 9 +++ 3 files changed, 132 insertions(+), 33 deletions(-) diff --git a/mojoshader.h b/mojoshader.h index f0707e57..1caed849 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -699,6 +699,12 @@ void MOJOSHADER_freeParseData(const MOJOSHADER_parseData *data); /* Effects interface... */ /* !!! FIXME: THIS API IS NOT STABLE YET! */ +typedef struct MOJOSHADER_effectParam +{ + const char *name; + const char *semantic; +} MOJOSHADER_effectParam; + typedef struct MOJOSHADER_effectState { unsigned int type; @@ -754,6 +760,18 @@ typedef struct MOJOSHADER_effect */ const char *profile; + /* + * The number of params pointed to by (params). + */ + int param_count; + + /* + * (param_count) elements of data that specify parameter bind points for + * this effect. + * This can be NULL on error or if (param_count) is zero. + */ + MOJOSHADER_effectParam *params; + /* * The number of elements pointed to by (techniques). */ diff --git a/mojoshader_effects.c b/mojoshader_effects.c index 1aab1f4f..5b1fd1c4 100644 --- a/mojoshader_effects.c +++ b/mojoshader_effects.c @@ -217,11 +217,14 @@ const MOJOSHADER_effect *MOJOSHADER_parseEffect(const char *profile, if (len < 8) goto parseEffect_unexpectedEOF; + const uint8 *base = NULL; if (readui32(&ptr, &len) != 0xFEFF0901) // !!! FIXME: is this always magic? goto parseEffect_notAnEffectsFile; else { const uint32 offset = readui32(&ptr, &len); + base = ptr; +//printf("base offset == %u\n", offset); if (offset > len) goto parseEffect_unexpectedEOF; ptr += offset; @@ -236,27 +239,61 @@ const MOJOSHADER_effect *MOJOSHADER_parseEffect(const char *profile, const uint32 numparams = readui32(&ptr, &len); const uint32 numtechniques = readui32(&ptr, &len); - readui32(&ptr, &len); // !!! FIXME: there are 8 unknown bytes here. - readui32(&ptr, &len); + readui32(&ptr, &len); // !!! FIXME: there are 8 unknown bytes here. Annotations? + /*const uint32 numobjects = */ readui32(&ptr, &len); - for (i = 0; i < numparams; i++) + if (numparams > 0) { - if (len < 16) - goto parseEffect_unexpectedEOF; + siz = sizeof (MOJOSHADER_effectParam) * numparams; + retval->params = (MOJOSHADER_effectParam *) m(siz, d); + if (retval->params == NULL) + goto parseEffect_outOfMemory; + memset(retval->params, '\0', siz); - /*const uint32 startoffset = */ readui32(&ptr, &len); - /*const uint32 endoffset = */ readui32(&ptr, &len); - readui32(&ptr, &len); // !!! FIXME: don't know what this is. - const uint32 numannos = readui32(&ptr, &len); - for (j = 0; j < numannos; j++) + retval->param_count = numparams; + + for (i = 0; i < numparams; i++) { - if (len < 8) + if (len < 16) goto parseEffect_unexpectedEOF; - // !!! FIXME: parse annotations. - readui32(&ptr, &len); - readui32(&ptr, &len); + + const uint32 typeoffset = readui32(&ptr, &len); + const uint32 valoffset = readui32(&ptr, &len); + const uint32 flags = readui32(&ptr, &len); + const uint32 numannos = readui32(&ptr, &len); + for (j = 0; j < numannos; j++) + { + if (len < 8) + goto parseEffect_unexpectedEOF; + // !!! FIXME: parse annotations. + readui32(&ptr, &len); + readui32(&ptr, &len); + } // for + + const uint8 *typeptr = base + typeoffset; + unsigned int typelen = 9999999; // !!! FIXME + const uint32 paramtype = readui32(&typeptr, &typelen); + const uint32 paramclass = readui32(&typeptr, &typelen); + const uint32 paramname = readui32(&typeptr, &typelen); + const uint32 paramsemantic = readui32(&typeptr, &typelen); + + // !!! FIXME: sanity checks! + const char *namestr = ((const char *) base) + paramname; + const char *semstr = ((const char *) base) + paramsemantic; + uint32 len; + char *strptr; + len = *((const uint32 *) namestr); + strptr = (char *) m(len + 1, d); + memcpy(strptr, namestr + 4, len); + strptr[len] = '\0'; + retval->params[i].name = strptr; + len = *((const uint32 *) semstr); + strptr = (char *) m(len + 1, d); + memcpy(strptr, semstr + 4, len); + strptr[len] = '\0'; + retval->params[i].semantic = strptr; } // for - } // for + } // if uint32 numshaders = 0; // we'll calculate this later. @@ -279,23 +316,37 @@ const MOJOSHADER_effect *MOJOSHADER_parseEffect(const char *profile, MOJOSHADER_effectTechnique *technique = &retval->techniques[i]; - // !!! FIXME: is this always 12? - const uint32 nameoffset = readui32(&ptr, &len) + 12; - readui32(&ptr, &len); // !!! FIXME: don't know what this field does. + const uint32 nameoffset = readui32(&ptr, &len); + const uint32 numannos = readui32(&ptr, &len); const uint32 numpasses = readui32(&ptr, &len); if (nameoffset >= _len) goto parseEffect_unexpectedEOF; - if (numpasses > 0) + if (numannos > 0) { - // !!! FIXME: verify this doesn't go past EOF looking for a null. - siz = strlen(((const char *) buf) + nameoffset) + 1; - technique->name = (char *) m(siz, d); - if (technique->name == NULL) - goto parseEffect_outOfMemory; - strcpy((char *) technique->name, ((const char *) buf) + nameoffset); + // !!! FIXME: expose these to the caller? + for (j = 0; j < numannos; j++) + { + if (len < 8) + goto parseEffect_unexpectedEOF; + readui32(&ptr, &len); // typedef offset + readui32(&ptr, &len); // value offset + } // for + } // if + + // !!! FIXME: verify this doesn't go past EOF looking for a null. + { + const char *namestr = ((char *) base) + nameoffset; + uint32 len = *((const uint32 *) namestr); + char *strptr = (char *) m(len + 1, d); + memcpy(strptr, namestr + 4, len); + strptr[len] = '\0'; + technique->name = strptr; + } + if (numpasses > 0) + { technique->pass_count = numpasses; siz = sizeof (MOJOSHADER_effectPass) * numpasses; @@ -311,20 +362,34 @@ const MOJOSHADER_effect *MOJOSHADER_parseEffect(const char *profile, MOJOSHADER_effectPass *pass = &technique->passes[j]; - // !!! FIXME: is this always 12? - const uint32 passnameoffset = readui32(&ptr, &len) + 12; - readui32(&ptr, &len); // !!! FIXME: don't know what this field does. + const uint32 passnameoffset = readui32(&ptr, &len); + const uint32 numannos = readui32(&ptr, &len); const uint32 numstates = readui32(&ptr, &len); if (passnameoffset >= _len) goto parseEffect_unexpectedEOF; // !!! FIXME: verify this doesn't go past EOF looking for a null. - siz = strlen(((const char *) buf) + passnameoffset) + 1; - pass->name = (char *) m(siz, d); - if (pass->name == NULL) - goto parseEffect_outOfMemory; - strcpy((char *) pass->name, ((const char *) buf) + passnameoffset); + { + const char *namestr = ((char *) base) + passnameoffset; + uint32 len = *((const uint32 *) namestr); + char *strptr = (char *) m(len + 1, d); + memcpy(strptr, namestr + 4, len); + strptr[len] = '\0'; + pass->name = strptr; + } + + if (numannos > 0) + { + for (k = 0; k < numannos; k++) + { + if (len < 8) + goto parseEffect_unexpectedEOF; + // !!! FIXME: do something with this. + readui32(&ptr, &len); + readui32(&ptr, &len); + } // for + } // if if (numstates > 0) { @@ -503,6 +568,13 @@ void MOJOSHADER_freeEffect(const MOJOSHADER_effect *_effect) f((void *) effect->profile, d); + for (i = 0; i < effect->param_count; i++) + { + f((void *) effect->params[i].name, d); + f((void *) effect->params[i].semantic, d); + } // for + f(effect->params, d); + for (i = 0; i < effect->technique_count; i++) { MOJOSHADER_effectTechnique *technique = &effect->techniques[i]; diff --git a/utils/testparse.c b/utils/testparse.c index 40c1dbfc..751541b4 100644 --- a/utils/testparse.c +++ b/utils/testparse.c @@ -400,6 +400,15 @@ static void print_effect(const char *fname, const MOJOSHADER_effect *effect, const MOJOSHADER_effectTechnique *technique = effect->techniques; const MOJOSHADER_effectTexture *texture = effect->textures; const MOJOSHADER_effectShader *shader = effect->shaders; + const MOJOSHADER_effectParam *param = effect->params; + + for (i = 0; i < effect->param_count; i++, param++) + { + INDENT(); + printf("PARAM #%d '%s' -> '%s'\n", i, param->name, param->semantic); + } // for + + printf("\n"); for (i = 0; i < effect->technique_count; i++, technique++) {