[Mesa-dev] [PATCH 2/2] mesa: fix GLSL program objects with more than 16 samplers combined

Marek Olšák maraeo at gmail.com
Tue May 21 16:32:39 PDT 2013


1) The tabs are used in the entire file. They might have got there
while I was moving some of the bits of code around. I don't really use
tabs for core Mesa work. I can change the tabs to spaces unless you
mean I should change everything to tabs (you didn't make that clear).

2) _mesa_get_sampler_uniform_value is really called at link time,
specifically at the conversion to TGSI. The only case where it might
be called after link time is when a new shader variant is being
generated, though i'm not really sure about this. Anyway, the function
already calls linker_error above my code to report an error. I decided
to do the same. _mesa_problem sounds better though.

Marek

On Tue, May 21, 2013 at 11:54 PM, Eric Anholt <eric at anholt.net> wrote:
> Marek Olšák <maraeo at gmail.com> writes:
>
>> The problem is the sampler units are allocated from the same pool for all
>> shader stages, so if a vertex shader uses 12 samplers (0..11), the fragment
>> shader samplers start at index 12, leaving only 4 sampler units
>> for the fragment shader. The main cause is probably the fact that samplers
>> (texture unit -> sampler unit mapping, etc.) are tracked globally
>> for an entire program object.
>>
>> This commit adapts the GLSL linker and core Mesa such that the sampler units
>> are assigned to sampler uniforms for each shader stage separately
>> (if a sampler uniform is used in all shader stages, it may occupy a different
>> sampler unit in each, and vice versa, an i-th sampler unit may refer to
>> a different sampler uniform in each shader stage), and the sampler-specific
>> variables are moved from gl_shader_program to gl_shader.
>>
>> This doesn't require any driver changes, and it fixes piglit/max-samplers
>> for gallium and classic swrast. It also works with any number of shader
>> stages.
>
> I was initially uncomfortable with gl_uniform_storage getting bigger,
> but it's *huge* already, and the increased overhead I thought I saw in
> uniform updates isn't really there.  So, just nitpicks:
>
>> @@ -335,8 +339,38 @@ public:
>>     int ubo_block_index;
>>     int ubo_byte_offset;
>>     bool ubo_row_major;
>> +   gl_shader_type shader_type;
>>
>>  private:
>> +   void handle_samplers(const glsl_type *base_type,
>> +                        struct gl_uniform_storage *uniform)
>> +   {
>> +
>> +      if (base_type->is_sampler()) {
>> +         uniform->sampler[shader_type].index = this->next_sampler;
>> +         uniform->sampler[shader_type].active = true;
>> +
>> +      /* Increment the sampler by 1 for non-arrays and by the number of
>> +       * array elements for arrays.
>> +       */
>
> bad tab indentation
>
>> +         this->next_sampler +=
>> +               MAX2(1, uniform->array_elements);
>> +
>> +      const gl_texture_index target = base_type->sampler_index();
>> +      const unsigned shadow = base_type->sampler_shadow;
>
> tabs
>
>> +         for (unsigned i = uniform->sampler[shader_type].index;
>> +              i < MIN2(this->next_sampler, MAX_SAMPLERS);
>> +              i++) {
>> +         this->targets[i] = target;
>> +         this->shader_samplers_used |= 1U << i;
>> +         this->shader_shadow_samplers |= shadow << i;
>> +      }
>
> tabs
>
>> @@ -388,26 +397,16 @@ private:
>>        base_type = type;
>>        }
>>
>> -      if (base_type->is_sampler()) {
>> -      this->uniforms[id].sampler = this->next_sampler;
>> +      /* This assigns sampler uniforms to sampler units. */
>> +      handle_samplers(base_type, &this->uniforms[id]);
>>
>> -      /* Increment the sampler by 1 for non-arrays and by the number of
>> -       * array elements for arrays.
>> -       */
>> -      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 < MIN2(this->next_sampler, MAX_SAMPLERS)
>> -              ; i++) {
>> -         this->targets[i] = target;
>> -         this->shader_samplers_used |= 1U << i;
>> -         this->shader_shadow_samplers |= shadow << i;
>> -      }
>> -
>> -      } else {
>> -      this->uniforms[id].sampler = ~0;
>> +      /* If there is already storage associated with this uniform, it means
>> +       * that it was set while processing an earlier shader stage.  For
>> +       * 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) {
>> +      return;
>
> tabs
>
>> @@ -119,6 +122,14 @@ _mesa_get_sampler_uniform_value(class ir_dereference *sampler,
>>        return 0;
>>     }
>>
>> -   return shader_program->UniformStorage[location].sampler + getname.offset;
>> -}
>> +   if (!shader_program->UniformStorage[location].sampler[shader].active) {
>> +      linker_error(shader_program,
>> +                "cannot return a sampler named %s, because it is not "
>> +                   "used in this shader stage. This is a driver bug.\n",
>> +                   getname.name);
>> +      return 0;
>> +   }
>
> Maybe _mesa_problem()?  This isn't really called at link time, and you
> want something really visible like an assert.
>
> Other than the style bits,
>
> Reviewed-by: Eric Anholt <eric at anholt.net>


More information about the mesa-dev mailing list