[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