[Mesa-dev] [PATCH v2 1/2] glsl: Add infrastructure for "hidden" uniforms.

Kenneth Graunke kenneth at whitecape.org
Wed Oct 29 17:16:31 PDT 2014


In the compiler, we'd like to generate implicit uniforms for internal
use.  These should not be visible via the GL uniform introspection API.

To support that, we add a new ir_variable::how_declared value of
ir_var_hidden, and plumb that through to gl_uniform_storage.

v2 (idr): Fix some memory management issues in
move_hidden_uniforms_to_end.  The comment block on the function has more
details.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/glsl/ir.h              |  6 ++++++
 src/glsl/ir_uniform.h      |  6 ++++++
 src/glsl/link_uniforms.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++
 src/mesa/main/mtypes.h     |  1 +
 src/mesa/main/shaderapi.c  |  6 ++++--
 5 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 90c443c..a7c4c6b 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -359,6 +359,12 @@ enum ir_var_declaration_type {
     * re-declared by the shader.
     */
    ir_var_declared_implicitly,
+
+   /**
+    * Variable is implicitly generated by the compiler and should not be
+    * visible via the API.
+    */
+   ir_var_hidden,
 };
 
 /**
diff --git a/src/glsl/ir_uniform.h b/src/glsl/ir_uniform.h
index b9ecf7c..21b5d05 100644
--- a/src/glsl/ir_uniform.h
+++ b/src/glsl/ir_uniform.h
@@ -175,6 +175,12 @@ struct gl_uniform_storage {
     * arrays this is the first element in the array.
     */
    unsigned remap_location;
+
+   /**
+    * This is a compiler-generated uniform that should not be advertised
+    * via the API.
+    */
+   bool hidden;
 };
 
 #ifdef __cplusplus
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
index 400e134..de2f6c9 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -585,6 +585,8 @@ private:
       this->uniforms[id].driver_storage = NULL;
       this->uniforms[id].storage = this->values;
       this->uniforms[id].atomic_buffer_index = -1;
+      this->uniforms[id].hidden =
+         current_var->data.how_declared == ir_var_hidden;
       if (this->ubo_block_index != -1) {
 	 this->uniforms[id].block_index = this->ubo_block_index;
 
@@ -806,6 +808,50 @@ link_set_image_access_qualifiers(struct gl_shader_program *prog)
    }
 }
 
+/**
+ * Sort the array of uniform storage so that the non-hidden uniforms are first
+ *
+ * This function sorts the list "in place."  This is important because some of
+ * the storage accessible from \c uniforms has \c uniforms as its \c ralloc
+ * context.  If \c uniforms is freed, some other storage will also be freed.
+ */
+static unsigned
+move_hidden_uniforms_to_end(struct gl_shader_program *prog,
+                            struct gl_uniform_storage *uniforms,
+                            unsigned num_elements)
+{
+   struct gl_uniform_storage *sorted_uniforms =
+      ralloc_array(prog, struct gl_uniform_storage, num_elements);
+   unsigned hidden_uniforms = 0;
+   unsigned j = 0;
+
+   /* Add the non-hidden uniforms. */
+   for (unsigned i = 0; i < num_elements; i++) {
+      if (!uniforms[i].hidden)
+         sorted_uniforms[j++] = uniforms[i];
+   }
+
+   /* Add and count the hidden uniforms. */
+   for (unsigned i = 0; i < num_elements; i++) {
+      if (uniforms[i].hidden) {
+         sorted_uniforms[j++] = uniforms[i];
+         hidden_uniforms++;
+      }
+   }
+
+   assert(prog->UniformHash != NULL);
+   prog->UniformHash->clear();
+   for (unsigned i = 0; i < num_elements; i++) {
+      if (sorted_uniforms[i].name != NULL)
+         prog->UniformHash->put(i, sorted_uniforms[i].name);
+   }
+
+   memcpy(uniforms, sorted_uniforms, sizeof(uniforms[0]) * num_elements);
+   ralloc_free(sorted_uniforms);
+
+   return hidden_uniforms;
+}
+
 void
 link_assign_uniform_locations(struct gl_shader_program *prog,
                               unsigned int boolean_true)
@@ -926,6 +972,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
              sizeof(prog->_LinkedShaders[i]->SamplerTargets));
    }
 
+   const unsigned hidden_uniforms =
+      move_hidden_uniforms_to_end(prog, uniforms, num_user_uniforms);
+
    /* Reserve all the explicit locations of the active uniforms. */
    for (unsigned i = 0; i < num_user_uniforms; i++) {
       if (uniforms[i].remap_location != UNMAPPED_UNIFORM_LOC) {
@@ -978,6 +1027,7 @@ link_assign_uniform_locations(struct gl_shader_program *prog,
 #endif
 
    prog->NumUserUniformStorage = num_user_uniforms;
+   prog->NumHiddenUniforms = hidden_uniforms;
    prog->UniformStorage = uniforms;
 
    link_set_image_access_qualifiers(prog);
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 35f5f69..7583f2c 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2843,6 +2843,7 @@ struct gl_shader_program
 
    /* post-link info: */
    unsigned NumUserUniformStorage;
+   unsigned NumHiddenUniforms;
    struct gl_uniform_storage *UniformStorage;
 
    /**
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 2be9092..6657820 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -565,13 +565,15 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param
       *params = _mesa_longest_attribute_name_length(shProg);
       return;
    case GL_ACTIVE_UNIFORMS:
-      *params = shProg->NumUserUniformStorage;
+      *params = shProg->NumUserUniformStorage - shProg->NumHiddenUniforms;
       return;
    case GL_ACTIVE_UNIFORM_MAX_LENGTH: {
       unsigned i;
       GLint max_len = 0;
+      const unsigned num_uniforms =
+         shProg->NumUserUniformStorage - shProg->NumHiddenUniforms;
 
-      for (i = 0; i < shProg->NumUserUniformStorage; i++) {
+      for (i = 0; i < num_uniforms; i++) {
 	 /* Add one for the terminating NUL character for a non-array, and
 	  * 4 for the "[0]" and the NUL for an array.
 	  */
-- 
2.1.2



More information about the mesa-dev mailing list