Mesa (master): glsl: Set up uniform initializers by walking the shaders after linking.

Eric Anholt anholt at kemper.freedesktop.org
Tue Aug 24 23:38:20 UTC 2010


Module: Mesa
Branch: master
Commit: 2f5bf20e44d509fa3afbe2cfbb9bb65347daea6a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=2f5bf20e44d509fa3afbe2cfbb9bb65347daea6a

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Aug 24 15:43:56 2010 -0700

glsl: Set up uniform initializers by walking the shaders after linking.

Previously, uniform initializers were handled by ir_to_mesa as it made
its Parameters list.  However, uniform values are global to all
shaders, and the value set in one Parameters list wasn't propagated to
the other gl_program->Parameters lists.  By going back through the
general Mesa uniform handling, we make sure that all gl_programs get
updated values, and also successfully separate uniform initializer
handling from ir_to_mesa gl_program generation.

Fixes:
glsl-uniform-initializer-5.

---

 src/mesa/main/uniforms.c        |  108 +++++++++++++----------
 src/mesa/main/uniforms.h        |   15 +++-
 src/mesa/program/ir_to_mesa.cpp |  180 +++++++++++++++++++++++----------------
 3 files changed, 181 insertions(+), 122 deletions(-)

diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index d68a776..a5d7da5 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -454,17 +454,12 @@ _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
  * The return value will encode two values, the uniform location and an
  * offset (used for arrays, structs).
  */
-static GLint
-_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
+GLint
+_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg,
+			   const GLchar *name)
 {
    GLint offset = 0, location = -1;
 
-   struct gl_shader_program *shProg =
-      _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
-
-   if (!shProg)
-      return -1;
-
    if (shProg->LinkStatus == GL_FALSE) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
       return -1;
@@ -751,11 +746,11 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program,
 /**
  * Called via glUniform*() functions.
  */
-static void
-_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
+void
+_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shProg,
+	      GLint location, GLsizei count,
               const GLvoid *values, GLenum type)
 {
-   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
    struct gl_uniform *uniform;
    GLint elems, offset;
 
@@ -923,12 +918,12 @@ set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
  * Called by glUniformMatrix*() functions.
  * Note: cols=2, rows=4  ==>  array[2] of vec4
  */
-static void
-_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
+void
+_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg,
+		     GLint cols, GLint rows,
                      GLint location, GLsizei count,
                      GLboolean transpose, const GLfloat *values)
 {
-   struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
    struct gl_uniform *uniform;
    GLint offset;
 
@@ -999,7 +994,7 @@ void GLAPIENTRY
 _mesa_Uniform1fARB(GLint location, GLfloat v0)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, 1, &v0, GL_FLOAT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_FLOAT);
 }
 
 void GLAPIENTRY
@@ -1009,7 +1004,7 @@ _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
    GLfloat v[2];
    v[0] = v0;
    v[1] = v1;
-   _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC2);
 }
 
 void GLAPIENTRY
@@ -1020,7 +1015,7 @@ _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
    v[0] = v0;
    v[1] = v1;
    v[2] = v2;
-   _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC3);
 }
 
 void GLAPIENTRY
@@ -1033,14 +1028,14 @@ _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
    v[1] = v1;
    v[2] = v2;
    v[3] = v3;
-   _mesa_uniform(ctx, location, 1, v, GL_FLOAT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1iARB(GLint location, GLint v0)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, 1, &v0, GL_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_INT);
 }
 
 void GLAPIENTRY
@@ -1050,7 +1045,7 @@ _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
    GLint v[2];
    v[0] = v0;
    v[1] = v1;
-   _mesa_uniform(ctx, location, 1, v, GL_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC2);
 }
 
 void GLAPIENTRY
@@ -1061,7 +1056,7 @@ _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
    v[0] = v0;
    v[1] = v1;
    v[2] = v2;
-   _mesa_uniform(ctx, location, 1, v, GL_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC3);
 }
 
 void GLAPIENTRY
@@ -1073,63 +1068,63 @@ _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
    v[1] = v1;
    v[2] = v2;
    v[3] = v3;
-   _mesa_uniform(ctx, location, 1, v, GL_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT);
 }
 
 void GLAPIENTRY
 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC2);
 }
 
 void GLAPIENTRY
 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC3);
 }
 
 void GLAPIENTRY
 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_FLOAT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT);
 }
 
 void GLAPIENTRY
 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC2);
 }
 
 void GLAPIENTRY
 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC3);
 }
 
 void GLAPIENTRY
 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC4);
 }
 
 
@@ -1138,7 +1133,7 @@ void GLAPIENTRY
 _mesa_Uniform1ui(GLint location, GLuint v0)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, 1, &v0, GL_UNSIGNED_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_UNSIGNED_INT);
 }
 
 void GLAPIENTRY
@@ -1148,7 +1143,7 @@ _mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1)
    GLuint v[2];
    v[0] = v0;
    v[1] = v1;
-   _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC2);
 }
 
 void GLAPIENTRY
@@ -1159,7 +1154,7 @@ _mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
    v[0] = v0;
    v[1] = v1;
    v[2] = v2;
-   _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC3);
 }
 
 void GLAPIENTRY
@@ -1171,35 +1166,35 @@ _mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
    v[1] = v1;
    v[2] = v2;
    v[3] = v3;
-   _mesa_uniform(ctx, location, 1, v, GL_UNSIGNED_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC4);
 }
 
 void GLAPIENTRY
 _mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT);
 }
 
 void GLAPIENTRY
 _mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC2);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC2);
 }
 
 void GLAPIENTRY
 _mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC3);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC3);
 }
 
 void GLAPIENTRY
 _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform(ctx, location, count, value, GL_UNSIGNED_INT_VEC4);
+   _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC4);
 }
 
 
@@ -1209,7 +1204,8 @@ _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 2, 2, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			2, 2, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1217,7 +1213,8 @@ _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 3, 3, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			3, 3, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1225,7 +1222,8 @@ _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 4, 4, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			4, 4, location, count, transpose, value);
 }
 
 
@@ -1237,7 +1235,8 @@ _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 2, 3, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			2, 3, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1245,7 +1244,8 @@ _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 3, 2, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			3, 2, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1253,7 +1253,8 @@ _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 2, 4, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			2, 4, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1261,7 +1262,8 @@ _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 4, 2, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			4, 2, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1269,7 +1271,8 @@ _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 3, 4, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			3, 4, location, count, transpose, value);
 }
 
 void GLAPIENTRY
@@ -1277,7 +1280,8 @@ _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
                          const GLfloat *value)
 {
    GET_CURRENT_CONTEXT(ctx);
-   _mesa_uniform_matrix(ctx, 4, 3, location, count, transpose, value);
+   _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram,
+			4, 3, location, count, transpose, value);
 }
 
 
@@ -1300,8 +1304,16 @@ _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
 GLint GLAPIENTRY
 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
 {
+   struct gl_shader_program *shProg;
+
    GET_CURRENT_CONTEXT(ctx);
-   return _mesa_get_uniform_location(ctx, programObj, name);
+
+   shProg = _mesa_lookup_shader_program_err(ctx, programObj,
+					    "glGetUniformLocation");
+   if (!shProg)
+      return -1;
+
+   return _mesa_get_uniform_location(ctx, shProg, name);
 }
 
 
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index ef98fe1..f823c61 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -150,7 +150,20 @@ _mesa_GetUniformivARB(GLhandleARB, GLint, GLint *);
 extern GLint GLAPIENTRY
 _mesa_GetUniformLocationARB(GLhandleARB, const GLcharARB *);
 
-
+GLint
+_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg,
+			   const GLchar *name);
+
+void
+_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shader_program,
+	      GLint location, GLsizei count,
+              const GLvoid *values, GLenum type);
+
+void
+_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg,
+		     GLint cols, GLint rows,
+                     GLint location, GLsizei count,
+                     GLboolean transpose, const GLfloat *values);
 
 extern void
 _mesa_update_shader_textures_used(struct gl_program *prog);
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index ea2560a..da69d26 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -261,12 +261,10 @@ public:
 			  int mul_operand);
 
    int add_uniform(const char *name,
-		   const glsl_type *type,
-		   ir_constant *constant);
+		   const glsl_type *type);
    void add_aggregate_uniform(ir_instruction *ir,
 			      const char *name,
 			      const struct glsl_type *type,
-			      ir_constant *constant,
 			      struct ir_to_mesa_dst_reg temp);
 
    struct hash_table *sampler_map;
@@ -1307,8 +1305,7 @@ get_builtin_matrix_ref(void *mem_ctx, struct gl_program *prog, ir_variable *var,
 
 int
 ir_to_mesa_visitor::add_uniform(const char *name,
-				const glsl_type *type,
-				ir_constant *constant)
+				const glsl_type *type)
 {
    int len;
 
@@ -1319,65 +1316,11 @@ ir_to_mesa_visitor::add_uniform(const char *name,
       len = type_size(type) * 4;
    }
 
-   float *values = NULL;
-   if (constant && type->is_array()) {
-      values = (float *)malloc(type->length * 4 * sizeof(float));
-
-      assert(type->fields.array->is_scalar() ||
-	     type->fields.array->is_vector() ||
-	     !"FINISHME: uniform array initializers for non-vector");
-
-      for (unsigned int i = 0; i < type->length; i++) {
-	 ir_constant *element = constant->array_elements[i];
-	 unsigned int c;
-
-	 for (c = 0; c < type->fields.array->vector_elements; c++) {
-	    switch (type->fields.array->base_type) {
-	    case GLSL_TYPE_FLOAT:
-	       values[4 * i + c] = element->value.f[c];
-	       break;
-	    case GLSL_TYPE_INT:
-	       values[4 * i + c] = element->value.i[c];
-	       break;
-	    case GLSL_TYPE_UINT:
-	       values[4 * i + c] = element->value.u[c];
-	       break;
-	    case GLSL_TYPE_BOOL:
-	       values[4 * i + c] = element->value.b[c];
-	       break;
-	    default:
-	       assert(!"not reached");
-	    }
-	 }
-      }
-   } else if (constant) {
-      values = (float *)malloc(16 * sizeof(float));
-      for (unsigned int i = 0; i < type->components(); i++) {
-	 switch (type->base_type) {
-	 case GLSL_TYPE_FLOAT:
-	    values[i] = constant->value.f[i];
-	    break;
-	 case GLSL_TYPE_INT:
-	    values[i] = constant->value.i[i];
-	    break;
-	 case GLSL_TYPE_UINT:
-	    values[i] = constant->value.u[i];
-	    break;
-	 case GLSL_TYPE_BOOL:
-	    values[i] = constant->value.b[i];
-	    break;
-	 default:
-	    assert(!"not reached");
-	 }
-      }
-   }
-
    int loc = _mesa_add_uniform(this->prog->Parameters,
 			       name,
 			       len,
 			       type->gl_type,
-			       values);
-   free(values);
+			       NULL);
 
    return loc;
 }
@@ -1389,17 +1332,12 @@ void
 ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir,
 					  const char *name,
 					  const struct glsl_type *type,
-					  ir_constant *constant,
 					  struct ir_to_mesa_dst_reg temp)
 {
    int loc;
 
    if (type->is_record()) {
       void *mem_ctx = talloc_new(NULL);
-      ir_constant *field_constant = NULL;
-
-      if (constant)
-	 field_constant = (ir_constant *)constant->components.get_head();
 
       for (unsigned int i = 0; i < type->length; i++) {
 	 const glsl_type *field_type = type->fields.structure[i].type;
@@ -1407,11 +1345,8 @@ ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir,
 	 add_aggregate_uniform(ir,
 			       talloc_asprintf(mem_ctx, "%s.%s", name,
 					       type->fields.structure[i].name),
-			       field_type, field_constant, temp);
+			       field_type, temp);
 	 temp.index += type_size(field_type);
-
-	 if (constant)
-	    field_constant = (ir_constant *)field_constant->next;
       }
 
       talloc_free(mem_ctx);
@@ -1421,7 +1356,7 @@ ir_to_mesa_visitor::add_aggregate_uniform(ir_instruction *ir,
 
    assert(type->is_vector() || type->is_scalar() || !"FINISHME: other types");
 
-   loc = add_uniform(name, type, constant);
+   loc = add_uniform(name, type);
 
    ir_to_mesa_src_reg uniform(PROGRAM_UNIFORM, loc, type);
 
@@ -1485,14 +1420,12 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
 	    this->variables.push_tail(entry);
 
 	    add_aggregate_uniform(ir->var, ir->var->name, ir->var->type,
-				  ir->var->constant_value,
 				  ir_to_mesa_dst_reg_from_src(temp));
 	    break;
 	 }
 
 	 loc = add_uniform(ir->var->name,
-			   ir->var->type,
-			   ir->var->constant_value);
+			   ir->var->type);
 
 	 /* Always mark the uniform used at this point.  If it isn't
 	  * used, dead code elimination should have nuked the decl already.
@@ -2433,6 +2366,105 @@ link_uniforms_to_shared_uniform_list(struct gl_uniform_list *uniforms,
    }
 }
 
+static void
+set_uniform_initializer(GLcontext *ctx, void *mem_ctx,
+			struct gl_shader_program *shader_program,
+			const char *name, const glsl_type *type,
+			ir_constant *val)
+{
+   if (type->is_record()) {
+      ir_constant *field_constant;
+
+      field_constant = (ir_constant *)val->components.get_head();
+
+      for (unsigned int i = 0; i < type->length; i++) {
+	 const glsl_type *field_type = type->fields.structure[i].type;
+	 const char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name,
+					    type->fields.structure[i].name);
+	 set_uniform_initializer(ctx, mem_ctx, shader_program, field_name,
+				 field_type, field_constant);
+	 field_constant = (ir_constant *)field_constant->next;
+      }
+      return;
+   }
+
+   int loc = _mesa_get_uniform_location(ctx, shader_program, name);
+
+   if (loc == -1) {
+      shader_program->InfoLog =
+	 talloc_asprintf_append(shader_program->InfoLog,
+				"Couldn't find uniform for "
+				"initializer %s\n", name);
+      shader_program->LinkStatus = false;
+      abort();
+   }
+
+   for (unsigned int i = 0; i < (type->is_array() ? type->length : 1); i++) {
+      ir_constant *element;
+      const glsl_type *element_type;
+      if (type->is_array()) {
+	 element = val->array_elements[i];
+	 element_type = type->fields.array;
+      } else {
+	 element = val;
+	 element_type = type;
+      }
+
+      void *values;
+
+      if (element_type->base_type == GLSL_TYPE_BOOL) {
+	 int *conv = talloc_array(mem_ctx, int, element_type->components());
+	 for (unsigned int j = 0; j < element_type->components(); j++) {
+	    conv[j] = element->value.b[j];
+	 }
+	 values = (void *)conv;
+	 element_type = glsl_type::get_instance(GLSL_TYPE_INT,
+						element_type->vector_elements,
+						1);
+      } else {
+	 values = &element->value;
+      }
+
+      if (element_type->is_matrix()) {
+	 _mesa_uniform_matrix(ctx, shader_program,
+			      element_type->matrix_columns,
+			      element_type->vector_elements,
+			      loc, 1, GL_FALSE, (GLfloat *)values);
+	 loc += element_type->matrix_columns;
+      } else {
+	 _mesa_uniform(ctx, shader_program, loc, element_type->matrix_columns,
+		       values, element_type->gl_type);
+	 loc += type_size(element_type);
+      }
+   }
+}
+
+static void
+set_uniform_initializers(GLcontext *ctx,
+			 struct gl_shader_program *shader_program)
+{
+   void *mem_ctx = NULL;
+
+   for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) {
+      struct gl_shader *shader = shader_program->_LinkedShaders[i];
+      foreach_iter(exec_list_iterator, iter, *shader->ir) {
+	 ir_instruction *ir = (ir_instruction *)iter.get();
+	 ir_variable *var = ir->as_variable();
+
+	 if (!var || var->mode != ir_var_uniform || !var->constant_value)
+	    continue;
+
+	 if (!mem_ctx)
+	    mem_ctx = talloc_new(NULL);
+
+	 set_uniform_initializer(ctx, mem_ctx, shader_program, var->name,
+				 var->type, var->constant_value);
+      }
+   }
+
+   talloc_free(mem_ctx);
+}
+
 struct gl_program *
 get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
 		 struct gl_shader *shader)
@@ -2780,6 +2812,8 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
       }
    }
 
+   set_uniform_initializers(ctx, prog);
+
    if (ctx->Shader.Flags & GLSL_DUMP) {
       if (!prog->LinkStatus) {
 	 printf("GLSL shader program %d failed to link\n", prog->Name);




More information about the mesa-commit mailing list