[Mesa-dev] [PATCH 2/3] glsl: Calcluate Mesa state slots in front-end instead of back-end

Ian Romanick idr at freedesktop.org
Fri Mar 25 11:40:49 PDT 2011


From: Ian Romanick <ian.d.romanick at intel.com>

This should be the last bit of infrastructure changes before
generating GLSL IR for assembly shaders.

This commit leaves some odd code formatting in ir_to_mesa and brw_fs.
This was done to minimize whitespace changes / reindentation in some
loops.  The following commit will restore formatting sanity.
---
 src/glsl/ir.h                        |   26 ++++++++++++++++
 src/glsl/ir_clone.cpp                |   12 +++++++
 src/glsl/ir_variable.cpp             |   46 ++++++++++++++++++++++++++--
 src/glsl/linker.cpp                  |   13 ++++++++
 src/mesa/drivers/dri/i965/brw_fs.cpp |   37 ++++-------------------
 src/mesa/program/ir_to_mesa.cpp      |   56 ++++++++++-----------------------
 6 files changed, 117 insertions(+), 73 deletions(-)

diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 39d4ebc..a419843 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -253,6 +253,16 @@ enum ir_depth_layout {
 const char*
 depth_layout_string(ir_depth_layout layout);
 
+/**
+ * Description of built-in state associated with a uniform
+ *
+ * \sa ir_variable::state_slots
+ */
+struct ir_state_slot {
+   int tokens[5];
+   int swizzle;
+};
+
 class ir_variable : public ir_instruction {
 public:
    ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
@@ -386,6 +396,22 @@ public:
    int location;
 
    /**
+    * Built-in state that backs this uniform
+    *
+    * Once set at variable creation, \c state_slots must remain invariant.
+    * This is because, ideally, this array would be shared by all clones of
+    * this variable in the IR tree.  In other words, we'd really like for it
+    * to be a fly-weight.
+    *
+    * If the variable is not a uniform, \c num_state_slots will be zero and
+    * \c state_slots will be \c NULL.
+    */
+   /*@{*/
+   unsigned num_state_slots;    /**< Number of state slots used */
+   ir_state_slot *state_slots;  /**< State descriptors. */
+   /*@}*/
+
+   /**
     * Emit a warning if this variable is accessed.
     */
    const char *warn_extension;
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index 2c0574d..069bb85 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -53,6 +53,18 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const
    var->origin_upper_left = this->origin_upper_left;
    var->pixel_center_integer = this->pixel_center_integer;
    var->explicit_location = this->explicit_location;
+
+   var->num_state_slots = this->num_state_slots;
+   if (this->state_slots) {
+      /* FINISHME: This really wants to use something like talloc_reference, but
+       * FINISHME: ralloc doesn't have any similar function.
+       */
+      var->state_slots = ralloc_array(var, ir_state_slot,
+				      this->num_state_slots);
+      memcpy(var->state_slots, this->state_slots,
+	     sizeof(this->state_slots[0]) * var->num_state_slots);
+   }
+
    if (this->explicit_location)
       var->location = this->location;
 
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
index c271525..94efebb 100644
--- a/src/glsl/ir_variable.cpp
+++ b/src/glsl/ir_variable.cpp
@@ -327,7 +327,43 @@ static ir_variable *
 add_uniform(exec_list *instructions, glsl_symbol_table *symtab,
 	    const char *name, const glsl_type *type)
 {
-   return add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
+   ir_variable *const uni =
+      add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
+
+   unsigned i;
+   for (i = 0; _mesa_builtin_uniform_desc[i].name != NULL; i++) {
+      if (strcmp(_mesa_builtin_uniform_desc[i].name, name) == 0) {
+	 break;
+      }
+   }
+
+   assert(_mesa_builtin_uniform_desc[i].name != NULL);
+   const struct gl_builtin_uniform_desc* const statevar =
+      &_mesa_builtin_uniform_desc[i];
+
+   const unsigned array_count = type->is_array() ? type->length : 1;
+   uni->num_state_slots = array_count * statevar->num_elements;
+
+   ir_state_slot *slots =
+      ralloc_array(uni, ir_state_slot, uni->num_state_slots);
+
+   uni->state_slots = slots;
+
+   for (unsigned a = 0; a < array_count; a++) {
+      for (unsigned i = 0; i < statevar->num_elements; i++) {
+	 struct gl_builtin_uniform_element *element = &statevar->elements[i];
+
+	 memcpy(slots->tokens, element->tokens, sizeof(element->tokens));
+	 if (type->is_array()) {
+	    slots->tokens[1] = a;
+	 }
+
+	 slots->swizzle = element->swizzle;
+	 slots++;
+      }
+   }
+
+   return uni;
 }
 
 static void
@@ -341,8 +377,12 @@ add_builtin_variable(exec_list *instructions, glsl_symbol_table *symtab,
 
    assert(type != NULL);
 
-   add_variable(instructions, symtab, proto->name, type, proto->mode,
-		proto->slot);
+   if (proto->mode == ir_var_uniform) {
+      add_uniform(instructions, symtab, proto->name, type);
+   } else {
+      add_variable(instructions, symtab, proto->name, type, proto->mode,
+		   proto->slot);
+   }
 }
 
 static void
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 7db5c5e..1749235 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -994,6 +994,19 @@ update_array_sizes(struct gl_shader_program *prog)
 	 }
 
 	 if (size + 1 != var->type->fields.array->length) {
+	    /* If this is a built-in uniform (i.e., it's backed by some
+	     * fixed-function state), adjust the number of state slots to
+	     * match the new array size.  The number of slots per array entry
+	     * is not known.  It seems saft to assume that the total number of
+	     * slots is an integer multiple of the number of array elements.
+	     * Determine the number of slots per array element by dividing by
+	     * the old (total) size.
+	     */
+	    if (var->num_state_slots > 0) {
+	       var->num_state_slots = (size + 1)
+		  * (var->num_state_slots / var->type->length);
+	    }
+
 	    var->type = glsl_type::get_array_instance(var->type->fields.array,
 						      size + 1);
 	    /* FINISHME: We should update the types of array
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 74596e9..705a223 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -399,41 +399,16 @@ fs_visitor::setup_uniform_values(int loc, const glsl_type *type)
 void
 fs_visitor::setup_builtin_uniform_values(ir_variable *ir)
 {
-   const struct gl_builtin_uniform_desc *statevar = NULL;
-
-   for (unsigned int i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
-      statevar = &_mesa_builtin_uniform_desc[i];
-      if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
-	 break;
-   }
-
-   if (!statevar->name) {
-      fail("Failed to find builtin uniform `%s'\n", ir->name);
-      return;
-   }
-
-   int array_count;
-   if (ir->type->is_array()) {
-      array_count = ir->type->length;
-   } else {
-      array_count = 1;
-   }
-
-   for (int a = 0; a < array_count; a++) {
-      for (unsigned int i = 0; i < statevar->num_elements; i++) {
-	 struct gl_builtin_uniform_element *element = &statevar->elements[i];
-	 int tokens[STATE_LENGTH];
-
-	 memcpy(tokens, element->tokens, sizeof(element->tokens));
-	 if (ir->type->is_array()) {
-	    tokens[1] = a;
-	 }
+   const ir_state_slot *const slots = ir->state_slots;
+   assert(ir->state_slots != NULL);
 
+   {
+      for (unsigned int i = 0; i < ir->num_state_slots; i++) {
 	 /* This state reference has already been setup by ir_to_mesa,
 	  * but we'll get the same index back here.
 	  */
 	 int index = _mesa_add_state_reference(this->fp->Base.Parameters,
-					       (gl_state_index *)tokens);
+					       (gl_state_index *)slots[i].tokens);
 
 	 /* Add each of the unique swizzles of the element as a
 	  * parameter.  This'll end up matching the expected layout of
@@ -441,7 +416,7 @@ fs_visitor::setup_builtin_uniform_values(ir_variable *ir)
 	  */
 	 int last_swiz = -1;
 	 for (unsigned int j = 0; j < 4; j++) {
-	    int swiz = GET_SWZ(element->swizzle, j);
+	    int swiz = GET_SWZ(slots[i].swizzle, j);
 	    if (swiz == last_swiz)
 	       break;
 	    last_swiz = swiz;
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 17e0f99..4cca2b7 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -754,27 +754,8 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
 
    if (ir->mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) {
       unsigned int i;
-      const struct gl_builtin_uniform_desc *statevar;
-
-      for (i = 0; _mesa_builtin_uniform_desc[i].name; i++) {
-	 if (strcmp(ir->name, _mesa_builtin_uniform_desc[i].name) == 0)
-	    break;
-      }
-
-      if (!_mesa_builtin_uniform_desc[i].name) {
-	 fail_link(this->shader_program,
-		   "Failed to find builtin uniform `%s'\n", ir->name);
-	 return;
-      }
-
-      statevar = &_mesa_builtin_uniform_desc[i];
-
-      int array_count;
-      if (ir->type->is_array()) {
-	 array_count = ir->type->length;
-      } else {
-	 array_count = 1;
-      }
+      const ir_state_slot *const slots = ir->state_slots;
+      assert(ir->state_slots != NULL);
 
       /* Check if this statevar's setup in the STATE file exactly
        * matches how we'll want to reference it as a
@@ -782,21 +763,27 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
        * temporary storage and hope that it'll get copy-propagated
        * out.
        */
-      for (i = 0; i < statevar->num_elements; i++) {
-	 if (statevar->elements[i].swizzle != SWIZZLE_XYZW) {
+      for (i = 0; i < ir->num_state_slots; i++) {
+	 if (slots[i].swizzle != SWIZZLE_XYZW) {
 	    break;
 	 }
       }
 
       struct variable_storage *storage;
       ir_to_mesa_dst_reg dst;
-      if (i == statevar->num_elements) {
+      if (i == ir->num_state_slots) {
 	 /* We'll set the index later. */
 	 storage = new(mem_ctx) variable_storage(ir, PROGRAM_STATE_VAR, -1);
 	 this->variables.push_tail(storage);
 
 	 dst = ir_to_mesa_undef_dst;
       } else {
+	 /* The variable_storage constructor allocates slots based on the size
+	  * of the type.  However, this had better match the number of state
+	  * elements that we're going to copy into the new temporary.
+	  */
+	 assert(ir->num_state_slots == type_size(ir->type));
+
 	 storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
 						 this->next_temp);
 	 this->variables.push_tail(storage);
@@ -808,29 +795,20 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
       }
 
 
-      for (int a = 0; a < array_count; a++) {
-	 for (unsigned int i = 0; i < statevar->num_elements; i++) {
-	    struct gl_builtin_uniform_element *element = &statevar->elements[i];
-	    int tokens[STATE_LENGTH];
-
-	    memcpy(tokens, element->tokens, sizeof(element->tokens));
-	    if (ir->type->is_array()) {
-	       tokens[1] = a;
-	    }
-
+      {
+	 for (unsigned int i = 0; i < ir->num_state_slots; i++) {
 	    int index = _mesa_add_state_reference(this->prog->Parameters,
-						  (gl_state_index *)tokens);
+						  (gl_state_index *)slots[i].tokens);
 
 	    if (storage->file == PROGRAM_STATE_VAR) {
 	       if (storage->index == -1) {
 		  storage->index = index;
 	       } else {
-		  assert(index ==
-                         (int)(storage->index + a * statevar->num_elements + i));
+		  assert(index == storage->index + (int)i);
 	       }
 	    } else {
 	       ir_to_mesa_src_reg src(PROGRAM_STATE_VAR, index, NULL);
-	       src.swizzle = element->swizzle;
+	       src.swizzle = slots[i].swizzle;
 	       ir_to_mesa_emit_op1(ir, OPCODE_MOV, dst, src);
 	       /* even a float takes up a whole vec4 reg in a struct/array. */
 	       dst.index++;
@@ -838,7 +816,7 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
 	 }
       }
       if (storage->file == PROGRAM_TEMPORARY &&
-	  dst.index != storage->index + type_size(ir->type)) {
+	  dst.index != storage->index + ir->num_state_slots) {
 	 fail_link(this->shader_program,
 		   "failed to load builtin uniform `%s'  (%d/%d regs loaded)\n",
 		   ir->name, dst.index - storage->index,
-- 
1.7.4



More information about the mesa-dev mailing list