[Mesa-dev] [PATCH] st/mesa: handle indirect samplers in arrays/structs properly (v2)
Timothy Arceri
t_arceri at yahoo.com.au
Thu Feb 4 09:33:42 UTC 2016
On Thu, 2016-02-04 at 17:44 +1000, Dave Airlie wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> The state tracker never handled this properly, and it finally
> annoyed me for the second time so I decided to fix it properly.
>
> This is inspired by the NIR sampler lowering code and I only realised
> NIR seems to do its deref ordering different to GLSL at the last
> minute, once I got that things got much easier.
>
> it fixes a bunch of tests in
> tests/spec/arb_gpu_shader5/execution/sampler_array_indexing/
>
> v2: fix AoA tests when forced on.
> I was right I didn't need all that code, fixing the AoA code
> meant cleaning up a chunk of code I didn't like in the array
> handling.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
> src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 148
> +++++++++++++++++++++++++----
> 1 file changed, 132 insertions(+), 16 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index b8182de..c44189e 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -257,6 +257,7 @@ public:
> GLboolean cond_update;
> bool saturate;
> st_src_reg sampler; /**< sampler register */
> + int sampler_base;
> int sampler_array_size; /**< 1-based size of sampler array, 1 if
> not array */
> int tex_target; /**< One of TEXTURE_*_INDEX */
> glsl_base_type tex_type;
> @@ -502,6 +503,18 @@ public:
>
> void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg
> src0);
>
> + void get_sampler_nonconst_offsets(ir_texture *ir,
> + unsigned *sampler_array_size,
> + unsigned *sampler_base,
> + unsigned *sampler_index,
> + st_src_reg *sampler_reg);
> + void calc_sampler_offsets(ir_texture *ir,
> + ir_dereference *tail,
> + unsigned *array_elements,
> + unsigned *sampler_index,
> + st_src_reg *indirect,
> + unsigned *location);
> +
> bool try_emit_mad(ir_expression *ir,
> int mul_operand);
> bool try_emit_mad_for_and_not(ir_expression *ir,
> @@ -3436,18 +3449,124 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
> this->result = entry->return_reg;
> }
>
> +static unsigned
> +glsl_get_length(const struct glsl_type *type)
> +{
> + return type->is_matrix() ? type->matrix_columns : type->length;
> +}
> +
> +void
> +glsl_to_tgsi_visitor::calc_sampler_offsets(ir_texture *ir,
> + ir_dereference *tail,
> + unsigned *array_elements,
> + unsigned *sampler_index,
> + st_src_reg *indirect,
> + unsigned *location)
> +{
> + switch (tail->ir_type) {
> + case ir_type_dereference_record: {
> + ir_dereference_record *deref_record = tail-
> >as_dereference_record();
> + const glsl_type *struct_type = deref_record->record->type;
> + int tmp = 0;
> + unsigned i;
> +
> + calc_sampler_offsets(ir, deref_record->record-
> >as_dereference(), array_elements, sampler_index, indirect,
> location);
> +
> + for (i = 0; i < struct_type->length; i++) {
> + if (strcmp(struct_type->fields.structure[i].name,
> deref_record->field) == 0)
> + break;
> + }
> + if (i < struct_type->length)
> + tmp = struct_type->record_location_offset(i);
> +
> + *location += tmp;
> + break;
> + }
> +
> + case ir_type_dereference_array: {
> + ir_dereference_array *deref_arr = tail-
> >as_dereference_array();
> + ir_constant *index = deref_arr->array_index-
> >constant_expression_value();
> +
> + if (deref_arr->array->ir_type == ir_type_dereference_variable
> && ir->sampler == tail) {
> + ir_dereference_variable *deref_var = deref_arr->array-
> >as_dereference_variable();
> + *location += deref_var->var->data.location;
> + }
> +
> + if (!index) {
> + st_src_reg temp_reg;
> + st_dst_reg temp_dst;
> +
> + temp_reg = get_temp(glsl_type::uint_type);
> + temp_dst = st_dst_reg(temp_reg);
> + temp_dst.writemask = 1;
> +
> + deref_arr->array_index->accept(this);
> + emit_asm(NULL, TGSI_OPCODE_MUL, temp_dst, this->result,
> st_src_reg_for_int(*array_elements));
> +
> + if (indirect->file == PROGRAM_UNDEFINED)
> + *indirect = temp_reg;
> + else {
> + temp_dst = st_dst_reg(*indirect);
> + temp_dst.writemask = 1;
> + emit_asm(NULL, TGSI_OPCODE_ADD, temp_dst, *indirect,
> temp_reg);
> + }
> + } else
> + *sampler_index += index->value.u[0] * *array_elements;
> +
> + *array_elements *= glsl_get_length(deref_arr->array->type);
> +
> + calc_sampler_offsets(ir, deref_arr->array->as_dereference(),
> array_elements, sampler_index, indirect, location);
> + break;
> + }
> + case ir_type_dereference_variable: {
> + if (ir->sampler == tail) {
> + ir_dereference_variable *deref_var = tail-
> >as_dereference_variable();
> + *location = deref_var->var->data.location;
> + }
> + break;
> + }
> + default:
> + break;
> + }
> +}
> +
> +void
> +glsl_to_tgsi_visitor::get_sampler_nonconst_offsets(ir_texture *ir,
> + unsigned
> *sampler_array_size,
> + unsigned
> *sampler_base,
> + unsigned
> *sampler_index,
> + st_src_reg
> *sampler_reg)
> +{
> + unsigned location = 0;
> + GLuint shader = _mesa_program_enum_to_shader_stage(this->prog-
> >Target);
> + st_src_reg indirect;
> + unsigned array_elements = 1;
> +
> + memset(&indirect, 0, sizeof(indirect));
> + indirect.file = PROGRAM_UNDEFINED;
> +
> + calc_sampler_offsets(ir, ir->sampler, &array_elements,
> sampler_index, &indirect, &location);
> +
> + if (indirect.file != PROGRAM_UNDEFINED) {
> + sampler_reg->reladdr = ralloc(mem_ctx, st_src_reg);
> + *sampler_reg->reladdr = indirect;
> + }
> + *sampler_array_size = array_elements;
> + *sampler_base = this->shader_program-
> >UniformStorage[location].opaque[shader].index;
> + *sampler_index += *sampler_base;
> +}
> +
> void
> glsl_to_tgsi_visitor::visit(ir_texture *ir)
> {
> st_src_reg result_src, coord, cube_sc, lod_info, projector, dx,
> dy;
> st_src_reg offset[MAX_GLSL_TEXTURE_OFFSET], sample_index,
> component;
> - st_src_reg levels_src;
> + st_src_reg levels_src, sampler_reg;
> st_dst_reg result_dst, coord_dst, cube_sc_dst;
> glsl_to_tgsi_instruction *inst = NULL;
> unsigned opcode = TGSI_OPCODE_NOP;
> const glsl_type *sampler_type = ir->sampler->type;
> - ir_rvalue *sampler_index =
> - _mesa_get_sampler_array_nonconst_index(ir->sampler);
This was the only user of _mesa_get_sampler_array_nonconst_index() so
you can remove this completely now.
I don't know enough about tgsi to review but it looks good as far as I
can tell.
> + unsigned sampler_array_size = 1, sampler_index = 0, sampler_base
> = 0;
> bool is_cube_array = false;
> unsigned i;
>
> @@ -3669,10 +3788,10 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
> coord_dst.writemask = WRITEMASK_XYZW;
> }
>
> - if (sampler_index) {
> - sampler_index->accept(this);
> - emit_arl(ir, sampler_reladdr, this->result);
> - }
> + get_sampler_nonconst_offsets(ir, &sampler_array_size,
> &sampler_base,
> + &sampler_index, &sampler_reg);
> + if (sampler_reg.reladdr)
> + emit_arl(ir, sampler_reladdr, *sampler_reg.reladdr);
>
> if (opcode == TGSI_OPCODE_TXD)
> inst = emit_asm(ir, opcode, result_dst, coord, dx, dy);
> @@ -3705,16 +3824,13 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
> if (ir->shadow_comparitor)
> inst->tex_shadow = GL_TRUE;
>
> - inst->sampler.index = _mesa_get_sampler_uniform_value(ir-
> >sampler,
> - this-
> >shader_program,
> - this-
> >prog);
> - if (sampler_index) {
> + inst->sampler.index = sampler_index;
> + inst->sampler_array_size = sampler_array_size;
> + inst->sampler_base = sampler_base;
> +
> + if (sampler_reg.reladdr) {
> inst->sampler.reladdr = ralloc(mem_ctx, st_src_reg);
> memcpy(inst->sampler.reladdr, &sampler_reladdr,
> sizeof(sampler_reladdr));
> - inst->sampler_array_size =
> - ir->sampler->as_dereference_array()->array->type-
> >array_size();
> - } else {
> - inst->sampler_array_size = 1;
> }
>
> if (ir->offset) {
> @@ -3915,7 +4031,7 @@ count_resources(glsl_to_tgsi_visitor *v,
> gl_program *prog)
> foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions)
> {
> if (inst->info->is_tex) {
> for (int i = 0; i < inst->sampler_array_size; i++) {
> - unsigned idx = inst->sampler.index + i;
> + unsigned idx = inst->sampler_base + i;
> v->samplers_used |= 1 << idx;
>
> debug_assert(idx < (int)ARRAY_SIZE(v->sampler_types));
More information about the mesa-dev
mailing list