[Mesa-dev] [PATCH 10/17] glsl: Linker merges UBO from shaders from different stage into program-scope UBO.

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


---
 src/glsl/linker.cpp    |   98 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/mesa/main/mtypes.h |    9 ++++
 2 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 5ae928d..0c8a2c2 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1193,6 +1193,99 @@ create_storage_type(const struct glsl_type *const type, void *ctx=NULL)
    return storage_tree;
 }
 
+
+/**
+ * Generate structures for declared and implicit (eg, array element/struct field) variables in UBO.
+ */
+static void expand_gl_ubo(struct gl_shader_program *sh, const struct gl_uniform_buffer_object *source,struct gl_uniform_buffer_object *dest)
+{
+   dest->Name = strdup(source->Name);
+   dest->MatrixLayout = source->MatrixLayout;
+   dest->Layout = source->Layout;
+   dest->NumberOfVariables = source->NumberOfVariables;
+   dest->Variables = (struct gl_shader_ubo_variable*)
+         malloc(dest->NumberOfVariables * sizeof(gl_shader_ubo_variable));
+
+   for (unsigned i = 0; i < dest->NumberOfVariables; i++) {
+      struct gl_shader_ubo_variable& sourcevar = source->Variables[i];
+      struct gl_shader_ubo_variable& destvar = dest->Variables[i];
+      destvar.Name = strdup(sourcevar.Name);
+      destvar.Type = sourcevar.Type;
+   }
+
+   dest->ReferencedByFS = dest->ReferencedByGS = dest->ReferencedByVS = 0;
+}
+
+/**
+ * At interstage this function extract UBOs from shaders to populate programs UBOs
+ * It also performs checks coherency between UBOs with same name.
+ */
+static void merge_interstage_ubo(gl_shader_program* prog)
+{
+   hash_table *ht = hash_table_ctor(0, hash_table_string_hash,
+                                    hash_table_string_compare);
+   unsigned& index = prog->UBOCount = 0;
+
+
+
+   for (unsigned k = 0; k < MESA_SHADER_TYPES; k++) {
+      gl_shader* shader = prog->_LinkedShaders[k];
+      if(shader==NULL)
+         continue;
+
+      for(unsigned ubo_idx = 0; ubo_idx < shader->UBOCount; ubo_idx++) {
+
+         struct gl_uniform_buffer_object* current_ubo = &(shader->UniformBufferObjects[ubo_idx]);
+         struct gl_uniform_buffer_object* ubo_model = (struct gl_uniform_buffer_object*) hash_table_find(ht,current_ubo->Name);
+         if(!ubo_model) {
+            if (index == 0)
+               prog->UniformBufferObject = (struct gl_uniform_buffer_object*) malloc(sizeof(struct gl_uniform_buffer_object));
+            else
+               prog->UniformBufferObject = (struct gl_uniform_buffer_object*) realloc(prog->UniformBufferObject, (index + 1) * sizeof(struct gl_uniform_buffer_object));
+            expand_gl_ubo(prog,current_ubo,&(prog->UniformBufferObject[index]));
+            prog->UniformBufferObject[index].Index = index;
+
+            hash_table_insert(ht,current_ubo,current_ubo->Name);
+            index++;
+         }
+         else {
+            if(!validate_separate_ubo(*current_ubo,*ubo_model))
+               linker_error(prog,"Uniform Buffer Object '%s definition mismatch",ubo_model->Name);
+         }
+         switch(shader->Type) {
+         case GL_FRAGMENT_SHADER:
+            prog->UniformBufferObject[index - 1].ReferencedByFS = 1;
+            break;
+         case GL_VERTEX_SHADER:
+            prog->UniformBufferObject[index - 1].ReferencedByVS = 1;
+            break;
+         case GL_GEOMETRY_SHADER_ARB:
+            prog->UniformBufferObject[index - 1].ReferencedByGS = 1;
+            break;
+         }
+
+      }
+      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++) {
+            for (unsigned k = 0; k < MESA_SHADER_TYPES; k++) {
+               struct gl_shader *shader = prog->_LinkedShaders[k];
+               if (!shader)
+                  continue;
+               ir_variable* var = shader->symbols->get_variable(ubo.Variables[j].Name);
+               if (!var)
+                  continue;
+               var->location = i + 1;
+            }
+         }
+      }
+
+   }
+
+   hash_table_dtor(ht);
+}
+
+
 #endif
 
 
@@ -2333,6 +2426,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
    link_assign_uniform_locations(prog);
    store_fragdepth_layout(prog);
 
+#ifdef FEATURE_ARB_uniform_buffer_object
+   merge_interstage_ubo(prog);
+#endif
+
+
    if (!check_resources(ctx, prog))
       goto done;
 
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 865b6dc..269e433 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2194,6 +2194,9 @@ struct gl_uniform_buffer_object
    GLuint Layout; /** packed, shared or std140 */
    GLuint MatrixLayout; /** rowmajor or columnmajor */
    GLuint NumberOfVariables; /**< number of UBOVariableInfo in StorageLayout */
+   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 */
 };
 
 
@@ -2346,6 +2349,12 @@ struct gl_shader_program
     * \c NULL.
     */
    struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
+   /**
+    * Program Scope UBO
+    */
+   struct gl_uniform_buffer_object *UniformBufferObject;
+   unsigned UBOCount;
+
 };   
 
 
-- 
1.7.7



More information about the mesa-dev mailing list