<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.</p>
<p dir="ltr">nir_instr_move_src expects the source to be already in an instruction.  The reason its correct in the old code is because were stealing it from the indirect.  For adding a "new" nir_src, use nir_instr_rewrite_src.<br>
--Jason</p>
<p dir="ltr">>  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"<br>
>  #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,<br>
> +                     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;<br>
> +         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)<br>
> +{<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>