[Mesa-dev] [PATCH 06/78] i965/nir/vec4: Add setup of uniform variables

Iago Toral itoral at igalia.com
Tue Jun 30 01:04:47 PDT 2015


Hi Jason,

On Mon, 2015-06-29 at 16:22 -0700, Jason Ekstrand wrote:
> On Fri, Jun 26, 2015 at 1:06 AM, Eduardo Lima Mitev <elima at igalia.com> wrote:
> > From: Iago Toral Quiroga <itoral at igalia.com>
> >
> > This is based on similar code existing in vec4_visitor. It builds the
> > uniform register file iterating through each uniform variable. It
> > also stores the index of each register at the corresponding offset
> > in a map. This map will later be used by load_uniform intrinsic
> > instructions to build the correct UNIFORM source register.
> >
> > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=89580
> > ---
> >  src/mesa/drivers/dri/i965/brw_vec4.h       |   2 +
> >  src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 115 ++++++++++++++++++++++++++++-
> >  2 files changed, 114 insertions(+), 3 deletions(-)
> >
> > diff --git a/src/mesa/drivers/dri/i965/brw_vec4.h b/src/mesa/drivers/dri/i965/brw_vec4.h
> > index 673df4e..6535f19 100644
> > --- a/src/mesa/drivers/dri/i965/brw_vec4.h
> > +++ b/src/mesa/drivers/dri/i965/brw_vec4.h
> > @@ -414,6 +414,8 @@ public:
> >     src_reg *nir_inputs;
> >     int *nir_outputs;
> >     brw_reg_type *nir_output_types;
> > +   unsigned *nir_uniform_offset;
> > +   unsigned *nir_uniform_driver_location;
> >
> >  protected:
> >     void emit_vertex();
> > diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> > index 2d457a6..40ec66f 100644
> > --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> > +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
> > @@ -106,19 +106,128 @@ vec4_visitor::nir_setup_outputs(nir_shader *shader)
> >  void
> >  vec4_visitor::nir_setup_uniforms(nir_shader *shader)
> >  {
> > -   /* @TODO: Not yet implemented */
> > +   uniforms = 0;
> > +
> > +   nir_uniform_offset =
> > +      rzalloc_array(mem_ctx, unsigned, this->uniform_array_size);
> > +   memset(nir_uniform_offset, 0, this->uniform_array_size * sizeof(unsigned));
> 
> rzalloc memsets the whole thing to 0 for you, this memset is redundant.
> 
> > +
> > +   nir_uniform_driver_location =
> > +      rzalloc_array(mem_ctx, unsigned, this->uniform_array_size);
> > +   memset(nir_uniform_driver_location, 0,
> > +          this->uniform_array_size * sizeof(unsigned));
> 
> Same here.

Oh, right.

> > +
> > +   if (shader_prog) {
> > +      foreach_list_typed(nir_variable, var, node, &shader->uniforms) {
> > +         /* UBO's, atomics and samplers don't take up space in the
> > +            uniform file */
> > +         if (var->interface_type != NULL || var->type->contains_atomic() ||
> > +             type_size(var->type) == 0) {
> 
> I'm curious as to why you have this extra type_size() == 0 condition.
> We don't have that in the FS NIR code.  What caused you to add it?

Take this piglit test for example:
bin/textureSize vs isampler1D -auto -fbo

here, 'tex' is a uniform of size 0 since type_size() returns 0 for all
sampler types. If we do not ignore these, we will try to store uniform
information for them in the various structures we have to track uniform
data, like uniform_size[] and others. The size allocated for these
arrays is computed by in the vec4_visitor constructor based on
stage_prog_data->nr_params (uniform_array_size) and that does not seem
to make room for zero-sized uniforms. Without that check we would
process more uniforms than uniform_array_size and overflow the arrays we
allocate to track uniform information. I understand that
stage_prog_data->nr_params does not track uniforms that don't use
register space, so skipping uniforms with no size seems to make sense
here.

Notice that this is done in the current vec4_visitor too, when we visit
the variable in vec4_visitor::visit(ir_variable *ir), for ir_var_uniform
there is this code:

if (ir->is_in_uniform_block() || type_size(ir->type) == 0)
    return; 

> > +            continue;
> > +         }
> > +
> > +         assert(uniforms < uniform_array_size);
> > +         this->uniform_size[uniforms] = type_size(var->type);
> > +
> > +         if (strncmp(var->name, "gl_", 3) == 0)
> > +            nir_setup_builtin_uniform(var);
> > +         else
> > +            nir_setup_uniform(var);
> > +      }
> > +   } else {
> > +      /* ARB_vertex_program is not supported yet */
> > +      assert("Not implemented");
> > +   }
> >  }
> >
> >  void
> >  vec4_visitor::nir_setup_uniform(nir_variable *var)
> >  {
> > -   /* @TODO: Not yet implemented */
> > +   int namelen = strlen(var->name);
> > +
> > +   /* The data for our (non-builtin) uniforms is stored in a series of
> > +    * gl_uniform_driver_storage structs for each subcomponent that
> > +    * glGetUniformLocation() could name.  We know it's been set up in the same
> > +    * order we'd walk the type, so walk the list of storage and find anything
> > +    * with our name, or the prefix of a component that starts with our name.
> > +    */
> > +    unsigned offset = 0;
> > +    for (unsigned u = 0; u < shader_prog->NumUniformStorage; u++) {
> > +       struct gl_uniform_storage *storage = &shader_prog->UniformStorage[u];
> > +
> > +       if (storage->builtin)
> > +          continue;
> > +
> > +       if (strncmp(var->name, storage->name, namelen) != 0 ||
> > +           (storage->name[namelen] != 0 &&
> > +            storage->name[namelen] != '.' &&
> > +            storage->name[namelen] != '[')) {
> > +          continue;
> > +       }
> > +
> > +       gl_constant_value *components = storage->storage;
> > +       unsigned vector_count = (MAX2(storage->array_elements, 1) *
> > +                                storage->type->matrix_columns);
> 
> In the FS backend, we simply use storage->type->component_slots().
> Why can't we do that here?  It seems to be performing the same
> calculation.

This does not seem to do what we want in the vec4 backend. For example,
consider the following piglit test:

tests/spec/gl-3.1/attributeless-vertexid.shader_test

In that test we have something like this:

   vec2[](
        vec2(-1, 1),
        vec2(-1,-1),
        vec2( 1,-1),
        vec2( 1, 1)
        );

And for that I see:

storage->type->component_slots() = 2

This is because storage->type is glsl_type::_vec2_type. This is not
convenient for us in the vec4 backend because it is giving a scalar
count and we want to compute the count in units of vec4.

> > +
> > +       for (unsigned s = 0; s < vector_count; s++) {
> > +          assert(uniforms < uniform_array_size);
> > +          uniform_vector_size[uniforms] = storage->type->vector_elements;
> > +
> > +          int i;
> > +          for (i = 0; i < uniform_vector_size[uniforms]; i++) {
> > +             stage_prog_data->param[uniforms * 4 + i] = components;
> > +             components++;
> > +          }
> > +          for (; i < 4; i++) {
> > +             static gl_constant_value zero = { 0.0 };
> 
> This should probably be const.

Yes, I will fix this.

> > +             stage_prog_data->param[uniforms * 4 + i] = &zero;
> > +          }
> > +
> > +          int uniform_offset = var->data.driver_location + offset;
> > +          nir_uniform_offset[uniform_offset] = uniforms;
> > +          offset++;
> > +
> > +          nir_uniform_driver_location[uniforms] = var->data.driver_location;
> > +          uniforms++;
> > +       }
> > +    }
> >  }
> >
> >  void
> >  vec4_visitor::nir_setup_builtin_uniform(nir_variable *var)
> >  {
> > -   /* @TODO: Not yet implemented */
> > +   const nir_state_slot *const slots = var->state_slots;
> > +   assert(var->state_slots != NULL);
> > +
> > +   unsigned offset = 0;
> > +   for (unsigned int i = 0; i < var->num_state_slots; i++) {
> > +      /* This state reference has already been setup by ir_to_mesa,
> > +       * but we'll get the same index back here.  We can reference
> > +       * ParameterValues directly, since unlike brw_fs.cpp, we never
> > +       * add new state references during compile.
> > +       */
> > +      int index = _mesa_add_state_reference(this->prog->Parameters,
> > +                                           (gl_state_index *)slots[i].tokens);
> > +      gl_constant_value *values =
> > +         &this->prog->Parameters->ParameterValues[index][0];
> > +
> > +      assert(this->uniforms < uniform_array_size);
> > +
> > +      for (unsigned j = 0; j < 4; j++)
> > +         stage_prog_data->param[this->uniforms * 4 + j] =
> > +            &values[GET_SWZ(slots[i].swizzle, j)];
> > +
> > +      this->uniform_vector_size[this->uniforms] =
> > +         (var->type->is_scalar() || var->type->is_vector() ||
> > +          var->type->is_matrix() ? var->type->vector_elements : 4);
> > +
> > +      int uniform_offset = var->data.driver_location + offset;
> > +      nir_uniform_offset[uniform_offset] = uniforms;
> > +      offset++;
> > +
> > +      nir_uniform_driver_location[uniforms] = var->data.driver_location;
> > +      this->uniforms++;
> > +   }
> >  }
> >
> >  void
> > --
> > 2.1.4
> >
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev




More information about the mesa-dev mailing list