<p dir="ltr"><br>
On Aug 30, 2015 3:44 AM, "Timothy Arceri" <<a href="mailto:t_arceri@yahoo.com.au">t_arceri@yahoo.com.au</a>> wrote:<br>
><br>
> As a bonus we get indirect support for arrays of arrays for free.<br>
> ---<br>
>  I've marked this as request for comment as although it works enough for to<br>
>  pass all the piglit tests there are issues as I'm still trying to figure out<br>
>  nir.<br>
><br>
>  The issues are around the second call to nir_instr_move_src() this call<br>
>  expects the use_link list not to be empty just so it can then remove all<br>
>  entries so I add the list_addtail() call above it to work around this.<br>
>  While this is enough to pass the piglit tests on a non debug build it fails<br>
>  validation for debug builds.<br>
><br>
>  I'm clearly missing a step and would be greatful to anyone who can point me<br>
>  in the right direction.<br>
><br>
>  The validation error:<br>
>  nir/nir_validate.c:873: postvalidate_ssa_def: Assertion `entry' failed.<br>
><br>
> src/glsl/nir/nir_lower_samplers.cpp | 169 ++++++++++++++++++++----------------<br>
>  1 file changed, 95 insertions(+), 74 deletions(-)<br>
><br>
> diff --git a/src/glsl/nir/nir_lower_samplers.cpp b/src/glsl/nir/nir_lower_samplers.cpp<br>
> index 9583b45..dbe9e95 100644<br>
> --- a/src/glsl/nir/nir_lower_samplers.cpp<br>
> +++ b/src/glsl/nir/nir_lower_samplers.cpp<br>
> @@ -24,6 +24,7 @@<br>
>   */<br>
><br>
>  #include "nir.h"<br>
> +#include "nir_builder.h"</p>
<p dir="ltr">Thank you for using the builder!</p>
<p dir="ltr">>  #include "../program.h"<br>
>  #include "program/hash_table.h"<br>
>  #include "ir_uniform.h"<br>
> @@ -35,89 +36,49 @@ extern "C" {<br>
>  #include "program/program.h"<br>
>  }<br>
><br>
> -static unsigned<br>
> -get_sampler_index(const struct gl_shader_program *shader_program,<br>
> -                  gl_shader_stage stage, const char *name)<br>
> -{<br>
> -   unsigned location;<br>
> -   if (!shader_program->UniformHash->get(location, name)) {<br>
> -      assert(!"failed to find sampler");<br>
> -      return 0;<br>
> -   }<br>
> -<br>
> -   if (!shader_program->UniformStorage[location].sampler[stage].active) {<br>
> -      assert(!"cannot return a sampler");<br>
> -      return 0;<br>
> -   }<br>
> -<br>
> -   return shader_program->UniformStorage[location].sampler[stage].index;<br>
> -}<br>
> -<br>
> +/* Calculate the sampler index based on array indicies and also<br>
> + * calculate the base uniform location for struct members.<br>
> + */<br>
>  static void<br>
> -lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,<br>
> -              gl_shader_stage stage, void *mem_ctx)<br>
> +calc_sampler_offsets(nir_deref *tail, nir_tex_instr *instr,<br>
> +                     unsigned *array_elements, nir_src *indirect,</p>
<p dir="ltr">What we have done in most other builder-like things in NIR is to pass around a nir_ssa_def pointer instead of a nir_src.  This keeps things less ambiguous because you always know exactly what kind of thing you're working with and you don't have the "should I copy this or move it or use rewrite or what?" issues that you have with a nir_src.</p>
<p dir="ltr">Also, I'd be kind of inclined to make an "offset" struct containing the base, the indirect SSA value, and the size.  Then use that for the return vale to keep the recursion cleaner.  Tracking by-reverence in/out arguments through a recursive algorithm is a pain.</p>
<p dir="ltr">> +                     nir_builder *b, unsigned *location,<br>
> +                     bool *found_indirect)<br>
>  {<br>
> -   if (instr->sampler == NULL)<br>
> -      return;<br>
> -<br>
> -   /* Get the name and the offset */<br>
> -   instr->sampler_index = 0;<br>
> -   char *name = ralloc_strdup(mem_ctx, instr->sampler->var->name);<br>
> -<br>
> -   for (nir_deref *deref = &instr->sampler->deref;<br>
> -        deref->child; deref = deref->child) {<br>
> -      switch (deref->child->deref_type) {<br>
> +   if (tail->child != NULL) {<br>
> +      switch (tail->child->deref_type) {<br>
>        case nir_deref_type_array: {<br>
> -         nir_deref_array *deref_array = nir_deref_as_array(deref->child);<br>
> +         nir_deref_array *deref_array = nir_deref_as_array(tail->child);<br>
><br>
>           assert(deref_array->deref_array_type != nir_deref_array_type_wildcard);<br>
><br>
> -         if (deref_array->deref.child) {<br>
> -            ralloc_asprintf_append(&name, "[%u]",<br>
> -               deref_array->deref_array_type == nir_deref_array_type_direct ?<br>
> -                  deref_array->base_offset : 0);<br>
> -         } else {<br>
> -            assert(deref->child->type->base_type == GLSL_TYPE_SAMPLER);<br>
> -            instr->sampler_index = deref_array->base_offset;<br>
> -         }<br>
> +         calc_sampler_offsets(tail->child, instr, array_elements,<br>
> +                              indirect, b, location, found_indirect);<br>
> +         instr->sampler_index += deref_array->base_offset * *array_elements;<br>
><br>
> -         /* XXX: We're assuming here that the indirect is the last array<br>
> -          * thing we have.  This should be ok for now as we don't support<br>
> -          * arrays_of_arrays yet.<br>
> -          */<br>
>           if (deref_array->deref_array_type == nir_deref_array_type_indirect) {<br>
> -            /* First, we have to resize the array of texture sources */<br>
> -            nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,<br>
> -                                                  instr->num_srcs + 1);<br>
> -<br>
> -            for (unsigned i = 0; i < instr->num_srcs; i++) {<br>
> -               new_srcs[i].src_type = instr->src[i].src_type;<br>
> -               nir_instr_move_src(&instr->instr, &new_srcs[i].src,<br>
> -                                  &instr->src[i].src);<br>
> +            nir_ssa_def *mul =<br>
> +               nir_imul(b, nir_imm_int(b, *array_elements),<br>
> +                        nir_ssa_for_src(b, deref_array->indirect, 1));<br>
> +<br>
> +            if (*found_indirect) {<br>
> +               indirect->ssa =<br>
> +                  nir_iadd(b, nir_ssa_for_src(b, *indirect, 1), mul);<br>
> +            } else {<br>
> +               *indirect = nir_src_for_ssa(mul);<br>
> +               *found_indirect = true;<br>
>              }<br>
> -<br>
> -            ralloc_free(instr->src);<br>
> -            instr->src = new_srcs;<br>
> -<br>
> -            /* Now we can go ahead and move the source over to being a<br>
> -             * first-class texture source.<br>
> -             */<br>
> -            instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;<br>
> -            instr->num_srcs++;<br>
> -            nir_instr_move_src(&instr->instr,<br>
> -                               &instr->src[instr->num_srcs - 1].src,<br>
> -                               &deref_array->indirect);<br>
> -<br>
> -            instr->sampler_array_size = glsl_get_length(deref->type);<br>
>           }<br>
> -         break;<br>
> +<br>
> +         *array_elements *= glsl_get_length(tail->type);<br>
> +          break;<br>
>        }<br>
><br>
>        case nir_deref_type_struct: {<br>
> -         nir_deref_struct *deref_struct = nir_deref_as_struct(deref->child);<br>
> -         const char *field = glsl_get_struct_elem_name(deref->type,<br>
> -                                                       deref_struct->index);<br>
> -         ralloc_asprintf_append(&name, ".%s", field);<br>
> +         nir_deref_struct *deref_struct = nir_deref_as_struct(tail->child);<br>
> +         *location += deref_struct->index;</p>
<p dir="ltr">This doesn't seem right... What if the struct contains multiple arrays of samplers? What happens if the struct contains 4 floats and then a sampler?  This line seems to imply that each element in the structure is a single sampler.</p>
<p dir="ltr">> +         calc_sampler_offsets(tail->child, instr, array_elements,<br>
> +                              indirect, b, location, found_indirect);<br>
>           break;<br>
>        }<br>
><br>
> @@ -125,15 +86,75 @@ lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_progr<br>
>           unreachable("Invalid deref type");<br>
>           break;<br>
>        }<br>
> +   } else {<br>
> +      return;<br>
> +   }<br>
> +}<br>
> +<br>
> +static void<br>
> +lower_sampler(nir_tex_instr *instr, const struct gl_shader_program *shader_program,<br>
> +              gl_shader_stage stage, nir_builder *builder)</p>
<p dir="ltr">Now that the calc_sampler_offsets stuff is split out we might as well pull this into lower_block_cb.  However that's probably better as a follow-on to keep review easy.  While we're at it, we should probably rename lower_block_cb to lower_samplers_block.  The nir_lower_samplers pass is old and predates the rent naming conventions.  OK, tangent over.</p>
<p dir="ltr">> +{<br>
> +   if (instr->sampler == NULL)<br>
> +      return;<br>
> +<br>
> +   instr->sampler_index = 0;<br>
> +   unsigned location = instr->sampler->var->data.location;<br>
> +<br>
> +   if (instr->sampler->deref.child) {<br>
> +      unsigned array_elements = 1;<br>
> +      nir_src indirect;<br>
> +      bool found_indirect = false;<br>
> +<br>
> +      builder->cursor = nir_before_instr(&instr->instr);<br>
> +      calc_sampler_offsets(&instr->sampler->deref, instr,<br>
> +                           &array_elements, &indirect, builder,<br>
> +                           &location, &found_indirect);<br>
> +<br>
> +      if (found_indirect) {<br>
> +         /* First, we have to resize the array of texture sources */<br>
> +         nir_tex_src *new_srcs = rzalloc_array(instr, nir_tex_src,<br>
> +                                               instr->num_srcs + 1);<br>
> +<br>
> +         for (unsigned i = 0; i < instr->num_srcs; i++) {<br>
> +            new_srcs[i].src_type = instr->src[i].src_type;<br>
> +            nir_instr_move_src(&instr->instr, &new_srcs[i].src,<br>
> +                               &instr->src[i].src);<br>
> +         }<br>
> +<br>
> +         ralloc_free(instr->src);<br>
> +         instr->src = new_srcs;<br>
> +<br>
> +         /* Now we can go ahead and move the source over to being a<br>
> +          * first-class texture source.<br>
> +          */<br>
> +         nir_src indirect_nir_src = nir_src_for_ssa(indirect.ssa);<br>
> +         list_addtail(&indirect_nir_src.use_link, &indirect_nir_src.ssa->uses);<br>
> +<br>
> +         instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;<br>
> +         instr->num_srcs++;<br>
> +         nir_instr_move_src(&instr->instr,<br>
> +                            &instr->src[instr->num_srcs - 1].src,<br>
> +                            &indirect_nir_src);<br>
> +<br>
> +         instr->sampler_array_size = array_elements;<br>
> +      }<br>
> +   }<br>
> +<br>
> +   if (location > shader_program->NumUniformStorage - 1 ||<br>
> +       !shader_program->UniformStorage[location].sampler[stage].active) {<br>
> +      assert(!"cannot return a sampler");<br>
> +      return;<br>
>     }<br>
><br>
> -   instr->sampler_index += get_sampler_index(shader_program, stage, name);<br>
> +   instr->sampler_index +=<br>
> +      shader_program->UniformStorage[location].sampler[stage].index;<br>
><br>
>     instr->sampler = NULL;<br>
>  }<br>
><br>
>  typedef struct {<br>
> -   void *mem_ctx;<br>
> +   nir_builder builder;<br>
>     const struct gl_shader_program *shader_program;<br>
>     gl_shader_stage stage;<br>
>  } lower_state;<br>
> @@ -147,7 +168,7 @@ lower_block_cb(nir_block *block, void *_state)<br>
>        if (instr->type == nir_instr_type_tex) {<br>
>           nir_tex_instr *tex_instr = nir_instr_as_tex(instr);<br>
>           lower_sampler(tex_instr, state->shader_program, state->stage,<br>
> -                       state->mem_ctx);<br>
> +                       &state->builder);<br>
>        }<br>
>     }<br>
><br>
> @@ -160,7 +181,7 @@ lower_impl(nir_function_impl *impl, const struct gl_shader_program *shader_progr<br>
>  {<br>
>     lower_state state;<br>
><br>
> -   state.mem_ctx = ralloc_parent(impl);<br>
> +   nir_builder_init(&state.builder, impl);<br>
>     state.shader_program = shader_program;<br>
>     state.stage = stage;<br>
><br>
> --<br>
> 2.4.3<br>
><br>
> _______________________________________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>