[Mesa-dev] [PATCH 07/14] linker: Calculate used samplers and shadow samplers in the linker

Ian Romanick idr at freedesktop.org
Fri Jan 6 16:49:58 PST 2012


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

It used to be done in ir_to_mesa, and that was kind of a bad place.

I didn't change st_glsl_to_tgsi because there is some strange stuff
happening in the code that generates glDrawPixels shaders.  It looked
like this would break horribly if I touched anything.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/glsl/link_uniforms.cpp      |   45 ++++++++++++++++++++++++++++++++++++++-
 src/mesa/main/mtypes.h          |   14 +++++++++--
 src/mesa/main/uniform_query.cpp |   13 ++++-------
 src/mesa/program/ir_to_mesa.cpp |   31 +++-----------------------
 4 files changed, 64 insertions(+), 39 deletions(-)

diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
index 47d34cf..02f57d9 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -212,6 +212,12 @@ public:
       memset(this->targets, 0, sizeof(this->targets));
    }
 
+   void start_shader()
+   {
+      this->shader_samplers_used = 0;
+      this->shader_shadow_samplers = 0;
+   }
+
 private:
    virtual void visit_field(const glsl_type *type, const char *name)
    {
@@ -230,8 +236,25 @@ private:
        * example, we may be processing the uniform in the fragment shader, but
        * the uniform was already processed in the vertex shader.
        */
-      if (this->uniforms[id].storage != NULL)
+      if (this->uniforms[id].storage != NULL) {
+	 /* If the uniform already has storage set from another shader stage,
+	  * mark the samplers used for this shader stage.
+	  */
+	 if (type->contains_sampler()) {
+	    const unsigned count = MAX2(1, this->uniforms[id].array_elements);
+	    const unsigned shadow = (type->is_array())
+	       ? type->fields.array->sampler_shadow : type->sampler_shadow;
+
+	    for (unsigned i = 0; i < count; i++) {
+	       const unsigned s = this->uniforms[id].sampler + i;
+
+	       this->shader_samplers_used |= 1U << s;
+	       this->shader_shadow_samplers |= shadow << s;
+	    }
+	 }
+
 	 return;
+      }
 
       const glsl_type *base_type;
       if (type->is_array()) {
@@ -251,10 +274,13 @@ private:
 	 this->next_sampler += MAX2(1, this->uniforms[id].array_elements);
 
 	 const gl_texture_index target = base_type->sampler_index();
+	 const unsigned shadow = base_type->sampler_shadow;
 	 for (unsigned i = this->uniforms[id].sampler
 		 ; i < this->next_sampler
 		 ; i++) {
 	    this->targets[i] = target;
+	    this->shader_samplers_used |= 1U << i;
+	    this->shader_shadow_samplers |= shadow << i;
 	 }
 
       } else {
@@ -280,6 +306,16 @@ public:
    union gl_constant_value *values;
 
    gl_texture_index targets[MAX_SAMPLERS];
+
+   /**
+    * Mask of samplers used by the current shader stage.
+    */
+   unsigned shader_samplers_used;
+
+   /**
+    * Mask of samplers used by the current shader stage for shadows.
+    */
+   unsigned shader_shadow_samplers;
 };
 
 void
@@ -356,6 +392,10 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
       if (prog->_LinkedShaders[i] == NULL)
 	 continue;
 
+      /* Reset various per-shader target counts.
+       */
+      parcel.start_shader();
+
       foreach_list(node, prog->_LinkedShaders[i]->ir) {
 	 ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
@@ -369,6 +409,9 @@ link_assign_uniform_locations(struct gl_shader_program *prog)
 
 	 parcel.process(var);
       }
+
+      prog->_LinkedShaders[i]->active_samplers = parcel.shader_samplers_used;
+      prog->_LinkedShaders[i]->shadow_samplers = parcel.shader_shadow_samplers;
    }
 
    assert(sizeof(prog->SamplerTargets) == sizeof(parcel.targets));
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 7e71a4f..0dc829f 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2183,9 +2183,17 @@ struct gl_shader
 
    unsigned Version;       /**< GLSL version used for linking */
 
-   unsigned num_samplers;	/**< Number of samplers used by this shader.
-				 * This field is only set post-linking.
-				 */
+   /**
+    * \name Sampler tracking
+    *
+    * \note Each of these fields is only set post-linking.
+    */
+   /*@{*/
+   unsigned num_samplers;	/**< Number of samplers used by this shader. */
+   GLbitfield active_samplers;	/**< Bitfield of which samplers are used */
+   GLbitfield shadow_samplers;	/**< Samplers used for shadow sampling. */
+   /*@}*/
+
    /**
     * Number of uniform components used by this shader.
     *
diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index d156cae..869f7d3 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -691,19 +691,16 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
 
       bool flushed = false;
       for (i = 0; i < MESA_SHADER_TYPES; i++) {
-	 struct gl_program *prog;
-
-	 if (shProg->_LinkedShaders[i] == NULL)
-	    continue;
-
-	 prog = shProg->_LinkedShaders[i]->Program;
+	 struct gl_shader *const sh = shProg->_LinkedShaders[i];
 
 	 /* If the shader stage doesn't use any samplers, don't bother
 	  * checking if any samplers have changed.
 	  */
-	 if (prog->SamplersUsed == 0)
+	 if (sh == NULL || sh->active_samplers == 0)
 	    continue;
 
+	 struct gl_program *const prog = sh->Program;
+
 	 assert(sizeof(prog->SamplerUnits) == sizeof(shProg->SamplerUnits));
 
 	 /* Determine if any of the samplers used by this shader stage have
@@ -711,7 +708,7 @@ _mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg,
 	  */
 	 bool changed = false;
 	 for (unsigned j = 0; j < Elements(prog->SamplerUnits); j++) {
-	    if ((prog->SamplersUsed & (1U << j)) != 0
+	    if ((sh->active_samplers & (1U << j)) != 0
 		&& (prog->SamplerUnits[j] != shProg->SamplerUnits[j])) {
 	       changed = true;
 	       break;
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 8280efe..6a90d5a 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2490,32 +2490,6 @@ print_program(struct prog_instruction *mesa_instructions,
    }
 }
 
-
-/**
- * Count resources used by the given gpu program (number of texture
- * samplers, etc).
- */
-static void
-count_resources(struct gl_shader_program *shProg, struct gl_program *prog)
-{
-   unsigned int i;
-
-   prog->SamplersUsed = 0;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = &prog->Instructions[i];
-
-      if (_mesa_is_tex_instruction(inst->Opcode)) {
-	 prog->SamplersUsed |= 1 << inst->TexSrcUnit;
-	 if (inst->TexShadow) {
-	    prog->ShadowSamplers |= 1 << inst->TexSrcUnit;
-	 }
-      }
-   }
-
-   _mesa_update_shader_textures_used(shProg, prog);
-}
-
 class add_uniform_to_shader : public uniform_field_visitor {
 public:
    add_uniform_to_shader(struct gl_shader_program *shader_program,
@@ -3195,7 +3169,10 @@ get_mesa_program(struct gl_context *ctx,
    mesa_instructions = NULL;
 
    do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER);
-   count_resources(shader_program, prog);
+
+   prog->SamplersUsed = shader->active_samplers;
+   prog->ShadowSamplers = shader->shadow_samplers;
+   _mesa_update_shader_textures_used(shader_program, prog);
 
    /* Set the gl_FragDepth layout. */
    if (target == GL_FRAGMENT_PROGRAM_ARB) {
-- 
1.7.6.4



More information about the mesa-dev mailing list