mojoshader.c
changeset 1028 74e7ee46ac93
parent 1027 3fe5609f3620
child 1029 5af5af0210df
equal deleted inserted replaced
1027:3fe5609f3620 1028:74e7ee46ac93
   135     int have_relative_input_registers;
   135     int have_relative_input_registers;
   136     int determined_constants_arrays;
   136     int determined_constants_arrays;
   137     int predicated;
   137     int predicated;
   138     int glsl_generated_lit_opcode;
   138     int glsl_generated_lit_opcode;
   139     int glsl_generated_texldd_setup;
   139     int glsl_generated_texldd_setup;
       
   140     int symbol_count;
       
   141     MOJOSHADER_symbol *symbols;
   140 
   142 
   141 #if SUPPORT_PROFILE_ARB1_NV
   143 #if SUPPORT_PROFILE_ARB1_NV
   142     int profile_supports_nv2;
   144     int profile_supports_nv2;
   143     int profile_supports_nv3;
   145     int profile_supports_nv3;
   144     int profile_supports_nv4;
   146     int profile_supports_nv4;
  6854 
  6856 
  6855     return 1;  // ate one token.
  6857     return 1;  // ate one token.
  6856 } // parse_version_token
  6858 } // parse_version_token
  6857 
  6859 
  6858 
  6860 
       
  6861 static int parse_ctab_string(const uint8 *start, const uint32 bytes,
       
  6862                              const uint32 name)
       
  6863 {
       
  6864     // Make sure strings don't overflow the CTAB buffer...
       
  6865     if (name < bytes)
       
  6866     {
       
  6867         int i;
       
  6868         const int slenmax = bytes - name;
       
  6869         const char *namestr = (const char *) (start + name);
       
  6870         for (i = 0; i < slenmax; i++)
       
  6871         {
       
  6872             if (namestr[i] == '\0')
       
  6873                 return 1;  // it's okay.
       
  6874         } // for
       
  6875     } // if
       
  6876 
       
  6877     return 0;  // overflowed.
       
  6878 } // parse_ctab_string
       
  6879 
       
  6880 
       
  6881 static int parse_ctab_typeinfo(Context *ctx, const uint8 *start,
       
  6882                                const uint32 bytes, const uint32 pos,
       
  6883                                MOJOSHADER_symbolTypeInfo *info)
       
  6884 {
       
  6885     if ((pos + 16) >= bytes)
       
  6886         return 0;  // corrupt CTAB.
       
  6887 
       
  6888     const uint16 *typeptr = (const uint16 *) (start + pos);
       
  6889 
       
  6890     info->parameter_class = (MOJOSHADER_symbolClass) SWAP16(typeptr[0]);
       
  6891     info->parameter_type = (MOJOSHADER_symbolType) SWAP16(typeptr[1]);
       
  6892     info->rows = (unsigned int) SWAP16(typeptr[2]);
       
  6893     info->columns = (unsigned int) SWAP16(typeptr[3]);
       
  6894     info->elements = (unsigned int) SWAP16(typeptr[4]);
       
  6895     info->member_count = (unsigned int) SWAP16(typeptr[5]);
       
  6896 
       
  6897     if ((pos + 16 + (info->member_count * 8)) >= bytes)
       
  6898         return 0;  // corrupt CTAB.
       
  6899 
       
  6900     const size_t len = sizeof (MOJOSHADER_symbolStructMember) *
       
  6901                         info->member_count;
       
  6902 
       
  6903     info->members = (MOJOSHADER_symbolStructMember *) Malloc(ctx, len);
       
  6904     if (info->members == NULL)
       
  6905         return 1;  // we'll check ctx->out_of_memory later.
       
  6906     memset(info->members, '\0', len);
       
  6907 
       
  6908     int i;
       
  6909     const uint32 *member = (const uint32 *)((const uint8 *) (&typeptr[6]));
       
  6910     for (i = 0; i < info->member_count; i++)
       
  6911     {
       
  6912         MOJOSHADER_symbolStructMember *mbr = &info->members[i];
       
  6913         const uint32 name = SWAP32(member[0]);
       
  6914         const uint32 memberinfopos = SWAP32(member[1]);
       
  6915         member += 2;
       
  6916 
       
  6917         if (!parse_ctab_string(start, bytes, name))
       
  6918             return 0;  // info->members will be free()'d elsewhere.
       
  6919 
       
  6920         mbr->name = StrDup(ctx, (const char *) (start + name));
       
  6921         if (mbr->name == NULL)
       
  6922             return 1;  // we'll check ctx->out_of_memory later.
       
  6923         if (!parse_ctab_typeinfo(ctx, start, bytes, memberinfopos, &mbr->info))
       
  6924             return 0;
       
  6925         if (ctx->out_of_memory)
       
  6926             return 1;  // drop out now.
       
  6927     } // for
       
  6928 
       
  6929     return 1;
       
  6930 } // parse_ctab_typeinfo
       
  6931 
       
  6932 
  6859 // Microsoft's tools add a CTAB comment to all shaders. This is the
  6933 // Microsoft's tools add a CTAB comment to all shaders. This is the
  6860 //  "constant table," or specifically: D3DXSHADER_CONSTANTTABLE:
  6934 //  "constant table," or specifically: D3DXSHADER_CONSTANTTABLE:
  6861 //  http://msdn.microsoft.com/en-us/library/bb205440(VS.85).aspx
  6935 //  http://msdn.microsoft.com/en-us/library/bb205440(VS.85).aspx
  6862 // This may tell us high-level truths about an otherwise generic low-level
  6936 // This may tell us high-level truths about an otherwise generic low-level
  6863 //  registers, for instance, how large an array actually is, etc.
  6937 //  registers, for instance, how large an array actually is, etc.
  6864 // !!! FIXME: parse symbols.
       
  6865 static void parse_constant_table(Context *ctx, const uint32 bytes)
  6938 static void parse_constant_table(Context *ctx, const uint32 bytes)
  6866 {
  6939 {
       
  6940     if (bytes < 32)
       
  6941     {
       
  6942         fail(ctx, "Truncated CTAB data");
       
  6943         return;
       
  6944     } // if
       
  6945 
       
  6946     assert(ctx->have_ctab == 0);  // !!! FIXME: can you have more than one?
       
  6947 
  6867     const uint8 *start = (uint8 *) &ctx->tokens[2];
  6948     const uint8 *start = (uint8 *) &ctx->tokens[2];
  6868     const uint32 id = SWAP32(ctx->tokens[1]);
  6949     const uint32 id = SWAP32(ctx->tokens[1]);
  6869     const uint32 size = SWAP32(ctx->tokens[2]);
  6950     const uint32 size = SWAP32(ctx->tokens[2]);
  6870     const uint32 creator = SWAP32(ctx->tokens[3]);
  6951     const uint32 creator = SWAP32(ctx->tokens[3]);
  6871     const uint32 version = SWAP32(ctx->tokens[4]);
  6952     const uint32 version = SWAP32(ctx->tokens[4]);
  6875     uint32 i = 0;
  6956     uint32 i = 0;
  6876 
  6957 
  6877     if (id != CTAB_ID)
  6958     if (id != CTAB_ID)
  6878         return;  // not the constant table.
  6959         return;  // not the constant table.
  6879 
  6960 
  6880     if (size != CTAB_SIZE)
  6961     if (size != CTAB_SIZE)  // !!! FIXME: should this fail()?
  6881         return;  // only handle this version of the struct.
  6962         return;  // only handle this version of the struct.
  6882 
  6963 
  6883     if (version != ctx->version_token) goto corrupt_ctab;
  6964     if (version != ctx->version_token) goto corrupt_ctab;
  6884     if (creator >= bytes) goto corrupt_ctab;
  6965     if (creator >= bytes) goto corrupt_ctab;
  6885     if ((constantinfo + (constants * CINFO_SIZE)) >= bytes) goto corrupt_ctab;
  6966     if ((constantinfo + (constants * CINFO_SIZE)) >= bytes) goto corrupt_ctab;
  6886     if (target >= bytes) goto corrupt_ctab;
  6967     if (target >= bytes) goto corrupt_ctab;
  6887 
  6968 
  6888     ctx->have_ctab = 1;
  6969     ctx->have_ctab = 1;
       
  6970 
       
  6971     ctx->symbol_count = constants;
       
  6972     ctx->symbols = Malloc(ctx, sizeof (MOJOSHADER_symbol) * constants);
       
  6973     if (ctx->symbols == NULL)
       
  6974         return;
       
  6975     memset(ctx->symbols, '\0', sizeof (MOJOSHADER_symbol) * constants);
  6889 
  6976 
  6890     for (i = 0; i < constants; i++)
  6977     for (i = 0; i < constants; i++)
  6891     {
  6978     {
  6892         const uint8 *ptr = start + constantinfo + (i * CINFO_SIZE);
  6979         const uint8 *ptr = start + constantinfo + (i * CINFO_SIZE);
  6893         const uint32 name = SWAP32(*((uint32 *) (ptr + 0)));
  6980         const uint32 name = SWAP32(*((uint32 *) (ptr + 0)));
  6896         const uint16 regcnt = SWAP16(*((uint16 *) (ptr + 8)));
  6983         const uint16 regcnt = SWAP16(*((uint16 *) (ptr + 8)));
  6897         const uint32 typeinf = SWAP32(*((uint32 *) (ptr + 12)));
  6984         const uint32 typeinf = SWAP32(*((uint32 *) (ptr + 12)));
  6898         const uint32 defval = SWAP32(*((uint32 *) (ptr + 16)));
  6985         const uint32 defval = SWAP32(*((uint32 *) (ptr + 16)));
  6899         MOJOSHADER_uniformType mojotype = MOJOSHADER_UNIFORM_UNKNOWN;
  6986         MOJOSHADER_uniformType mojotype = MOJOSHADER_UNIFORM_UNKNOWN;
  6900 
  6987 
  6901         if (name >= bytes) goto corrupt_ctab;
  6988         if (!parse_ctab_string(start, bytes, name)) goto corrupt_ctab;
  6902         if ((typeinf + 16) >= bytes) goto corrupt_ctab;
       
  6903         if (defval >= bytes) goto corrupt_ctab;
  6989         if (defval >= bytes) goto corrupt_ctab;
  6904 
  6990 
  6905         switch (regset)
  6991         switch (regset)
  6906         {
  6992         {
  6907             case 0: mojotype = MOJOSHADER_UNIFORM_BOOL; break;
  6993             case 0: mojotype = MOJOSHADER_UNIFORM_BOOL; break;
  6925                 item->emit_position = -1;
  7011                 item->emit_position = -1;
  6926                 item->next = ctx->variables;
  7012                 item->next = ctx->variables;
  6927                 ctx->variables = item;
  7013                 ctx->variables = item;
  6928             } // if
  7014             } // if
  6929         } // if
  7015         } // if
       
  7016 
       
  7017         // Add the symbol.
       
  7018         const char *namecpy = StrDup(ctx, (const char *) (start + name));
       
  7019         if (namecpy == NULL)
       
  7020             return;
       
  7021 
       
  7022         MOJOSHADER_symbol *sym = &ctx->symbols[i];
       
  7023         sym->name = namecpy;
       
  7024         sym->register_set = (MOJOSHADER_symbolRegisterSet) regset;
       
  7025         sym->register_index = (unsigned int) regidx;
       
  7026         sym->register_count = (unsigned int) regcnt;
       
  7027         if (!parse_ctab_typeinfo(ctx, start, bytes, typeinf, &sym->info))
       
  7028             goto corrupt_ctab;  // sym->name will get free()'d later.
       
  7029         else if (ctx->out_of_memory)
       
  7030             return;  // just bail now.
  6930     } // for
  7031     } // for
  6931 
  7032 
  6932     return;
  7033     return;
  6933 
  7034 
  6934 corrupt_ctab:
  7035 corrupt_ctab:
  6935     fail(ctx, "Shader has corrupt CTAB data");
  7036     fail(ctx, "Shader has corrupt CTAB data");
  6936 } // parse_constant_table
  7037 } // parse_constant_table
  6937 
  7038 
  6938 
  7039 
       
  7040 static int is_comment_token(Context *ctx, const uint32 tok, uint32 *tokcount)
       
  7041 {
       
  7042     const uint32 token = SWAP32(tok);
       
  7043     if ((token & 0xFFFF) == 0xFFFE)  // actually a comment token?
       
  7044     {
       
  7045         if ((token & 0x80000000) != 0)
       
  7046             fail(ctx, "comment token high bit must be zero.");  // so says msdn.
       
  7047         *tokcount = ((token >> 16) & 0xFFFF);
       
  7048         return 1;
       
  7049     } // if
       
  7050 
       
  7051     return 0;
       
  7052 } // is_comment_token
       
  7053 
       
  7054 
  6939 static int parse_comment_token(Context *ctx)
  7055 static int parse_comment_token(Context *ctx)
  6940 {
  7056 {
  6941     const uint32 token = SWAP32(*(ctx->tokens));
  7057     uint32 commenttoks = 0;
  6942     if ((token & 0xFFFF) != 0xFFFE)
  7058     if (is_comment_token(ctx, *ctx->tokens, &commenttoks))
  6943         return 0;  // not a comment token.
  7059     {
  6944     if ((token & 0x80000000) != 0)
  7060         if ((commenttoks >= 1) && (commenttoks < ctx->tokencount))
  6945         fail(ctx, "comment token high bit must be zero.");  // so says msdn.
  7061         {
  6946 
  7062             const uint32 id = SWAP32(ctx->tokens[1]);
  6947     const uint32 commenttoks = ((token >> 16) & 0xFFFF);
  7063             if (id == CTAB_ID)
  6948     if ((commenttoks >= 8) && (commenttoks < ctx->tokencount))
  7064                 parse_constant_table(ctx, commenttoks * 4);
  6949         parse_constant_table(ctx, commenttoks * 4);
  7065         } // if
  6950     return commenttoks + 1;  // comment data plus the initial token.
  7066         return commenttoks + 1;  // comment data plus the initial token.
       
  7067     } // if
       
  7068 
       
  7069     return 0;  // not a comment token.
  6951 } // parse_comment_token
  7070 } // parse_comment_token
  6952 
  7071 
  6953 
  7072 
  6954 static int parse_end_token(Context *ctx)
  7073 static int parse_end_token(Context *ctx)
  6955 {
  7074 {
  7103         VariableList *next = item->next;
  7222         VariableList *next = item->next;
  7104         f(item, d);
  7223         f(item, d);
  7105         item = next;
  7224         item = next;
  7106     } // while
  7225     } // while
  7107 } // free_variable_list
  7226 } // free_variable_list
       
  7227 
       
  7228 
       
  7229 static void free_sym_typeinfo(MOJOSHADER_free f, void *d,
       
  7230                               MOJOSHADER_symbolTypeInfo *typeinfo)
       
  7231 {
       
  7232     int i;
       
  7233     for (i = 0; i < typeinfo->member_count; i++)
       
  7234     {
       
  7235         f((void *) typeinfo->members[i].name, d);
       
  7236         free_sym_typeinfo(f, d, &typeinfo->members[i].info);
       
  7237     } // for
       
  7238     f((void *) typeinfo->members, d);
       
  7239 } // free_sym_members
       
  7240 
       
  7241 
       
  7242 static void free_symbols(MOJOSHADER_free f, void *d, MOJOSHADER_symbol *syms,
       
  7243                          const int symcount)
       
  7244 {
       
  7245     int i;
       
  7246     for (i = 0; i < symcount; i++)
       
  7247     {
       
  7248         f((void *) syms[i].name, d);
       
  7249         free_sym_typeinfo(f, d, &syms[i].info);
       
  7250     } // for
       
  7251     f((void *) syms, d);
       
  7252 } // free_symbols
  7108 
  7253 
  7109 
  7254 
  7110 static void destroy_context(Context *ctx)
  7255 static void destroy_context(Context *ctx)
  7111 {
  7256 {
  7112     if (ctx != NULL)
  7257     if (ctx != NULL)
  7126         free_reglist(f, d, ctx->uniforms.next);
  7271         free_reglist(f, d, ctx->uniforms.next);
  7127         free_reglist(f, d, ctx->attributes.next);
  7272         free_reglist(f, d, ctx->attributes.next);
  7128         free_reglist(f, d, ctx->samplers.next);
  7273         free_reglist(f, d, ctx->samplers.next);
  7129         free_variable_list(f, d, ctx->variables);
  7274         free_variable_list(f, d, ctx->variables);
  7130         errorlist_destroy(ctx->errors);
  7275         errorlist_destroy(ctx->errors);
       
  7276         free_symbols(f, d, ctx->symbols, ctx->symbol_count);
  7131         f(ctx, d);
  7277         f(ctx, d);
  7132     } // if
  7278     } // if
  7133 } // destroy_context
  7279 } // destroy_context
  7134 
  7280 
  7135 
  7281 
  7505         retval->samplers = samplers;
  7651         retval->samplers = samplers;
  7506         retval->attribute_count = attribute_count;
  7652         retval->attribute_count = attribute_count;
  7507         retval->attributes = attributes;
  7653         retval->attributes = attributes;
  7508         retval->swizzle_count = ctx->swizzles_count;
  7654         retval->swizzle_count = ctx->swizzles_count;
  7509         retval->swizzles = swizzles;
  7655         retval->swizzles = swizzles;
       
  7656         retval->symbol_count = ctx->symbol_count;
       
  7657         retval->symbols = ctx->symbols;
       
  7658 
       
  7659         ctx->symbols = NULL;  // we don't own this now, retval does.
       
  7660         ctx->symbol_count = 0;
  7510     } // else
  7661     } // else
  7511 
  7662 
  7512     retval->error_count = error_count;
  7663     retval->error_count = error_count;
  7513     retval->errors = errors;
  7664     retval->errors = errors;
  7514     retval->malloc = (ctx->malloc == MOJOSHADER_internal_malloc) ? NULL : ctx->malloc;
  7665     retval->malloc = (ctx->malloc == MOJOSHADER_internal_malloc) ? NULL : ctx->malloc;
  7808 
  7959 
  7809     for (i = 0; i < data->sampler_count; i++)
  7960     for (i = 0; i < data->sampler_count; i++)
  7810         f((void *) data->samplers[i].name, d);
  7961         f((void *) data->samplers[i].name, d);
  7811     f((void *) data->samplers, d);
  7962     f((void *) data->samplers, d);
  7812 
  7963 
  7813     for (i = 0; i < data->symbol_count; i++)
  7964     free_symbols(f, d, data->symbols, data->symbol_count);
  7814     {
       
  7815         f((void *) data->symbols[i].name, d);
       
  7816         f((void *) data->symbols[i].default_value, d);
       
  7817     } // for
       
  7818     f((void *) data->symbols, d);
       
  7819 
  7965 
  7820     f(data, d);
  7966     f(data, d);
  7821 } // MOJOSHADER_freeParseData
  7967 } // MOJOSHADER_freeParseData
  7822 
  7968 
  7823 
  7969