From c59f17e80fbbe436b7e3e4bd22160486a7fde19b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 3 May 2008 15:28:30 -0400 Subject: [PATCH] Report hardcoded constants in MOJOSHADER_parseData. --HG-- branch : trunk --- mojoshader.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++- mojoshader.h | 38 ++++++++++++++++++++ testparse.c | 34 ++++++++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) diff --git a/mojoshader.c b/mojoshader.c index 1d4e94f3..484ec853 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -228,6 +228,11 @@ typedef struct RegisterList struct RegisterList *next; } RegisterList; +typedef struct ConstantsList +{ + MOJOSHADER_constant constant; + struct ConstantsList *next; +} ConstantsList; // result modifiers. #define MOD_SATURATE 0x01 @@ -348,6 +353,8 @@ struct Context int cmps; RegisterList used_registers; RegisterList defined_registers; + int constant_count; + ConstantsList *constants; int uniform_count; RegisterList uniforms; int attribute_count; @@ -3594,9 +3601,22 @@ static int parse_args_TEX(Context *ctx) } // parse_args_TEX - // State machine functions... +static ConstantsList *alloc_constant_listitem(Context *ctx) +{ + ConstantsList *item = (ConstantsList *) Malloc(ctx, sizeof (ConstantsList)); + if (item == NULL) + return NULL; + + memset(&item->constant, '\0', sizeof (MOJOSHADER_constant)); + item->next = ctx->constants; + ctx->constants = item; + ctx->constant_count++; + + return item; +} // alloc_constant_listitem + static void state_DEF(Context *ctx) { const RegisterType regtype = ctx->dest_arg.regtype; @@ -3604,10 +3624,19 @@ static void state_DEF(Context *ctx) ctx->instruction_count--; // these don't increase your instruction count. + // !!! FIXME: fail if same register is defined twice. + if (regtype != REG_TYPE_CONST) fail(ctx, "DEF token using invalid register"); else + { + ConstantsList *item = alloc_constant_listitem(ctx); + item->constant.index = regnum; + item->constant.type = MOJOSHADER_UNIFORM_FLOAT; + memcpy(item->constant.value.f, ctx->dwords, + sizeof (item->constant.value.f)); set_defined_register(ctx, regtype, regnum); + } // else } // state_DEF static void state_DEFI(Context *ctx) @@ -3615,12 +3644,22 @@ static void state_DEFI(Context *ctx) const RegisterType regtype = ctx->dest_arg.regtype; const int regnum = ctx->dest_arg.regnum; + // !!! FIXME: fail if same register is defined twice. + ctx->instruction_count--; // these don't increase your instruction count. if (regtype != REG_TYPE_CONSTINT) fail(ctx, "DEFI token using invalid register"); else + { + ConstantsList *item = alloc_constant_listitem(ctx); + item->constant.index = regnum; + item->constant.type = MOJOSHADER_UNIFORM_INT; + memcpy(item->constant.value.i, ctx->dwords, + sizeof (item->constant.value.i)); + set_defined_register(ctx, regtype, regnum); + } // else } // state_DEFI static void state_DEFB(Context *ctx) @@ -3628,12 +3667,20 @@ static void state_DEFB(Context *ctx) const RegisterType regtype = ctx->dest_arg.regtype; const int regnum = ctx->dest_arg.regnum; + // !!! FIXME: fail if same register is defined twice. + ctx->instruction_count--; // these don't increase your instruction count. if (regtype != REG_TYPE_CONSTBOOL) fail(ctx, "DEFB token using invalid register"); else + { + ConstantsList *item = alloc_constant_listitem(ctx); + item->constant.index = regnum; + item->constant.type = MOJOSHADER_UNIFORM_BOOL; + item->constant.value.b = ctx->dwords[0] ? 1 : 0; set_defined_register(ctx, regtype, regnum); + } // else } // state_DEFB static void state_DCL(Context *ctx) @@ -4458,6 +4505,17 @@ static void free_output_list(MOJOSHADER_free f, void *d, OutputListNode *item) } // free_output_list +static void free_constants_list(MOJOSHADER_free f, void *d, ConstantsList *item) +{ + while (item != NULL) + { + ConstantsList *next = item->next; + f(item, d); + item = next; + } // while +} // free_constants_list + + static void destroy_context(Context *ctx) { if (ctx != NULL) @@ -4472,6 +4530,7 @@ static void destroy_context(Context *ctx) free_output_list(f, d, ctx->mainline_intro.head.next); free_output_list(f, d, ctx->mainline.head.next); free_output_list(f, d, ctx->ignore.head.next); + free_constants_list(f, d, ctx->constants); free_reglist(f, d, ctx->used_registers.next); free_reglist(f, d, ctx->defined_registers.next); free_reglist(f, d, ctx->uniforms.next); @@ -4593,6 +4652,33 @@ static MOJOSHADER_uniform *build_uniforms(Context *ctx) } // build_uniforms +static MOJOSHADER_constant *build_constants(Context *ctx) +{ + const size_t len = sizeof (MOJOSHADER_constant) * ctx->constant_count; + MOJOSHADER_constant *retval = (MOJOSHADER_constant *) Malloc(ctx, len); + + if (retval != NULL) + { + ConstantsList *item = ctx->constants; + int i; + + for (i = 0; i < ctx->constant_count; i++) + { + if (item == NULL) + { + fail(ctx, "BUG: mismatched constant list and count"); + break; + } // if + + memcpy(&retval[i], &item->constant, sizeof (MOJOSHADER_constant)); + item = item->next; + } // for + } // if + + return retval; +} // build_constants + + static MOJOSHADER_sampler *build_samplers(Context *ctx) { const size_t len = sizeof (MOJOSHADER_sampler) * ctx->sampler_count; @@ -4718,6 +4804,7 @@ static MOJOSHADER_attribute *build_attributes(Context *ctx, int *_count) static MOJOSHADER_parseData *build_parsedata(Context *ctx) { char *output = NULL; + MOJOSHADER_constant *constants = NULL; MOJOSHADER_uniform *uniforms = NULL; MOJOSHADER_attribute *attributes = NULL; MOJOSHADER_sampler *samplers = NULL; @@ -4733,6 +4820,9 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx) if (!isfail(ctx)) output = build_output(ctx); + if (!isfail(ctx)) + constants = build_constants(ctx); + if (!isfail(ctx)) uniforms = build_uniforms(ctx); @@ -4748,6 +4838,7 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx) int i; Free(ctx, output); + Free(ctx, constants); if (uniforms != NULL) { @@ -4784,6 +4875,8 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx) retval->minor_ver = (int) ctx->minor_ver; retval->uniform_count = ctx->uniform_count; retval->uniforms = uniforms; + retval->constant_count = ctx->constant_count; + retval->constants = constants; retval->attribute_count = attribute_count; retval->attributes = attributes; retval->sampler_count = ctx->sampler_count; @@ -4945,6 +5038,9 @@ void MOJOSHADER_freeParseData(const MOJOSHADER_parseData *_data) if (data->output != NULL) // check for NULL in case of dumb free() impl. f((void *) data->output, d); + if (data->constants != NULL) + f((void *) data->constants, d); + if (data->uniforms != NULL) { for (i = 0; i < data->uniform_count; i++) diff --git a/mojoshader.h b/mojoshader.h index 4cb2ab6d..4172834f 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -94,6 +94,29 @@ typedef struct const char *name; } MOJOSHADER_uniform; +/* + * These are the constants defined in a shader. These are data values + * hardcoded in a shader (with the DEF, DEFI, DEFB instructions), which + * override your Uniforms. This data is largely for informational purposes, + * since they are compiled in and can't be changed, like Uniforms can be. + * These integers are register indexes. So if index==6 and + * type==MOJOSHADER_UNIFORM_FLOAT, that means we'd expect a 4-float vector + * to be specified for what would be register "c6" in D3D assembly language, + * before drawing with the shader. + * (value) is the value of the constant, unioned by type. + */ +typedef struct +{ + MOJOSHADER_uniformType type; + int index; + union + { + float f[4]; /* if type==MOJOSHADER_UNIFORM_FLOAT */ + int i[4]; /* if type==MOJOSHADER_UNIFORM_INT */ + int b; /* if type==MOJOSHADER_UNIFORM_BOOL */ + } value; +} MOJOSHADER_constant; + /* * Data types for samplers. See MOJOSHADER_sampler for more information. */ @@ -232,6 +255,21 @@ typedef struct */ MOJOSHADER_uniform *uniforms; + /* + * The number of elements pointed to by (constants). + */ + int constant_count; + + /* + * (constant_count) elements of data that specify constants used in + * this shader. See discussion on MOJOSHADER_constant for details. + * This can be NULL on error or if (constant_count) is zero. + * This is largely informational: constants are hardcoded into a shader. + * The constants that you can set like parameters are in the "uniforms" + * list. + */ + MOJOSHADER_constant *constants; + /* * The number of elements pointed to by (samplers). */ diff --git a/testparse.c b/testparse.c index c6de92df..de8ae277 100644 --- a/testparse.c +++ b/testparse.c @@ -95,6 +95,40 @@ static int do_parse(const unsigned char *buf, const int len, const char *prof) } // for } // else + printf("CONSTANTS:"); + if (pd->constant_count == 0) + printf(" (none.)\n"); + else + { + int i; + printf("\n"); + for (i = 0; i < pd->constant_count; i++) + { + static const char *typenames[] = { "float", "int", "bool" }; + const MOJOSHADER_constant *c = &pd->constants[i]; + printf(" * %d: %s (", c->index, typenames[(int) c->type]); + if (c->type == MOJOSHADER_UNIFORM_FLOAT) + { + printf("%f %f %f %f", c->value.f[0], c->value.f[1], + c->value.f[2], c->value.f[3]); + } // if + else if (c->type == MOJOSHADER_UNIFORM_INT) + { + printf("%d %d %d %d", c->value.i[0], c->value.i[1], + c->value.i[2], c->value.i[3]); + } // else if + else if (c->type == MOJOSHADER_UNIFORM_BOOL) + { + printf("%s", c->value.b ? "true" : "false"); + } // else if + else + { + printf("???"); + } // else + printf(")\n"); + } // for + } // else + printf("UNIFORMS:"); if (pd->uniform_count == 0) printf(" (none.)\n");