On Thu, Jul 9, 2015 at 9:17 AM, Dave Airlie <airl...@gmail.com> wrote: > From: Dave Airlie <airl...@redhat.com> > > This adds linker support for subroutine uniforms, they > have some subtle differences from real uniforms, we also hide > them and they are given internal uniform names. > > This also adds the subroutine locations and subroutine uniforms > to the program resource tracking for later use. > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > src/glsl/ir_uniform.h | 2 + > src/glsl/link_uniforms.cpp | 56 +++++++++++++++++++++++++-- > src/glsl/linker.cpp | 94 > +++++++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 146 insertions(+), 6 deletions(-) > > diff --git a/src/glsl/ir_uniform.h b/src/glsl/ir_uniform.h > index e1b8014..be1b38d 100644 > --- a/src/glsl/ir_uniform.h > +++ b/src/glsl/ir_uniform.h > @@ -114,6 +114,8 @@ struct gl_uniform_storage { > > struct gl_opaque_uniform_index image[MESA_SHADER_STAGES]; > > + struct gl_opaque_uniform_index subroutine[MESA_SHADER_STAGES]; > + > /** > * Storage used by the driver for the uniform > */ > diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp > index 11ae06f..78a830a 100644 > --- a/src/glsl/link_uniforms.cpp > +++ b/src/glsl/link_uniforms.cpp > @@ -47,9 +47,10 @@ > static unsigned > values_for_type(const glsl_type *type) > { > - if (type->is_sampler()) { > + if (type->is_sampler() || type->is_subroutine()) { > return 1; > - } else if (type->is_array() && type->fields.array->is_sampler()) { > + } else if (type->is_array() && (type->fields.array->is_sampler() || > + type->fields.array->is_subroutine())) { > return type->array_size(); > } else { > return type->component_slots(); > @@ -284,6 +285,7 @@ public: > count_uniform_size(struct string_to_uint_map *map) > : num_active_uniforms(0), num_values(0), num_shader_samplers(0), > num_shader_images(0), num_shader_uniform_components(0), > + num_shader_subroutines(0), > is_ubo_var(false), map(map) > { > /* empty */ > @@ -294,6 +296,7 @@ public: > this->num_shader_samplers = 0; > this->num_shader_images = 0; > this->num_shader_uniform_components = 0; > + this->num_shader_subroutines = 0; > } > > void process(ir_variable *var) > @@ -331,6 +334,11 @@ public: > */ > unsigned num_shader_uniform_components; > > + /** > + * Number of subroutine uniforms used > + */ > + unsigned num_shader_subroutines; > + > bool is_ubo_var; > > private: > @@ -348,7 +356,9 @@ private: > * count it for each shader target. > */ > const unsigned values = values_for_type(type); > - if (type->contains_sampler()) { > + if (type->contains_subroutine()) { > + this->num_shader_subroutines += values; > + } else if (type->contains_sampler()) { > this->num_shader_samplers += values; > } else if (type->contains_image()) { > this->num_shader_images += values; > @@ -421,6 +431,7 @@ public: > this->shader_shadow_samplers = 0; > this->next_sampler = 0; > this->next_image = 0; > + this->next_subroutine = 0; > memset(this->targets, 0, sizeof(this->targets)); > } > > @@ -535,6 +546,24 @@ private: > } > } > > + void handle_subroutines(const glsl_type *base_type, > + struct gl_uniform_storage *uniform) > + { > + if (base_type->is_subroutine()) { > + uniform->subroutine[shader_type].index = this->next_subroutine; > + uniform->subroutine[shader_type].active = true; > + > + /* Increment the subroutine index by 1 for non-arrays and by the > + * number of array elements for arrays. > + */ > + this->next_subroutine += MAX2(1, uniform->array_elements); > + > + } else { > + uniform->subroutine[shader_type].index = ~0; > + uniform->subroutine[shader_type].active = false; > + } > + } > + > virtual void visit_field(const glsl_type *type, const char *name, > bool row_major) > { > @@ -588,6 +617,7 @@ private: > /* This assigns uniform indices to sampler and image uniforms. */ > handle_samplers(base_type, &this->uniforms[id]); > handle_images(base_type, &this->uniforms[id]); > + handle_subroutines(base_type, &this->uniforms[id]); > > /* If there is already storage associated with this uniform or if the > * uniform is set as builtin, it means that it was set while processing > @@ -672,6 +702,7 @@ private: > struct gl_uniform_storage *uniforms; > unsigned next_sampler; > unsigned next_image; > + unsigned next_subroutine; > > public: > union gl_constant_value *values; > @@ -952,8 +983,11 @@ link_assign_uniform_locations(struct gl_shader_program > *prog, > sh->num_samplers = uniform_size.num_shader_samplers; > sh->NumImages = uniform_size.num_shader_images; > sh->num_uniform_components = > uniform_size.num_shader_uniform_components; > - > sh->num_combined_uniform_components = sh->num_uniform_components; > + sh->NumSubroutineUniforms = uniform_size.num_shader_subroutines; > + > + sh->SubroutineUniformRemapTable = ralloc_array(sh, struct > gl_uniform_storage *, sh->NumSubroutineUniforms); > + > for (unsigned i = 0; i < sh->NumUniformBlocks; i++) { > sh->num_combined_uniform_components += > sh->UniformBlocks[i].UniformBufferSize / 4; > @@ -1049,6 +1083,20 @@ link_assign_uniform_locations(struct gl_shader_program > *prog, > uniforms[i].remap_location = prog->NumUniformRemapTable; > > prog->NumUniformRemapTable += entries; > + > + if (uniforms[i].hidden) { > + for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) { > + struct gl_shader *sh = prog->_LinkedShaders[j]; > + if (!sh) > + continue; > + > + if (uniforms[i].subroutine[j].active) { > + for (unsigned k = 0; k < entries; k++) > + > sh->SubroutineUniformRemapTable[uniforms[i].subroutine[j].index + k] = > &uniforms[i]; > + break; > + } > + } > + } > } > > #ifndef NDEBUG > diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp > index b7a783c..b679a0a 100644 > --- a/src/glsl/linker.cpp > +++ b/src/glsl/linker.cpp > @@ -780,6 +780,10 @@ cross_validate_globals(struct gl_shader_program *prog, > if (uniforms_only && (var->data.mode != ir_var_uniform)) > continue; > > + /* don't cross validate subroutine uniforms */ > + if (var->type->contains_subroutine()) > + continue; > + > /* Don't cross validate temporaries that are at global scope. These > * will eventually get pulled into the shaders 'main'. > */ > @@ -1872,8 +1876,11 @@ update_array_sizes(struct gl_shader_program *prog) > * Atomic counters are supposed to get deterministic > * locations assigned based on the declaration ordering and > * sizes, array compaction would mess that up. > + * > + * Subroutine uniforms are not removed. > */ > - if (var->is_in_uniform_block() || var->type->contains_atomic()) > + if (var->is_in_uniform_block() || var->type->contains_atomic() || > + var->type->contains_subroutine()) > continue; > > unsigned int size = var->data.max_array_access; > @@ -2436,6 +2443,23 @@ check_resources(struct gl_context *ctx, struct > gl_shader_program *prog) > } > } > > +static void > +check_subroutine_resources(struct gl_context *ctx, struct gl_shader_program > *prog) > +{ > + > + if (!ctx->Extensions.ARB_shader_subroutine) > + return; > + > + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { > + struct gl_shader *sh = prog->_LinkedShaders[i]; > + > + if (sh) { > + if (sh->NumSubroutineUniforms > MAX_SUBROUTINE_UNIFORM_LOCATIONS) > + linker_error(prog, "Too many %s shader subroutine uniforms\n", > + _mesa_shader_stage_to_string(i)); > + } > + } > +} > /** > * Validate shader image resources. > */ > @@ -2791,10 +2815,39 @@ build_program_resource_list(struct gl_context *ctx, > return; > } > > + for (unsigned i = 0; i < shProg->NumUniformStorage; i++) { > + GLenum type; > + if (!shProg->UniformStorage[i].hidden) > + continue; > + > + for (int j = MESA_SHADER_VERTEX; j < MESA_SHADER_STAGES; j++) { > + if (!shProg->UniformStorage[i].subroutine[j].active) > + continue; > + > + type = _mesa_shader_stage_to_subroutine_uniform((gl_shader_stage)j); > + /* add shader subroutines */ > + if (!add_program_resource(shProg, type, &shProg->UniformStorage[i], > 0)) > + return; > + } > + } > + > + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { > + struct gl_shader *sh = shProg->_LinkedShaders[i]; > + GLuint type; > + > + if (!sh) > + continue; > + > + type = _mesa_shader_stage_to_subroutine((gl_shader_stage)i); > + for (unsigned j = 0; j < sh->NumSubroutineFunctions; j++) { > + if (!add_program_resource(shProg, type, &sh->SubroutineFunctions[j], > 0))
Wrong indentation. Marek _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev