Effect struct parameter support
authorEthan Lee <flibitijibibo@flibitijibibo.com>
Tue, 09 Feb 2016 00:05:18 -0500
changeset 1152 8f7653f0dc37
parent 1151 5e0ebc5366f3
child 1153 663c9541e21f
Effect struct parameter support
mojoshader.c
mojoshader_effects.c
mojoshader_effects.h
mojoshader_opengl.c
utils/testparse.c
--- a/mojoshader.c	Fri Jan 01 12:53:03 2016 -0500
+++ b/mojoshader.c	Tue Feb 09 00:05:18 2016 -0500
@@ -8125,7 +8125,7 @@
     } // else
 
     int i;
-    const uint32 *member = (const uint32 *)((const uint8 *) (&typeptr[6]));
+    const uint32 *member = (const uint32 *) (start + typeptr[6]);
     for (i = 0; i < info->member_count; i++)
     {
         MOJOSHADER_symbolStructMember *mbr = &info->members[i];
--- a/mojoshader_effects.c	Fri Jan 01 12:53:03 2016 -0500
+++ b/mojoshader_effects.c	Tue Feb 09 00:05:18 2016 -0500
@@ -261,11 +261,11 @@
     const uint32 semantic = readui32(&typeptr, &typelen);
     const uint32 numelements = readui32(&typeptr, &typelen);
 
-    value->value_type = (MOJOSHADER_symbolType) type;
-    value->value_class = (MOJOSHADER_symbolClass) valclass;
+    value->type.parameter_type = (MOJOSHADER_symbolType) type;
+    value->type.parameter_class = (MOJOSHADER_symbolClass) valclass;
     value->name = readstring(base, name, m, d);
     value->semantic = readstring(base, semantic, m, d);
-    value->element_count = numelements;
+    value->type.elements = numelements;
 
     /* Class sanity check */
     assert(valclass >= MOJOSHADER_SYMCLASS_SCALAR && valclass <= MOJOSHADER_SYMCLASS_STRUCT);
@@ -281,8 +281,8 @@
         const uint32 columncount = readui32(&typeptr, &typelen);
         const uint32 rowcount = readui32(&typeptr, &typelen);
 
-        value->column_count = columncount;
-        value->row_count = rowcount;
+        value->type.columns = columncount;
+        value->type.rows = rowcount;
 
         uint32 siz = columncount * rowcount;
         if (numelements > 0)
@@ -346,8 +346,51 @@
     } // else if
     else if (valclass == MOJOSHADER_SYMCLASS_STRUCT)
     {
-        /* TODO: Maybe this is like parse_ctab_typeinfo? -flibit */
-        assert(0 && "Effect struct value parsing not implemented!");
+        uint32 siz;
+
+        value->type.member_count = readui32(&typeptr, &typelen);
+        siz = value->type.member_count * sizeof (MOJOSHADER_symbolStructMember);
+        value->type.members = (MOJOSHADER_symbolStructMember *) m(siz, d);
+
+        uint32 structsize = 0;
+        for (i = 0; i < value->type.member_count; i++)
+        {
+            MOJOSHADER_symbolStructMember *mem = &value->type.members[i];
+
+            mem->info.parameter_type = (MOJOSHADER_symbolType) readui32(&typeptr, &typelen);
+            mem->info.parameter_class = (MOJOSHADER_symbolClass) readui32(&typeptr, &typelen);
+
+            const uint32 memname = readui32(&typeptr, &typelen);
+            /*const uint32 memsemantic =*/ readui32(&typeptr, &typelen);
+            mem->name = readstring(base, memname, m, d);
+
+            mem->info.elements = readui32(&typeptr, &typelen);
+            mem->info.columns = readui32(&typeptr, &typelen);
+            mem->info.rows = readui32(&typeptr, &typelen);
+
+            // !!! FIXME: Nested structs! -flibit
+            assert(mem->info.parameter_class >= MOJOSHADER_SYMCLASS_SCALAR
+                && mem->info.parameter_class <= MOJOSHADER_SYMCLASS_VECTOR);
+            assert(mem->info.parameter_type >= MOJOSHADER_SYMTYPE_BOOL
+                && mem->info.parameter_type <= MOJOSHADER_SYMTYPE_FLOAT);
+            mem->info.member_count = 0;
+            mem->info.members = NULL;
+
+            uint32 memsize = mem->info.columns * mem->info.rows;
+            if (mem->info.elements > 0)
+                memsize *= mem->info.elements;
+            structsize += memsize;
+        } // for
+
+        value->type.columns = structsize;
+        value->type.rows = 1;
+        value->value_count = structsize;
+        if (numelements > 0)
+            value->value_count *= numelements;
+
+        siz = value->value_count * 4;
+        value->values = m(siz, d);
+        memcpy(value->values, typeptr, siz); /* Yes, typeptr. -flibit */
     } // else if
 } // readvalue
 
@@ -897,16 +940,30 @@
 } // MOJOSHADER_parseEffect
 
 
+void freetypeinfo(MOJOSHADER_symbolTypeInfo *typeinfo,
+                  MOJOSHADER_free f, void *d)
+{
+    int i;
+    for (i = 0; i < typeinfo->member_count; i++)
+    {
+        f((void *) typeinfo->members[i].name, d);
+        freetypeinfo(&typeinfo->members[i].info, f, d);
+    } // for
+    f((void *) typeinfo->members, d);
+} // freetypeinfo
+
+
 void freevalue(MOJOSHADER_effectValue *value, MOJOSHADER_free f, void *d)
 {
     int i;
     f((void *) value->name, d);
     f((void *) value->semantic, d);
-    if (value->value_type == MOJOSHADER_SYMTYPE_SAMPLER
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER1D
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER2D
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER3D
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE)
+    freetypeinfo(&value->type, f, d);
+    if (value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER1D
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER2D
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER3D
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE)
         for (i = 0; i < value->value_count; i++)
             freevalue(&value->valuesSS[i].value, f, d);
     f(value->values, d);
@@ -1007,6 +1064,39 @@
 } // MOJOSHADER_freeEffect
 
 
+// !!! FIXME: Out of memory check!
+#define COPY_STRING(location) \
+    if (src->location != NULL) \
+    { \
+        siz = strlen(src->location) + 1; \
+        stringcopy = (char *) m(siz, d); \
+        strcpy(stringcopy, src->location); \
+        dst->location = stringcopy; \
+    } // if
+
+
+void copysymboltypeinfo(MOJOSHADER_symbolTypeInfo *dst,
+                        MOJOSHADER_symbolTypeInfo *src,
+                        MOJOSHADER_malloc m,
+                        void *d)
+{
+    int i;
+    uint32 siz = 0;
+    char *stringcopy = NULL;
+    memcpy(dst, src, sizeof (MOJOSHADER_symbolTypeInfo));
+    if (dst->member_count > 0)
+    {
+        siz = dst->member_count * sizeof (MOJOSHADER_symbolStructMember);
+        dst->members = (MOJOSHADER_symbolStructMember *) m(siz, d);
+        for (i = 0; i < dst->member_count; i++)
+        {
+            COPY_STRING(members[i].name)
+            copysymboltypeinfo(&dst->members[i].info, &src->members[i].info, m, d);
+        } // for
+    } // if
+} // copysymboltypeinfo
+
+
 void copyvalue(MOJOSHADER_effectValue *dst,
                MOJOSHADER_effectValue *src,
                MOJOSHADER_malloc m,
@@ -1016,42 +1106,29 @@
     uint32 siz = 0;
     char *stringcopy = NULL;
 
-    // !!! FIXME: Out of memory check!
-    #define COPY_STRING(location) \
-        if (src->location != NULL) \
-        { \
-            siz = strlen(src->location) + 1; \
-            stringcopy = (char *) m(siz, d); \
-            strcpy(stringcopy, src->location); \
-            dst->location = stringcopy; \
-        } // if
-
     COPY_STRING(name)
     COPY_STRING(semantic)
-    dst->element_count = src->element_count;
-    dst->row_count = src->row_count;
-    dst->column_count = src->column_count;
-    dst->value_class = src->value_class;
-    dst->value_type = src->value_type;
+    copysymboltypeinfo(&dst->type, &src->type, m, d);
     dst->value_count = src->value_count;
 
-    if (dst->value_class == MOJOSHADER_SYMCLASS_SCALAR
-     || dst->value_class == MOJOSHADER_SYMCLASS_VECTOR
-     || dst->value_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS
-     || dst->value_class == MOJOSHADER_SYMCLASS_MATRIX_COLUMNS)
+    if (dst->type.parameter_class == MOJOSHADER_SYMCLASS_SCALAR
+     || dst->type.parameter_class == MOJOSHADER_SYMCLASS_VECTOR
+     || dst->type.parameter_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS
+     || dst->type.parameter_class == MOJOSHADER_SYMCLASS_MATRIX_COLUMNS
+     || dst->type.parameter_class == MOJOSHADER_SYMCLASS_STRUCT)
     {
         siz = dst->value_count * 4;
         dst->values = m(siz, d);
         // !!! FIXME: Out of memory check!
         memcpy(dst->values, src->values, siz);
     } // if
-    else if (dst->value_class == MOJOSHADER_SYMCLASS_OBJECT)
+    else if (dst->type.parameter_class == MOJOSHADER_SYMCLASS_OBJECT)
     {
-        if (dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER
-         || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER1D
-         || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER2D
-         || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLER3D
-         || dst->value_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE)
+        if (dst->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER
+         || dst->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER1D
+         || dst->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER2D
+         || dst->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER3D
+         || dst->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE)
         {
             siz = dst->value_count * sizeof (MOJOSHADER_effectSamplerState);
             dst->values = m(siz, d);
@@ -1073,13 +1150,11 @@
             memcpy(dst->values, src->values, siz);
         } // else
     } // else if
-    else if (dst->value_class == MOJOSHADER_SYMCLASS_STRUCT)
-    {
-        /* TODO: See readvalue! -flibit */
-    } // else if
+
+} // copyvalue
 
-    #undef COPY_STRING
-} // copyvalue
+
+#undef COPY_STRING
 
 
 void copysymbolinfo(MOJOSHADER_symbolTypeInfo *dst,
--- a/mojoshader_effects.h	Fri Jan 01 12:53:03 2016 -0500
+++ b/mojoshader_effects.h	Tue Feb 09 00:05:18 2016 -0500
@@ -316,11 +316,7 @@
 {
     const char *name;
     const char *semantic;
-    unsigned int element_count;
-    unsigned int row_count;
-    unsigned int column_count;
-    MOJOSHADER_symbolClass value_class;
-    MOJOSHADER_symbolType value_type;
+    MOJOSHADER_symbolTypeInfo type;
     unsigned int value_count;
     union
     {
--- a/mojoshader_opengl.c	Fri Jan 01 12:53:03 2016 -0500
+++ b/mojoshader_opengl.c	Tue Feb 09 00:05:18 2016 -0500
@@ -2860,14 +2860,14 @@
         // float/int registers are vec4, so they have 4 elements each
         const uint32 start = sym->register_index << 2;
 
-        if (param->value_type == MOJOSHADER_SYMTYPE_FLOAT)
+        if (param->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT)
         {
             // Matrices have to be transposed from row-major to column-major!
-            if (param->value_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS)
+            if (param->type.parameter_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS)
             {
-                if (param->element_count > 1)
+                if (param->type.elements > 1)
                 {
-                    const uint32 regcount = sym->register_count / param->element_count;
+                    const uint32 regcount = sym->register_count / param->type.elements;
                     j = 0;
                     do
                     {
@@ -2881,12 +2881,12 @@
                                                    (r << 2) +
                                                   ((j << 2) * regcount);
                                 const uint32 src = r +
-                                                  (c * param->row_count) +
-                                                  (j * param->row_count * param->column_count);
+                                                  (c * param->type.rows) +
+                                                  (j * param->type.rows * param->type.columns);
                                 regf[dest] = param->valuesF[src];
-                            } while (++c < param->column_count);
+                            } while (++c < param->type.columns);
                         } while (++r < regcount);
-                    } while (++j < param->element_count);
+                    } while (++j < param->type.elements);
                 } // if
                 else
                 {
@@ -2896,8 +2896,8 @@
                         c = 0;
                         do
                         {
-                            regf[start + (r << 2 ) + c] = param->valuesF[r + (c * param->row_count)];
-                        } while (++c < param->column_count);
+                            regf[start + (r << 2 ) + c] = param->valuesF[r + (c * param->type.rows)];
+                        } while (++c < param->type.columns);
                     } while (++r < sym->register_count);
                 } // else
             } // if
@@ -2907,25 +2907,46 @@
                 do
                 {
                     memcpy(regf + start + (j << 2),
-                           param->valuesF + (j * param->column_count),
-                           param->column_count << 2);
+                           param->valuesF + (j * param->type.columns),
+                           param->type.columns << 2);
                 } while (++j < sym->register_count);
             } // else if
             else
-                memcpy(regf + start, param->valuesF, param->column_count << 2);
+                memcpy(regf + start, param->valuesF, param->type.columns << 2);
         } // if
         else if (sym->register_set == MOJOSHADER_SYMREGSET_FLOAT4)
         {
             // Sometimes int/bool parameters get thrown into float registers...
-            j = 0;
-            do
+            if (param->type.parameter_class == MOJOSHADER_SYMCLASS_STRUCT)
             {
-                c = 0;
+                float *struct_offset = param->valuesF;
+                r = 0; /* Register offset */
+                j = 0;
                 do
                 {
-                    regf[start + (j << 2) + c] = (float) param->valuesI[(j * param->column_count) + c];
-                } while (++c < param->column_count);
-            } while (++j < sym->register_count);
+                    c = 0;
+                    do
+                    {
+                        memcpy(regf + start + (r << 2),
+                               struct_offset,
+                               param->type.members[c].info.columns << 2);
+                        struct_offset += param->type.members[c].info.columns;
+                        r++;
+                    } while (++c < param->type.member_count);
+                } while (++j < param->type.elements);
+            } // if
+            else
+            {
+                j = 0;
+                do
+                {
+                    c = 0;
+                    do
+                    {
+                        regf[start + (j << 2) + c] = (float) param->valuesI[(j * param->type.columns) + c];
+                    } while (++c < param->type.columns);
+                } while (++j < sym->register_count);
+            } // else
         } // else if
         else if (sym->register_set == MOJOSHADER_SYMREGSET_INT4)
         {
@@ -2935,12 +2956,12 @@
                 do
                 {
                     memcpy(regi + start + (j << 2),
-                           param->valuesI + (j * param->column_count),
-                           param->column_count << 2);
+                           param->valuesI + (j * param->type.columns),
+                           param->type.columns << 2);
                 } while (++j < sym->register_count);
             } // if
             else
-                memcpy(regi + start, param->valuesI, param->column_count << 2);
+                memcpy(regi + start, param->valuesI, param->type.columns << 2);
         } // else if
         else if (sym->register_set == MOJOSHADER_SYMREGSET_BOOL)
         {
--- a/utils/testparse.c	Fri Jan 01 12:53:03 2016 -0500
+++ b/utils/testparse.c	Tue Feb 09 00:05:18 2016 -0500
@@ -454,21 +454,21 @@
         "UNSUPPORTED"
     };
     do_indent(indent + 1);
-    printf("CLASS: %s\n", classes[value->value_class]);
+    printf("CLASS: %s\n", classes[value->type.parameter_class]);
     do_indent(indent + 1);
-    printf("TYPE: %s\n", types[value->value_type]);
+    printf("TYPE: %s\n", types[value->type.parameter_type]);
 
     do_indent(indent + 1);
     printf("ROWS/COLUMNS/ELEMENTS: %d, %d, %d\n",
-           value->row_count, value->column_count, value->element_count);
+           value->type.rows, value->type.columns, value->type.elements);
     do_indent(indent + 1);
     printf("TOTAL VALUES: %d\n", value->value_count);
 
-    if (value->value_type == MOJOSHADER_SYMTYPE_SAMPLER
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER1D
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER2D
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLER3D
-     || value->value_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE)
+    if (value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER1D
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER2D
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLER3D
+     || value->type.parameter_type == MOJOSHADER_SYMTYPE_SAMPLERCUBE)
     {
         do_indent(indent + 1);
         printf("SAMPLER VALUES:\n");
@@ -516,7 +516,7 @@
     else
     {
         do_indent(indent + 1);
-        printf("%s VALUES:\n", types[value->value_type]);
+        printf("%s VALUES:\n", types[value->type.parameter_type]);
         for (i = 0; i < value->value_count; i++)
         {
             do_indent(indent + 2);
@@ -541,10 +541,10 @@
                 "%d\n",
                 "%X\n"
             };
-            if (value->value_type == MOJOSHADER_SYMTYPE_FLOAT)
-                printf(prints[value->value_type], value->valuesF[i]);
+            if (value->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT)
+                printf(prints[value->type.parameter_type], value->valuesF[i]);
             else
-                printf(prints[value->value_type], value->valuesI[i]);
+                printf(prints[value->type.parameter_type], value->valuesI[i]);
         } // for
     } // else
 } // print_value