ir_to_mesa: Generate gl_program_parameter list by walking the GLSL IR.
authorIan Romanick <ian.d.romanick@intel.com>
Sat, 10 Sep 2011 01:27:36 +0000 (18:27 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Wed, 19 Oct 2011 00:26:38 +0000 (17:26 -0700)
Generate the program parameters list by walking the IR instead of by
walking the list of linked uniforms.  This simplifies the code quite a
bit, and is probably a bit more correct.  The list of linked uniforms
should really only be used by the GL API to interact with the
application.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Cc: Bryan Cain <bryancain3@gmail.com>
Cc: Eric Anholt <eric@anholt.net>
src/mesa/program/ir_to_mesa.cpp
src/mesa/program/ir_to_mesa.h

index 8330bc501a22152c49481465996def7d140d7611..fecab50f753efb7df3cf38ca59c07d8cfe3ab361 100644 (file)
@@ -2588,121 +2588,83 @@ check_resources(const struct gl_context *ctx,
 }
 
 
-
-struct uniform_sort {
-   struct gl_uniform *u;
-   int pos;
-};
-
-/* The shader_program->Uniforms list is almost sorted in increasing
- * uniform->{Frag,Vert}Pos locations, but not quite when there are
- * uniforms shared between targets.  We need to add parameters in
- * increasing order for the targets.
- */
 static int
-sort_uniforms(const void *a, const void *b)
-{
-   struct uniform_sort *u1 = (struct uniform_sort *)a;
-   struct uniform_sort *u2 = (struct uniform_sort *)b;
-
-   return u1->pos - u2->pos;
-}
-
-/* Add the uniforms to the parameters.  The linker chose locations
- * in our parameters lists (which weren't created yet), which the
- * uniforms code will use to poke values into our parameters list
- * when uniforms are updated.
- */
-static void
-add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
-                               struct gl_shader *shader,
-                               struct gl_program *prog)
+add_uniform_to_shader(ir_variable *var,
+                     struct gl_program_parameter_list *params,
+                     unsigned int &next_sampler)
 {
-   unsigned int i;
-   unsigned int next_sampler = 0, num_uniforms = 0;
-   struct uniform_sort *sorted_uniforms;
+   const glsl_type *type = var->type;
+   unsigned int size;
 
-   sorted_uniforms = ralloc_array(NULL, struct uniform_sort,
-                                 shader_program->Uniforms->NumUniforms);
+   if (type->is_vector() || type->is_scalar()) {
+      size = type->vector_elements;
+   } else {
+      size = type_size(type) * 4;
+   }
 
-   for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
-      struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
-      int parameter_index = -1;
+   gl_register_file file;
+   if (type->is_sampler() ||
+       (type->is_array() && type->fields.array->is_sampler())) {
+      file = PROGRAM_SAMPLER;
+   } else {
+      file = PROGRAM_UNIFORM;
+   }
 
-      switch (shader->Type) {
-      case GL_VERTEX_SHADER:
-        parameter_index = uniform->VertPos;
-        break;
-      case GL_FRAGMENT_SHADER:
-        parameter_index = uniform->FragPos;
-        break;
-      case GL_GEOMETRY_SHADER:
-        parameter_index = uniform->GeomPos;
-        break;
-      }
+   int index = _mesa_lookup_parameter_index(params, -1, var->name);
+   if (index < 0) {
+      index = _mesa_add_parameter(params, file,
+                                 var->name, size, type->gl_type,
+                                 NULL, NULL, 0x0);
 
-      /* Only add uniforms used in our target. */
-      if (parameter_index != -1) {
-        sorted_uniforms[num_uniforms].pos = parameter_index;
-        sorted_uniforms[num_uniforms].u = uniform;
-        num_uniforms++;
+      /* Sampler uniform values are stored in prog->SamplerUnits,
+       * and the entry in that array is selected by this index we
+       * store in ParameterValues[].
+       */
+      if (file == PROGRAM_SAMPLER) {
+        for (unsigned int j = 0; j < size / 4; j++)
+           params->ParameterValues[index + j][0].f = next_sampler++;
       }
    }
 
-   qsort(sorted_uniforms, num_uniforms, sizeof(struct uniform_sort),
-        sort_uniforms);
-
-   for (i = 0; i < num_uniforms; i++) {
-      struct gl_uniform *uniform = sorted_uniforms[i].u;
-      int parameter_index = sorted_uniforms[i].pos;
-      const glsl_type *type = uniform->Type;
-      unsigned int size;
-
-      if (type->is_vector() ||
-         type->is_scalar()) {
-        size = type->vector_elements;
-      } else {
-        size = type_size(type) * 4;
-      }
+   return index;
+}
 
-      gl_register_file file;
-      if (type->is_sampler() ||
-         (type->is_array() && type->fields.array->is_sampler())) {
-        file = PROGRAM_SAMPLER;
-      } else {
-        file = PROGRAM_UNIFORM;
-      }
+/**
+ * Generate the program parameters list for the user uniforms in a shader
+ *
+ * \param shader_program Linked shader program.  This is only used to
+ *                       emit possible link errors to the info log.
+ * \param sh             Shader whose uniforms are to be processed.
+ * \param params         Parameter list to be filled in.
+ */
+void
+_mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
+                                           *shader_program,
+                                           struct gl_shader *sh,
+                                           struct gl_program_parameter_list
+                                           *params)
+{
+   unsigned int next_sampler = 0;
 
-      GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
-                                                uniform->Name);
+   foreach_list(node, sh->ir) {
+      ir_variable *var = ((ir_instruction *) node)->as_variable();
 
-      if (index < 0) {
-        index = _mesa_add_parameter(prog->Parameters, file,
-                                    uniform->Name, size, type->gl_type,
-                                    NULL, NULL, 0x0);
+      if ((var == NULL) || (var->mode != ir_var_uniform)
+         || (strncmp(var->name, "gl_", 3) == 0))
+        continue;
 
-        /* Sampler uniform values are stored in prog->SamplerUnits,
-         * and the entry in that array is selected by this index we
-         * store in ParameterValues[].
-         */
-        if (file == PROGRAM_SAMPLER) {
-           for (unsigned int j = 0; j < size / 4; j++)
-              prog->Parameters->ParameterValues[index + j][0].f = next_sampler++;
-        }
+      int loc = add_uniform_to_shader(var, params, next_sampler);
 
-        /* The location chosen in the Parameters list here (returned
-         * from _mesa_add_uniform) has to match what the linker chose.
-         */
-        if (index != parameter_index) {
-           linker_error(shader_program,
-                        "Allocation of uniform `%s' to target failed "
-                        "(%d vs %d)\n",
-                        uniform->Name, index, parameter_index);
-        }
+      /* The location chosen in the Parameters list here (returned from
+       * _mesa_add_parameter) has to match what the linker chose.
+       */
+      if (var->location != loc) {
+        linker_error(shader_program,
+                     "Allocation of uniform `%s' to target failed "
+                     "(%d vs %d)\n",
+                     var->name, loc, var->location);
       }
    }
-
-   ralloc_free(sorted_uniforms);
 }
 
 static void
@@ -3046,7 +3008,8 @@ get_mesa_program(struct gl_context *ctx,
    v.shader_program = shader_program;
    v.options = options;
 
-   add_uniforms_to_parameters_list(shader_program, shader, prog);
+   _mesa_generate_parameters_list_for_uniforms(shader_program, shader,
+                                              prog->Parameters);
 
    /* Emit Mesa IR for main(). */
    visit_exec_list(shader->ir, &v);
index 5649282f03fcd184a507aff91c365a48ef15df6b..d046b0fcf9bd19bfd82cf94b651b8aba02fb32fa 100644 (file)
@@ -38,4 +38,11 @@ GLboolean _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program
 
 #ifdef __cplusplus
 }
+
+void
+_mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
+                                           *shader_program,
+                                           struct gl_shader *sh,
+                                           struct gl_program_parameter_list
+                                           *params);
 #endif