<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>