glsl: Add infrastructure for "hidden" uniforms.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 27 Oct 2014 23:34:06 +0000 (16:34 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Fri, 7 Nov 2014 00:20:01 +0000 (16:20 -0800)
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@whitecape.org>
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/ir.h
src/glsl/ir_uniform.h
src/glsl/link_uniforms.cpp
src/mesa/main/mtypes.h
src/mesa/main/shaderapi.c

index 5c7faf6ee64a85ff70eaf5b023e52d271b5e8766..a0f48b2af6667617ba7c8921b592ddf419ee18b5 100644 (file)
@@ -342,6 +342,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,
 };
 
 /**
index b9ecf7cdd3c6db85adb2aa697d229de871d63dd6..21b5d05c11a03c5d7882552fbda462bb4c6b5415 100644 (file)
@@ -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
index 400e13479330195eec954e85e63834039196cba4..de2f6c9ac994b5a57f1fe9f29cfda3c978cedd19 100644 (file)
@@ -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);
index be79ed3590e058de13c7f2f21b3c4bd1e7e9f6cf..7389baa1d0255bae17fd09a533a2a16c4f0acf78 100644 (file)
@@ -2843,6 +2843,7 @@ struct gl_shader_program
 
    /* post-link info: */
    unsigned NumUserUniformStorage;
+   unsigned NumHiddenUniforms;
    struct gl_uniform_storage *UniformStorage;
 
    /**
index 2be9092c10d2c4c0cccecd3a903cdf5a8fa8566b..66578204f08053ce792527691f2b06180903076a 100644 (file)
@@ -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.
          */