[Mesa-dev] [PATCH 12/17] glsl: Linker sets indexed uniform

Vincent Lejeune vljn at ovi.com
Sun Dec 25 10:20:07 PST 2011


GL_ARB_uniform_buffer_object API uses index as a way to query information about
classic uniform and variables in UBOs. For classic uniform, index does not have to
match uniform location, but it is not forbidden and is simpler to implement.
Linker generates an array that stores in index order variable in UBO information. This
array can later be queried using API.
---
 src/glsl/linker.cpp    |   91 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/mesa/main/mtypes.h |   23 ++++++++++++
 2 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 34bc537..1ff965a 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1193,6 +1193,88 @@ create_storage_type(const struct glsl_type *const type, void *ctx=NULL)
    return storage_tree;
 }
 
+static void
+generate_indexed_ubo_variables_recursive( struct gl_shader_program *sh, struct gl_uniform_buffer_object *parent_ubo,
+                                          const union gl_variable_storage *storage_tree,
+                                          const char *prefix, const struct glsl_type *const type, unsigned& index,
+                                          unsigned offset_from_stride = 0)
+{
+   // type is not a leaf, we need to recurse over it
+   if ( type->is_record() ) {
+      for (unsigned i = 0; i < type->length; i++) {
+         char* new_prefix = (char*) malloc(strlen(prefix) + 1 + strlen(type->fields.structure[i].name));
+         sprintf(new_prefix,"%s.%s",prefix,type->fields.structure[i].name);
+         generate_indexed_ubo_variables_recursive(sh,
+                                                  parent_ubo,
+                                                  storage_tree->AsRecord.Fields[i],
+                                                  new_prefix,
+                                                  type->fields.structure[i].type,
+                                                  index,
+                                                  offset_from_stride);
+         free(new_prefix);
+      }
+      return;
+   }
+   if (type->is_array() && type->fields.array->is_record()) {
+      for (unsigned i = 0; i < (unsigned) type->array_size(); i++) {
+         char * new_prefix = (char *) malloc(strlen(prefix) + 2 + 8);
+         sprintf(new_prefix,"%s[%d]",prefix,i);
+         generate_indexed_ubo_variables_recursive(sh,
+                                                  parent_ubo,
+                                                  storage_tree->AsArray.FirstElement,
+                                                  new_prefix,
+                                                  type->fields.array,
+                                                  index,
+                                                  i * storage_tree->AsArray.Stride);
+         free(new_prefix);
+      }
+      return;
+   }
+
+   // we add a type, so we need to extend variable storage
+   index++;
+   sh->IndexedVariableCount++;
+
+   if (sh->IndexedVariableCount == 1)
+      sh->IndexedUBOVariables = (gl_indexed_ubo_variable*) malloc(sizeof(struct gl_indexed_ubo_variable));
+   else
+      sh->IndexedUBOVariables = (gl_indexed_ubo_variable*) realloc(sh->IndexedUBOVariables, (sh->IndexedVariableCount) * sizeof(struct gl_indexed_ubo_variable));
+
+   struct gl_indexed_ubo_variable& ubo = sh->IndexedUBOVariables[sh->IndexedVariableCount - 1];
+   ubo.Name = strdup(prefix);
+   ubo.Stride = -1;
+   sh->NamedAccessUBOVariables->put(index-1,ubo.Name);
+   ubo.UBO = parent_ubo;
+   ubo.Type = type->gl_type;
+
+   if (type->is_array()) {
+      if (type->fields.array->is_scalar() || type->fields.array->is_vector())
+         ubo.Offset = offset_from_stride + storage_tree->AsArray.FirstElement->AsLeaf.Offset;
+      if (type->fields.array->is_matrix())
+         ubo.Offset = offset_from_stride + storage_tree->AsArray.FirstElement->AsMatrix.Offset;
+      ubo.Stride = storage_tree->AsArray.Stride;
+      ubo.Size = type->length;
+   }
+   if (type->is_scalar() || type->is_vector()) {
+      ubo.Offset = offset_from_stride + storage_tree->AsLeaf.Offset;
+   }
+
+   if (type->is_matrix()) {
+      ubo.Offset = offset_from_stride + storage_tree->AsMatrix.Offset;
+   }
+}
+
+/**
+ * Populate the indexed variable array that is used by query from UBO API.
+ */
+static void generate_indexed_ubo_variables(struct gl_shader_program *sh, struct gl_uniform_buffer_object *ubo)
+{
+   unsigned index = sh->NumUserUniformStorage + sh->IndexedVariableCount;
+   for (unsigned i = 0; i < ubo->NumberOfVariables; i++) {
+      struct gl_shader_ubo_variable& ubovar = ubo->Variables[i];
+      generate_indexed_ubo_variables_recursive(sh,ubo,ubovar.Storage,ubovar.Name,ubovar.Type,index);
+   }
+}
 
 /**
  * Generate structures for declared and implicit (eg, array element/struct field) variables in UBO.
@@ -1347,6 +1429,7 @@ static void merge_interstage_ubo(gl_shader_program* prog)
                                     hash_table_string_compare);
    unsigned& index = prog->UBOCount = 0;
 
+   prog->NamedAccessUBOVariables = new string_to_uint_map();
 
 
    for (unsigned k = 0; k < MESA_SHADER_TYPES; k++) {
@@ -1386,6 +1469,14 @@ static void merge_interstage_ubo(gl_shader_program* prog)
          }
 
       }
+
+      for (unsigned i = 0; i < prog->UBOCount; i++) {
+            // Set variables info in current_ubo
+            // Todo : implementation dependant packing rules
+            set_standard_uniform_block_layout(prog->UniformBufferObject[i]);
+            generate_indexed_ubo_variables(prog, &(prog->UniformBufferObject[i]));
+      }
+
       for (unsigned i = 0; i < prog->UBOCount; i++) {
          const gl_uniform_buffer_object& ubo = prog->UniformBufferObject[i];
          for (unsigned j = 0; j < ubo.NumberOfVariables; j++) {
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 269e433..c3f8956 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2165,6 +2165,15 @@ struct gl_shader_ubo_variable
    const struct glsl_type* Type;
    const union gl_variable_storage *Storage;
 };
+
+struct gl_indexed_ubo_variable
+{
+   char* Name;
+   GLenum Type; /** GL_FLOAT, GL_FLOAT_VEC2,... */
+   GLuint Size; /** if array, number of element, else 1 */
+   GLuint Offset; /** In bytes, from start of UBO */
+   GLint Stride; /** In array case, stride between 2 consecutive elements, -1 otherwise */
+   struct gl_uniform_buffer_object* UBO; /** Pointer to containing UBO structure inside program */
 };
 
 
@@ -2197,6 +2206,8 @@ struct gl_uniform_buffer_object
    unsigned ReferencedByVS:1; /** Is it present in VS ? Set at link time */
    unsigned ReferencedByGS:1; /** Is it present in GS ? Set at link time */
    unsigned ReferencedByFS:1; /** Is it present in FS ? Set at link time */
+   unsigned Size; /** In bytes, with padding included */
+   unsigned BindingPoint;
 };
 
 
@@ -2355,6 +2366,18 @@ struct gl_shader_program
    struct gl_uniform_buffer_object *UniformBufferObject;
    unsigned UBOCount;
 
+   /** All uniforms (in UBO or not) have to be accessed by a 1D index ;
+    * For classical uniform, index equals location (matches others drivers)
+    * For variables in UBO, we use this array.
+    * Note that IndexedUBOVariables[0] is associated to index max_loc + 1
+    * where max_loc is the highest location of uniforms in the program.
+    */
+   GLuint IndexedVariableCount;
+   struct gl_indexed_ubo_variable* IndexedUBOVariables; /** 1D array of pointers */
+   /** String to GLuint hashtable, provides a quick access to index from variable
+    * name.
+    */
+   struct string_to_uint_map* NamedAccessUBOVariables;
 };   
 
 
-- 
1.7.7



More information about the mesa-dev mailing list