From 6c0df75803e1944f82a1468dcca47d23de82ea6b Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 14 Nov 2011 21:58:50 -0800 Subject: [PATCH] linker: Calculate used samplers and shadow samplers in the linker 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 Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke --- 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 47d34cf0b79..02f57d91174 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 25597950ede..9fdabf98c06 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 d156cae5050..869f7d373ba 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 8280efefe82..6a90d5ad7e8 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) { -- 2.30.2