[Mesa-dev] [PATCH 14/19] glsl: add uniform and program resource support
Marek Olšák
maraeo at gmail.com
Mon Jul 20 15:34:33 PDT 2015
On Thu, Jul 9, 2015 at 9:17 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at 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 <airlied at 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
More information about the mesa-dev
mailing list