<p dir="ltr"><br>
On Aug 30, 2015 9:27 PM, "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>
> V2: Fixed validation error in debug build<br>
> ---<br>
> Â src/glsl/nir/nir_lower_samplers.cpp | 168 ++++++++++++++++++++----------------<br>
> Â 1 file changed, 94 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..e07ca38 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,51 @@ 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>
> +  Â  Â  Â  Â  Â  list_del(&deref_array->indirect.use_link);</p>
<p dir="ltr">Another way to do this is nir_instr_rewrite_src(instr, src, NIR_SRC_INIT).  That's probably "better". We really need a nir_src_finish function.</p>
<p dir="ltr">> +<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 +88,72 @@ 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>
> +  Â  Â  Â  Â instr->src[instr->num_srcs].src_type = nir_tex_src_sampler_offset;<br>
> +  Â  Â  Â  Â instr->num_srcs++;<br>
> +  Â  Â  Â  Â nir_instr_rewrite_src(&instr->instr,<br>
> +  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â &instr->src[instr->num_srcs - 1].src,<br>
> +  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â indirect);<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 +167,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 +180,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>