From d3f911b3736d3d27a7e0da0ecbc61d94b1e858a3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 19 Dec 2008 00:05:20 -0500 Subject: [PATCH] Allow errors to specify post-processing problems. This can happen if the entire shader is valid but we have a problem when parsing uniforms, etc. --- mojoshader.c | 27 +++++--- mojoshader.h | 7 ++- mojoshader_assembler.c | 138 ++++++++++++++++++++++++++++++++++++++--- mojoshader_internal.h | 7 +++ 4 files changed, 161 insertions(+), 18 deletions(-) diff --git a/mojoshader.c b/mojoshader.c index 33097eb8..6064429c 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -164,7 +164,7 @@ struct Context const uint32 *orig_tokens; const uint32 *tokens; uint32 tokencount; - int started_parsing; + MOJOSHADER_parsePhase parse_phase; const MOJOSHADER_swizzle *swizzles; unsigned int swizzles_count; OutputList *output; @@ -6712,6 +6712,7 @@ static Context *build_context(const char *profile, ctx->ignore.tail = &ctx->ignore.head; ctx->output = &ctx->mainline; ctx->last_address_reg_component = -1; + ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED; const int profileid = find_profile_id(profile); ctx->profileid = profileid; @@ -7155,16 +7156,25 @@ static MOJOSHADER_parseData *build_parsedata(Context *ctx) Free(ctx, samplers); } // if - if (ctx->started_parsing) - retval->error_position = (ctx->tokens - ctx->orig_tokens) * sizeof (uint32); - else - retval->error_position = -1; + switch (ctx->parse_phase) + { + case MOJOSHADER_PARSEPHASE_NOTSTARTED: + retval->error_position = -2; + break; + case MOJOSHADER_PARSEPHASE_WORKING: + retval->error_position = (ctx->tokens - ctx->orig_tokens) * sizeof (uint32); + break; + case MOJOSHADER_PARSEPHASE_DONE: + retval->error_position = -1; + break; + } // switch + retval->error = ctx->failstr; // we recycle. :) ctx->failstr = NULL; // don't let this get free()'d too soon. } // if else { - retval->error_position = -2; + retval->error_position = -3; retval->profile = ctx->profile->name; retval->output = output; retval->output_len = ctx->output_len; @@ -7375,7 +7385,7 @@ const MOJOSHADER_parseData *MOJOSHADER_parse(const char *profile, // Version token always comes first. if (!isfail(ctx)) { - ctx->started_parsing = 1; + ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING; rc = parse_version_token(ctx, profile); } // if @@ -7396,7 +7406,10 @@ const MOJOSHADER_parseData *MOJOSHADER_parse(const char *profile, } // while if (!isfail(ctx)) + { + ctx->parse_phase = MOJOSHADER_PARSEPHASE_DONE; process_definitions(ctx); + } // if if (!isfail(ctx)) ctx->profile->finalize_emitter(ctx); diff --git a/mojoshader.h b/mojoshader.h index 704b0168..916b7720 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -251,9 +251,10 @@ typedef struct MOJOSHADER_parseData */ const char *error; - /* !!! FIXME: needs a -3 for post-processing. - * Position of error, if there is one. Will be -2 if there was no - * error, and -1 if there was an error before processing started. If >= 0, + /* + * Position of error, if there is one. Will be -3 if there was no + * error, -2 if there was an error before processing started, and + * -1 if there was an error during final processing. If >= 0, * MOJOSHADER_parse() sets this to the byte offset (starting at zero) into * the bytecode you supplied, and MOJOSHADER_assemble() sets this to a * a line number in the source code you supplied (starting at one). diff --git a/mojoshader_assembler.c b/mojoshader_assembler.c index 89a4f8c3..86e244ca 100644 --- a/mojoshader_assembler.c +++ b/mojoshader_assembler.c @@ -35,7 +35,7 @@ struct Context void *malloc_data; const char *failstr; TokenizerContext tctx; - int started_parsing; + MOJOSHADER_parsePhase parse_phase; MOJOSHADER_shaderType shader_type; uint8 major_ver; uint8 minor_ver; @@ -1620,6 +1620,7 @@ static Context *build_context(const char *source, MOJOSHADER_malloc m, ctx->malloc = m; ctx->free = f; ctx->malloc_data = d; + ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED; ctx->tctx.source = source; ctx->tctx.linenum = 1; @@ -1661,15 +1662,138 @@ static const MOJOSHADER_parseData *build_failed_assembly(Context *ctx) retval->error = ctx->failstr; // we recycle. :) ctx->failstr = NULL; // don't let this get free()'d too soon. - if (ctx->started_parsing) - retval->error_position = ctx->tctx.linenum; - else - retval->error_position = -1; + switch (ctx->parse_phase) + { + case MOJOSHADER_PARSEPHASE_NOTSTARTED: + retval->error_position = -2; + break; + case MOJOSHADER_PARSEPHASE_WORKING: + retval->error_position = ctx->tctx.linenum; + break; + case MOJOSHADER_PARSEPHASE_DONE: + retval->error_position = -1; + break; + } // switch return retval; } // build_failed_assembly +typedef struct CTabTypeInfo +{ + uint16 parameter_class; + uint16 parameter_type; + uint16 rows; + uint16 columns; + uint16 elements; + uint16 structMembers; + uint32 structMemberInfo; +} CTabTypeInfo; + + +FUCK THIS CODE. +static void output_ctab(Context *ctx, const MOJOSHADER_symbol *symbols, + unsigned int symbol_count) +{ + if (symbol_count == 0) + return; + + unsigned int i; + uint8 *bytes = NULL; + const char *creator = "MojoShader revision " MOJOSHADER_CHANGESET; + const size_t creatorlen = strlen(creator) + 1; + add_ctab_bytes(ctx, &bytes, &offset, creator, creatorlen); + add_ctab_bytes(ctx, &bytes, &offset, "", 1); // !!! FIXME: target + + // build all the unique D3DXSHADER_TYPEINFO structs into the bytes. + CTabTypeInfo *tinfo; + tinfo = (CTabTypeInfo *) Malloc(sizeof (CTabTypeInfo) * symbol_count); + if (tinfo == NULL) + { + Free(ctx, bytes); + return; + } // if + + for (i = 0; i < symbol_count; i++) + { + // !!! FIXME: struct packing! + tinfo[i].parameter_class = SWAP16(symbols[i].parameter_class); + tinfo[i].parameter_type = SWAP16(symbols[i].parameter_type); + tinfo[i].rows = SWAP16(symbols[i].rows); + tinfo[i].columns = SWAP16(symbols[i].columns); + tinfo[i].elements = SWAP16(symbols[i].elements); + tinfo[i].structMembers = SWAP16(symbols[i].structMembers); + tinfo[i].structMembersInfo = SWAP32(0); // !!! FIXME: points to DWORD name, DWORD typeinfo + add_ctab_bytes(ctx, &bytes, &offset, &tinfo[i], sizeof (tinfo[i])); + } // for + + + uint8 ctab = sdfkjsldkfjsdlkf; + uint32 *table = (uint32 *) ctab; + uint32 offset = CTAB_SIZE + (CINFO_SIZE * symbol_count); + uint8 *data = ctab + offset + sizeof (uint32); + union { uint8 *ui8; uint16 *ui16; uint32 *ui32; } info; + info.ui8 = ctab + CTAB_SIZE + sizeof (uint32); + + *(table++) = SWAP32(CTAB_ID); + *(table++) = SWAP32(28); + *(table++) = SWAP32(find_ctab_bytes(ctx, bytes, creator, creatorlen)); + *(table++) = SWAP32(ctx->version_token); + *(table++) = SWAP32(((uint32) symbol_count)); + *(table++) = SWAP32(CTAB_SIZE); // info array right after table. + *(table++) = SWAP32(0); + *(table++) = SWAP32(find_ctab_bytes(ctx, bytes, "", 1)); // !!! FIXME: target? + + assert( ((uint8 *) table) == info.ui8 ); + for (i = 0; i < symbol_count; i++) + { + const char *name = symbols[i].name; + const size_t namelen = strlen(symbols[i].name) + 1; + add_ctab_bytes(bytes, &offset, name, namelen); + *(info.ui32++) = SWAP32(add_ctab_string(ctx, &data, &offset, symbols[i].name)); + *(info.ui16++) = SWAP16((uint16) symbols[i].register_set); + *(info.ui16++) = SWAP16((uint16) symbols[i].register_index); + *(info.ui16++) = SWAP16((uint16) symbols[i].register_count); + *(info.ui16++) = SWAP16(0); // reserved + + MOJOSHADER_symbolClass parameter_class; + MOJOSHADER_symbolType parameter_type; + unsigned int rows; + unsigned int columns; + unsigned int elements; + unsigned int structMembers; + unsigned int bytes; + void *default_value; + + } // for + + assert( info.ui8 == origdata); + + output_comment_bytes(ctx, ctab, (size_t) (ptr - ctab)); +} // output_ctab + + +static void output_comments(Context *ctx, const char **comments, + unsigned int comment_count, + const MOJOSHADER_symbol *symbols, + unsigned int symbol_count) +{ + if (isfail(ctx)) + return; + + // make error messages sane if CTAB fails, etc. + ctx->parse_phase = MOJOSHADER_PARSEPHASE_NOTSTARTED; + + output_ctab(ctx, symbols, symbol_count); + + int i; + for (i = 0; i < comment_count; i++) + output_comment_string(ctx, comments[i]); + + if (!isfail(ctx)) + ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING; +} // output_comments + // API entry point... @@ -1687,7 +1811,7 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, return &out_of_mem_data; // Version token always comes first. - ctx->started_parsing = 1; + ctx->parse_phase = MOJOSHADER_PARSEPHASE_WORKING; parse_version_token(ctx); ctx->started_parsing = 0; // make error messages sane if CTAB fails, etc. @@ -1698,8 +1822,6 @@ const MOJOSHADER_parseData *MOJOSHADER_assemble(const char *source, // !!! FIXME: insert CTAB here. - ctx->started_parsing = 1; - // parse out the rest of the tokens after the version token... while (nexttoken(ctx, 1, 1, 0, 1) == NOFAIL) parse_token(ctx); diff --git a/mojoshader_internal.h b/mojoshader_internal.h index 9d56dbb9..4de0c367 100644 --- a/mojoshader_internal.h +++ b/mojoshader_internal.h @@ -256,6 +256,13 @@ static inline int scalar_register(const MOJOSHADER_shaderType shader_type, return 0; } // scalar_register +typedef enum +{ + MOJOSHADER_PARSEPHASE_NOTSTARTED, + MOJOSHADER_PARSEPHASE_WORKING, + MOJOSHADER_PARSEPHASE_DONE, +} MOJOSHADER_parsePhase; + extern MOJOSHADER_parseData out_of_mem_data; extern const char *out_of_mem_str;