Mesa (master): ir_to_mesa: Add support for samplers in structures.

Eric Anholt anholt at kemper.freedesktop.org
Wed Aug 25 19:40:11 UTC 2010


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

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

ir_to_mesa: Add support for samplers in structures.

Fixes:
glsl-fs-uniform-sampler-struct
glsl-fs-sampler-numbering-3
Bug #29690

---

 src/mesa/program/ir_to_mesa.cpp |  231 ++++++++++++++++++++------------------
 1 files changed, 122 insertions(+), 109 deletions(-)

diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 4a4278e..7fb5974 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -173,6 +173,7 @@ public:
 
    GLcontext *ctx;
    struct gl_program *prog;
+   struct gl_shader_program *shader_program;
 
    int next_temp;
 
@@ -260,10 +261,7 @@ public:
    GLboolean try_emit_mad(ir_expression *ir,
 			  int mul_operand);
 
-   struct hash_table *sampler_map;
-
-   void set_sampler_location(ir_variable *sampler, int location);
-   int get_sampler_location(ir_variable *sampler);
+   int get_sampler_uniform_value(ir_dereference *deref);
 
    void *mem_ctx;
 };
@@ -368,25 +366,6 @@ ir_to_mesa_visitor::ir_to_mesa_emit_op0(ir_instruction *ir,
 			      ir_to_mesa_undef);
 }
 
-void
-ir_to_mesa_visitor::set_sampler_location(ir_variable *sampler, int location)
-{
-   if (this->sampler_map == NULL) {
-      this->sampler_map = hash_table_ctor(0, hash_table_pointer_hash,
-					  hash_table_pointer_compare);
-   }
-
-   hash_table_insert(this->sampler_map, (void *)(uintptr_t)location, sampler);
-}
-
-int
-ir_to_mesa_visitor::get_sampler_location(ir_variable *sampler)
-{
-   void *result = hash_table_find(this->sampler_map, sampler);
-
-   return (int)(uintptr_t)result;
-}
-
 inline ir_to_mesa_dst_reg
 ir_to_mesa_dst_reg_from_src(ir_to_mesa_src_reg reg)
 {
@@ -1308,27 +1287,6 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
 	 if (entry)
 	    break;
 
-	 if (ir->var->type->base_type == GLSL_TYPE_SAMPLER ||
-	     (ir->var->type->base_type == GLSL_TYPE_ARRAY &&
-	      ir->var->type->fields.array->base_type == GLSL_TYPE_SAMPLER)) {
-	    int array_length;
-
-	    if (ir->var->type->base_type == GLSL_TYPE_ARRAY)
-	       array_length = ir->var->type->length;
-	    else
-	       array_length = 1;
-	    int sampler = _mesa_add_sampler(this->prog->Parameters,
-					    ir->var->name,
-					    ir->var->type->gl_type,
-					    array_length);
-	    set_sampler_location(ir->var, sampler);
-
-	    entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_SAMPLER,
-						  sampler);
-	    this->variables.push_tail(entry);
-	    break;
-	 }
-
 	 entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_UNIFORM,
 					       ir->var->location);
 	 this->variables.push_tail(entry);
@@ -1825,6 +1783,91 @@ ir_to_mesa_visitor::visit(ir_call *ir)
    this->result = entry->return_reg;
 }
 
+class get_sampler_name : public ir_hierarchical_visitor
+{
+public:
+   get_sampler_name(ir_to_mesa_visitor *mesa, ir_dereference *last)
+   {
+      this->mem_ctx = mesa->mem_ctx;
+      this->mesa = mesa;
+      this->name = NULL;
+      this->offset = 0;
+      this->last = last;
+   }
+
+   virtual ir_visitor_status visit(ir_dereference_variable *ir)
+   {
+      this->name = ir->var->name;
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_leave(ir_dereference_record *ir)
+   {
+      this->name = talloc_asprintf(mem_ctx, "%s.%s", name, ir->field);
+      return visit_continue;
+   }
+
+   virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
+   {
+      ir_constant *index = ir->array_index->as_constant();
+      int i;
+
+      if (index) {
+	 i = index->value.i[0];
+      } else {
+	 /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
+	  * while GLSL 1.30 requires that the array indices be
+	  * constant integer expressions.  We don't expect any driver
+	  * to actually work with a really variable array index, so
+	  * all that would work would be an unrolled loop counter that ends
+	  * up being constant above.
+	  */
+	 mesa->shader_program->InfoLog =
+	    talloc_asprintf_append(mesa->shader_program->InfoLog,
+				   "warning: Variable sampler array index "
+				   "unsupported.\nThis feature of the language "
+				   "was removed in GLSL 1.20 and is unlikely "
+				   "to be supported for 1.10 in Mesa.\n");
+	 i = 0;
+      }
+      if (ir != last) {
+	 this->name = talloc_asprintf(mem_ctx, "%s[%d]", name, i);
+      } else {
+	 offset = i;
+      }
+      return visit_continue;
+   }
+
+   ir_to_mesa_visitor *mesa;
+   const char *name;
+   void *mem_ctx;
+   int offset;
+   ir_dereference *last;
+};
+
+int
+ir_to_mesa_visitor::get_sampler_uniform_value(ir_dereference *sampler)
+{
+   get_sampler_name getname(this, sampler);
+
+   sampler->accept(&getname);
+
+   GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
+					      getname.name);
+
+   if (index < 0) {
+      this->shader_program->InfoLog =
+	 talloc_asprintf_append(this->shader_program->InfoLog,
+				"failed to find sampler named %s.\n",
+				getname.name);
+      this->shader_program->LinkStatus = GL_FALSE;
+      return 0;
+   }
+
+   index += getname.offset;
+
+   return this->prog->Parameters->ParameterValues[index][0];
+}
 
 void
 ir_to_mesa_visitor::visit(ir_texture *ir)
@@ -1925,34 +1968,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir)
    if (ir->shadow_comparitor)
       inst->tex_shadow = GL_TRUE;
 
-   ir_variable *sampler = ir->sampler->variable_referenced();
+   inst->sampler = get_sampler_uniform_value(ir->sampler);
 
-   /* generate the mapping, remove when we generate storage at
-    * declaration time
-    */
-   ir->sampler->accept(this);
-
-   inst->sampler = get_sampler_location(sampler);
-
-   ir_dereference_array *sampler_array = ir->sampler->as_dereference_array();
-   if (sampler_array) {
-      ir_constant *array_index =
-	 sampler_array->array_index->constant_expression_value();
-
-      /* GLSL 1.10 and 1.20 allowed variable sampler array indices,
-       * while GLSL 1.30 requires that the array indices be constant
-       * integer expressions.  We don't expect any driver to actually
-       * work with a really variable array index, and in 1.20 all that
-       * would work would be an unrolled loop counter, so assert that
-       * we ended up with a constant at least..
-       */
-      assert(array_index);
-      inst->sampler += array_index->value.i[0];
-   }
-
-   const glsl_type *sampler_type = sampler->type;
-   while (sampler_type->base_type == GLSL_TYPE_ARRAY)
-      sampler_type = sampler_type->fields.array;
+   const glsl_type *sampler_type = ir->sampler->type;
 
    switch (sampler_type->sampler_dimensionality) {
    case GLSL_SAMPLER_DIM_1D:
@@ -2066,7 +2084,6 @@ ir_to_mesa_visitor::ir_to_mesa_visitor()
    result.file = PROGRAM_UNDEFINED;
    next_temp = 1;
    next_signature_id = 1;
-   sampler_map = NULL;
    current_function = NULL;
    mem_ctx = talloc_new(NULL);
 }
@@ -2074,8 +2091,6 @@ ir_to_mesa_visitor::ir_to_mesa_visitor()
 ir_to_mesa_visitor::~ir_to_mesa_visitor()
 {
    talloc_free(mem_ctx);
-   if (this->sampler_map)
-      hash_table_dtor(this->sampler_map);
 }
 
 static struct prog_src_register
@@ -2222,12 +2237,6 @@ count_resources(struct gl_program *prog)
    for (i = 0; i < prog->NumInstructions; i++) {
       struct prog_instruction *inst = &prog->Instructions[i];
 
-      /* Instead of just using the uniform's value to map to a
-       * sampler, Mesa first allocates a separate number for the
-       * sampler (_mesa_add_sampler), then we reindex it down to a
-       * small integer (sampler_map[], SamplersUsed), then that gets
-       * mapped to the uniform's value, and we get an actual sampler.
-       */
       if (_mesa_is_tex_instruction(inst->Opcode)) {
 	 prog->SamplerTargets[inst->TexSrcUnit] =
 	    (gl_texture_index)inst->TexSrcTarget;
@@ -2252,6 +2261,7 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
 				struct gl_program *prog)
 {
    unsigned int i;
+   unsigned int next_sampler = 0;
 
    for (i = 0; i < shader_program->Uniforms->NumUniforms; i++) {
       struct gl_uniform *uniform = shader_program->Uniforms->Uniforms + i;
@@ -2282,39 +2292,41 @@ add_uniforms_to_parameters_list(struct gl_shader_program *shader_program,
 	 size = type_size(type) * 4;
       }
 
+      gl_register_file file;
       if (type->is_sampler() ||
 	  (type->is_array() && type->fields.array->is_sampler())) {
-	 int array_length;
+	 file = PROGRAM_SAMPLER;
+      } else {
+	 file = PROGRAM_UNIFORM;
+      }
 
-	 if (type->is_array())
-	    array_length = type->length;
-	 else
-	    array_length = 1;
+      GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
+						 uniform->Name);
 
-	 (void)_mesa_add_sampler(prog->Parameters,
-				 uniform->Name,
-				 type->gl_type,
-				 array_length);
-      } else {
-	 GLint index = _mesa_lookup_parameter_index(prog->Parameters, -1,
-						    uniform->Name);
-
-	 if (index < 0) {
-	    index = _mesa_add_parameter(prog->Parameters, PROGRAM_UNIFORM,
-					uniform->Name, size, type->gl_type,
-					NULL, NULL, 0x0);
-
-	    /* The location chosen in the Parameters list here (returned
-	     * from _mesa_add_uniform) has to match what the linker chose.
-	     */
-	    if (index != parameter_index) {
-	       shader_program->InfoLog =
-		  talloc_asprintf_append(shader_program->InfoLog,
-					 "Allocation of uniform `%s' to target "
-					 "failed (%d vs %d)\n", uniform->Name,
-					 index, parameter_index);
-	       shader_program->LinkStatus = false;
-	    }
+      if (index < 0) {
+	 index = _mesa_add_parameter(prog->Parameters, file,
+				     uniform->Name, size, type->gl_type,
+				     NULL, NULL, 0x0);
+
+	 /* 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] = 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) {
+	    shader_program->InfoLog =
+	       talloc_asprintf_append(shader_program->InfoLog,
+				      "Allocation of uniform `%s' to target "
+				      "failed (%d vs %d)\n", uniform->Name,
+				      index, parameter_index);
+	    shader_program->LinkStatus = false;
 	 }
       }
    }
@@ -2456,6 +2468,7 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
    prog->Attributes = _mesa_new_parameter_list();
    v.ctx = ctx;
    v.prog = prog;
+   v.shader_program = shader_program;
 
    add_uniforms_to_parameters_list(shader_program, shader, prog);
 




More information about the mesa-commit mailing list