GLSL: Use varyings when usage_str is NULL for vertex/pixel shaders
authorEthan Lee <flibitijibibo@flibitijibibo.com>
Sat, 28 May 2016 22:45:59 -0400
changeset 1173 4b2f745c643b
parent 1172 55700e64bd8c
child 1174 e83fe013f0c5
GLSL: Use varyings when usage_str is NULL for vertex/pixel shaders
GLSLES: Various fixes from Maik Macho, thanks!
Effects: Store parameter staging buffers as vec4 values, per ID3DXEffect spec
mojoshader.c
mojoshader_effects.c
mojoshader_opengl.c
utils/testparse.c
--- a/mojoshader.c	Sun May 29 00:31:36 2016 -0400
+++ b/mojoshader.c	Sat May 28 22:45:59 2016 -0400
@@ -2224,9 +2224,10 @@
         else
             output_line(ctx, "precision mediump float;");
         output_line(ctx, "precision mediump int;");
-        output_line(ctx, "varying vec4 v_FrontColor;");
-        output_line(ctx, "varying vec4 v_FrontSecondaryColor;");
-        output_line(ctx, "varying vec4 v_TexCoord[10];"); // 10 according to SM3
+        // Some drivers don't like it when the precision varies between shaders. -ade
+        output_line(ctx, "varying highp vec4 v_FrontColor;");
+        output_line(ctx, "varying highp vec4 v_FrontSecondaryColor;");
+        output_line(ctx, "varying highp vec4 v_TexCoord[10];"); // 10 according to SM3
         pop_output(ctx);
     } // else if
     #endif
@@ -2344,6 +2345,12 @@
                 //  ps_1_1 TEX opcode expects to overwrite it.
                 if (!shader_version_atleast(ctx, 1, 4))
                 {
+#if SUPPORT_PROFILE_GLSLES
+                    if (support_glsles(ctx))
+                        output_line(ctx, "vec4 %s = v_TexCoord[%d];",
+                                    varname, regnum);
+                    else
+#endif
                     output_line(ctx, "vec4 %s = gl_TexCoord[%d];",
                                 varname, regnum);
                 } // if
@@ -2648,7 +2655,15 @@
             push_output(ctx, &ctx->globals);
             // no mapping to built-in var? Just make it a regular global, pray.
             if (usage_str == NULL)
-                output_line(ctx, "vec4 %s;", var);
+            {
+#if SUPPORT_PROFILE_GLSLES
+                if (support_glsles(ctx))
+                    output_line(ctx, "varying highp vec4 io_%i_%i;", usage, index);
+                else
+#endif
+                output_line(ctx, "varying vec4 io_%i_%i;", usage, index);
+                output_line(ctx, "#define %s io_%i_%i", var, usage, index);
+            } // if
             else
             {
                 output_line(ctx, "#define %s %s%s%s%s", var, usage_str,
@@ -2731,15 +2746,9 @@
 #endif
                     usage_str = "gl_SecondaryColor";
                 } // else if
-                else
-                    fail(ctx, "unsupported color index");
-            } // else if
-
-            else if (usage == MOJOSHADER_USAGE_DEPTH) // !!! FIXME: Possibly more! -flibit
-            {
-                push_output(ctx, &ctx->globals);
-                output_line(ctx, "attribute vec4 %s;", var);
-                pop_output(ctx);
+                // FIXME: Does this even matter when we have varyings? -flibit
+                // else
+                //    fail(ctx, "unsupported color index");
             } // else if
         } // else if
 
@@ -2768,13 +2777,24 @@
             fail(ctx, "unknown pixel shader attribute register");
         } // else
 
-        if (usage_str != NULL)
-        {
-            push_output(ctx, &ctx->globals);
+        push_output(ctx, &ctx->globals);
+        // no mapping to built-in var? Just make it a regular global, pray.
+        if (usage_str == NULL)
+        {
+#if SUPPORT_PROFILE_GLSLES
+            if (support_glsles(ctx))
+                output_line(ctx, "varying highp vec4 io_%i_%i;", usage, index);
+            else
+#endif
+            output_line(ctx, "varying vec4 io_%i_%i;", usage, index);
+            output_line(ctx, "#define %s io_%i_%i", var, usage, index);
+        } // if
+        else
+        {
             output_line(ctx, "#define %s %s%s%s%s", var, usage_str,
                         arrayleft, index_str, arrayright);
-            pop_output(ctx);
-        } // if
+        } // else
+        pop_output(ctx);
     } // else if
 
     else
@@ -5031,15 +5051,6 @@
 
                 else if (usage == MOJOSHADER_USAGE_FOG)
                     output_line(ctx, "float4 %s [[user(fog)]];", var);
-
-                #if 0  // !!! FIXME: Ethan added this for GLSL, but I don't know what it does.  --ryan.
-                else if (usage == MOJOSHADER_USAGE_DEPTH) // !!! FIXME: Possibly more! -flibit
-                {
-                    push_output(ctx, &ctx->globals);
-                    output_line(ctx, "attribute vec4 %s;", var);
-                    pop_output(ctx);
-                } // else if
-                #endif
             } // else
 
             pop_output(ctx);
--- a/mojoshader_effects.c	Sun May 29 00:31:36 2016 -0400
+++ b/mojoshader_effects.c	Sat May 28 22:45:59 2016 -0400
@@ -251,7 +251,7 @@
                       MOJOSHADER_malloc m,
                       void *d)
 {
-    int i;
+    int i, j, k;
     const uint8 *typeptr = base + typeoffset;
     const uint8 *valptr = base + valoffset;
     unsigned int typelen = 9999999;  // !!! FIXME
@@ -284,13 +284,16 @@
         value->type.columns = columncount;
         value->type.rows = rowcount;
 
-        uint32 siz = columncount * rowcount;
+        uint32 siz = 4 * rowcount;
         if (numelements > 0)
             siz *= numelements;
         value->value_count = siz;
         siz *= 4;
         value->values = m(siz, d);
-        memcpy(value->values, valptr, siz);
+        memset(value->values, '\0', siz);
+        siz /= 16;
+        for (i = 0; i < siz; i++)
+            memcpy(value->valuesF + (i << 2), valptr + ((columncount << 2) * i), columncount << 2);
     } // if
     else if (valclass == MOJOSHADER_SYMCLASS_OBJECT)
     {
@@ -376,7 +379,7 @@
             mem->info.member_count = 0;
             mem->info.members = NULL;
 
-            uint32 memsize = mem->info.columns * mem->info.rows;
+            uint32 memsize = 4 * mem->info.rows;
             if (mem->info.elements > 0)
                 memsize *= mem->info.elements;
             structsize += memsize;
@@ -390,7 +393,24 @@
 
         siz = value->value_count * 4;
         value->values = m(siz, d);
-        memcpy(value->values, typeptr, siz); /* Yes, typeptr. -flibit */
+        memset(value->values, '\0', siz);
+        int dst_offset = 0, src_offset = 0;
+        i = 0;
+        do
+        {
+            for (j = 0; j < value->type.member_count; j++)
+            {
+                siz = value->type.members[j].info.rows * value->type.members[j].info.elements;
+                for (k = 0; k < siz; k++)
+                {
+                    memcpy(value->valuesF + dst_offset,
+                           typeptr + src_offset, /* Yes, typeptr. -flibit */
+                           value->type.members[j].info.columns << 2);
+                    dst_offset += 4;
+                    src_offset += value->type.members[j].info.columns << 2;
+                } // for
+            }
+        } while (++i < numelements);
     } // else if
 } // readvalue
 
@@ -1639,8 +1659,8 @@
                                         const unsigned int offset,
                                         const unsigned int len)
 {
-    // !!! FIXME: uint32* case is arbitary, for Win32 -flibit
-    memcpy((uint32 *) parameter->value.values + offset, data, len);
+    // !!! FIXME: char* case is arbitary, for Win32 -flibit
+    memcpy((char *) parameter->value.values + offset, data, len);
 } // MOJOSHADER_effectSetRawValueHandle
 
 
@@ -1655,8 +1675,8 @@
     {
         if (strcmp(name, effect->params[i].value.name) == 0)
         {
-            // !!! FIXME: uint32* case is arbitary, for Win32 -flibit
-            memcpy((uint32 *) effect->params[i].value.values + offset, data, len);
+            // !!! FIXME: char* case is arbitary, for Win32 -flibit
+            memcpy((char *) effect->params[i].value.values + offset, data, len);
             return;
         } // if
     } // for
--- a/mojoshader_opengl.c	Sun May 29 00:31:36 2016 -0400
+++ b/mojoshader_opengl.c	Sat May 28 22:45:59 2016 -0400
@@ -726,7 +726,7 @@
 static void impl_ARB1_DeleteProgram(const GLuint program)
 {
     // no-op. ARB1 doesn't have real linked programs.
-} // impl_GLSL_DeleteProgram
+} // impl_ARB1_DeleteProgram
 
 static GLint impl_ARB1_GetUniformLocation(MOJOSHADER_glProgram *program,
                                           MOJOSHADER_glShader *shader, int idx)
@@ -1074,8 +1074,10 @@
         const char *str = (const char *) ctx->glGetString(enumval);
         if (ctx->glGetError() == GL_INVALID_ENUM)
             str = NULL;
-        if (strstr(str, "OpenGL ES GLSL ES "))
-            str += 18;
+        if (strstr(str, "OpenGL ES GLSL "))
+            str += 15;
+        if (strstr(str, "ES "))
+            str += 3;
         parse_opengl_version_str(str, &ctx->glsl_major, &ctx->glsl_minor);
     } // if
 #endif
@@ -1279,7 +1281,7 @@
     #if SUPPORT_PROFILE_GLSLES
     else if (strcmp(profile, MOJOSHADER_PROFILE_GLSLES) == 0)
     {
-        MUST_HAVE_GLSL(MOJOSHADER_PROFILE_GLSLES, 1, 10);
+        MUST_HAVE_GLSL(MOJOSHADER_PROFILE_GLSLES, 1, 00);
     } // else if
     #endif
 
@@ -2864,116 +2866,44 @@
         const uint32 start = sym->register_index << 2;
 
         if (param->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT)
-        {
-            // Matrices have to be transposed from row-major to column-major!
-            if (param->type.parameter_class == MOJOSHADER_SYMCLASS_MATRIX_ROWS)
-            {
-                if (param->type.elements > 1)
-                {
-                    const uint32 regcount = sym->register_count / param->type.elements;
-                    j = 0;
-                    do
-                    {
-                        r = 0;
-                        do
-                        {
-                            c = 0;
-                            do
-                            {
-                                const uint32 dest = start + c +
-                                                   (r << 2) +
-                                                  ((j << 2) * regcount);
-                                const uint32 src = r +
-                                                  (c * param->type.rows) +
-                                                  (j * param->type.rows * param->type.columns);
-                                regf[dest] = param->valuesF[src];
-                            } while (++c < param->type.columns);
-                        } while (++r < regcount);
-                    } while (++j < param->type.elements);
-                } // if
-                else
-                {
-                    r = 0;
-                    do
-                    {
-                        c = 0;
-                        do
-                        {
-                            regf[start + (r << 2 ) + c] = param->valuesF[r + (c * param->type.rows)];
-                        } while (++c < param->type.columns);
-                    } while (++r < sym->register_count);
-                } // else
-            } // if
-            else if (sym->register_count > 1)
-            {
-                j = 0;
-                do
-                {
-                    memcpy(regf + start + (j << 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->type.columns << 2);
-        } // if
+            memcpy(regf + start, param->valuesF, sym->register_count << 4);
         else if (sym->register_set == MOJOSHADER_SYMREGSET_FLOAT4)
         {
-            // Sometimes int/bool parameters get thrown into float registers...
+            // Structs are a whole different world...
             if (param->type.parameter_class == MOJOSHADER_SYMCLASS_STRUCT)
+                memcpy(regf + start, param->valuesF, sym->register_count << 4);
+            else
             {
-                float *struct_offset = param->valuesF;
-                r = 0; /* Register offset */
+                // Sometimes int/bool parameters get thrown into float registers...
                 j = 0;
                 do
                 {
                     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];
+                        regf[start + (j << 2) + c] = (float) param->valuesI[(j << 2) + c];
                     } while (++c < param->type.columns);
                 } while (++j < sym->register_count);
             } // else
         } // else if
         else if (sym->register_set == MOJOSHADER_SYMREGSET_INT4)
-        {
-            if (sym->register_count > 1)
-            {
-                j = 0;
-                do
-                {
-                    memcpy(regi + start + (j << 2),
-                           param->valuesI + (j * param->type.columns),
-                           param->type.columns << 2);
-                } while (++j < sym->register_count);
-            } // if
-            else
-                memcpy(regi + start, param->valuesI, param->type.columns << 2);
-        } // else if
+            memcpy(regi + start, param->valuesI, sym->register_count << 4);
         else if (sym->register_set == MOJOSHADER_SYMREGSET_BOOL)
         {
             j = 0;
+            r = 0;
             do
             {
-                // regb is not a vec4, enjoy this bitshift! -flibit
-                regb[(start >> 2) + j] = param->valuesI[j];
-            } while (++j < sym->register_count);
+                c = 0;
+                do
+                {
+                    // regb is not a vec4, enjoy that 'start' bitshift! -flibit
+                    regb[(start >> 2) + r + c] = param->valuesI[(j << 2) + c];
+                    c++;
+                } while (c < param->type.columns && ((r + c) < sym->register_count));
+                r += c;
+                j++;
+            } while (r < sym->register_count);
         } // else if
     } // for
 } // copy_parameter_data
@@ -2985,7 +2915,7 @@
     MOJOSHADER_effectShader *rawFrag = glEffect->current_frag_raw;
 
     /* Used for shader selection from preshaders */
-    int i;
+    int i, j;
     MOJOSHADER_effectValue *param;
     float selector;
     int shader_object;
@@ -3003,9 +2933,10 @@
             do \
             { \
                 param = &glEffect->effect->params[raw->preshader_params[i]].value; \
-                memcpy(raw->preshader->registers + raw->preshader->symbols[i].register_index, \
-                       param->values, \
-                       param->value_count << 2); \
+                for (j = 0; j < (param->value_count >> 2); j++) \
+                    memcpy(raw->preshader->registers + raw->preshader->symbols[i].register_index + j, \
+                           param->valuesI + (j << 2), \
+                           param->type.columns << 2); \
             } while (++i < raw->preshader->symbol_count); \
             MOJOSHADER_runPreshader(raw->preshader, &selector); \
             shader_object = glEffect->effect->params[raw->params[0]].value.valuesI[(int) selector]; \
@@ -3051,12 +2982,6 @@
     #define COPY_PARAMETER_DATA(raw, stage) \
         if (raw != NULL) \
         { \
-            if (ctx->bound_program->stage##_float4_loc != -1) \
-                memset(ctx->stage##_reg_file_f, '\0', ctx->bound_program->stage##_uniforms_float4_count << 4); \
-            if (ctx->bound_program->stage##_int4_loc != -1) \
-                memset(ctx->stage##_reg_file_i, '\0', ctx->bound_program->stage##_uniforms_int4_count << 4); \
-            if (ctx->bound_program->stage##_bool_loc != -1) \
-                memset(ctx->stage##_reg_file_b, '\0', ctx->bound_program->stage##_uniforms_bool_count << 2); \
             copy_parameter_data(glEffect->effect->params, raw->params, \
                                 raw->shader->symbols, \
                                 raw->shader->symbol_count, \
--- a/utils/testparse.c	Sun May 29 00:31:36 2016 -0400
+++ b/utils/testparse.c	Sat May 28 22:45:59 2016 -0400
@@ -419,7 +419,7 @@
 static void print_value(const MOJOSHADER_effectValue *value,
                         const unsigned int indent)
 {
-    int i;
+    int i, r, c;
 
     INDENT();
     printf("VALUE: %s -> %s\n", value->name, value->semantic);
@@ -518,35 +518,44 @@
     {
         do_indent(indent + 1);
         printf("%s VALUES:\n", types[value->type.parameter_type]);
-        for (i = 0; i < value->value_count; i++)
+        i = 0;
+        do
         {
-            do_indent(indent + 2);
             static const char *prints[] =
             {
-                "%X\n",
-                "%d\n",
-                "%d\n",
-                "%.2f\n",
-                "%d\n",
-                "%d\n",
-                "%d\n",
-                "%d\n",
-                "%d\n",
-                "%d\n",
-                "SAMPLER?!\n",
-                "SAMPLER?!\n",
-                "SAMPLER?!\n",
-                "SAMPLER?!\n",
-                "SAMPLER?!\n",
-                "%d\n",
-                "%d\n",
-                "%X\n"
+                "%X ",
+                "%d ",
+                "%d ",
+                "%.2f ",
+                "%d ",
+                "%d ",
+                "%d ",
+                "%d ",
+                "%d ",
+                "%d ",
+                "SAMPLER?! ",
+                "SAMPLER?! ",
+                "SAMPLER?! ",
+                "SAMPLER?! ",
+                "SAMPLER?! ",
+                "%d ",
+                "%d ",
+                "%X "
             };
-            if (value->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT)
-                printf(prints[value->type.parameter_type], value->valuesF[i]);
-            else
-                printf(prints[value->type.parameter_type], value->valuesI[i]);
-        } // for
+            for (r = 0; r < value->type.rows; r++)
+            {
+                do_indent(indent + 2);
+                for (c = 0; c < value->type.columns; c++)
+                {
+                    const int offset = (i * value->type.rows * 4) + (r * 4) + c;
+                    if (value->type.parameter_type == MOJOSHADER_SYMTYPE_FLOAT)
+                        printf(prints[value->type.parameter_type], value->valuesF[offset]);
+                    else
+                        printf(prints[value->type.parameter_type], value->valuesI[offset]);
+                } // for
+                printf("\n");
+            } // for
+        } while (++i < value->type.elements);
     } // else
 } // print_value