Skip to content

Commit

Permalink
Report hardcoded constants in MOJOSHADER_parseData.
Browse files Browse the repository at this point in the history
--HG--
branch : trunk
  • Loading branch information
icculus committed May 3, 2008
1 parent c7fc7ec commit c59f17e
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 1 deletion.
98 changes: 97 additions & 1 deletion mojoshader.c
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -3594,46 +3601,86 @@ 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;
const int regnum = ctx->dest_arg.regnum;

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)
{
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)
{
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)
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -4748,6 +4838,7 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx)
int i;

Free(ctx, output);
Free(ctx, constants);

if (uniforms != NULL)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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++)
Expand Down
38 changes: 38 additions & 0 deletions mojoshader.h
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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).
*/
Expand Down
34 changes: 34 additions & 0 deletions testparse.c
Expand Up @@ -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");
Expand Down

0 comments on commit c59f17e

Please sign in to comment.