[Mesa-stable] [PATCH 4/5] st/glsl_to_tgsi: fix atomic counter addressing

Nicolai Hähnle nhaehnle at gmail.com
Thu Oct 13 15:13:16 UTC 2016


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

When more than one atomic counter buffer is in use, UniformStorage[n].opaque
is set up to contain indices that are contiguous across all used buffers.

This appears to be used by i965 via NIR, but for TGSI we do not treat atomic
counter buffers as opaque, so using the data in the opaque array is incorrect.

Fixes GL45-CTS.compute_shader.resource-atomic-counter.

Cc: mesa-stable at lists.freedesktop.org
---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index a7ea19f..682c034 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -545,21 +545,22 @@ public:
 
    void emit_scalar(ir_instruction *ir, unsigned op,
                     st_dst_reg dst, st_src_reg src0, st_src_reg src1);
 
    void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0);
 
    void get_deref_offsets(ir_dereference *ir,
                           unsigned *array_size,
                           unsigned *base,
                           unsigned *index,
-                          st_src_reg *reladdr);
+                          st_src_reg *reladdr,
+                          bool opaque);
   void calc_deref_offsets(ir_dereference *head,
                           ir_dereference *tail,
                           unsigned *array_elements,
                           unsigned *base,
                           unsigned *index,
                           st_src_reg *indirect,
                           unsigned *location);
    st_src_reg canonicalize_gather_offset(st_src_reg offset);
 
    bool try_emit_mad(ir_expression *ir,
@@ -3247,21 +3248,21 @@ glsl_to_tgsi_visitor::visit_atomic_counter_intrinsic(ir_call *ir)
    ir_dereference *deref = static_cast<ir_dereference *>(param);
    ir_variable *location = deref->variable_referenced();
 
    st_src_reg buffer(
          PROGRAM_BUFFER, location->data.binding, GLSL_TYPE_ATOMIC_UINT);
 
    /* Calculate the surface offset */
    st_src_reg offset;
    unsigned array_size = 0, base = 0, index = 0;
 
-   get_deref_offsets(deref, &array_size, &base, &index, &offset);
+   get_deref_offsets(deref, &array_size, &base, &index, &offset, false);
 
    if (offset.file != PROGRAM_UNDEFINED) {
       emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(offset),
                offset, st_src_reg_for_int(ATOMIC_COUNTER_SIZE));
       emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(offset),
                offset, st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE));
    } else {
       offset = st_src_reg_for_int(location->data.offset + index * ATOMIC_COUNTER_SIZE);
    }
 
@@ -3578,21 +3579,21 @@ glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
 
    ir_dereference *img = (ir_dereference *)param;
    const ir_variable *imgvar = img->variable_referenced();
    const glsl_type *type = imgvar->type->without_array();
    unsigned sampler_array_size = 1, sampler_base = 0;
 
    st_src_reg reladdr;
    st_src_reg image(PROGRAM_IMAGE, 0, GLSL_TYPE_UINT);
 
    get_deref_offsets(img, &sampler_array_size, &sampler_base,
-                     (unsigned int *)&image.index, &reladdr);
+                     (unsigned int *)&image.index, &reladdr, true);
    if (reladdr.file != PROGRAM_UNDEFINED) {
       image.reladdr = ralloc(mem_ctx, st_src_reg);
       *image.reladdr = reladdr;
       emit_arl(ir, sampler_reladdr, reladdr);
    }
 
    st_dst_reg dst = undef_dst;
    if (ir->return_deref) {
       ir->return_deref->accept(this);
       dst = st_dst_reg(this->result);
@@ -3960,21 +3961,22 @@ glsl_to_tgsi_visitor::calc_deref_offsets(ir_dereference *head,
    default:
       break;
    }
 }
 
 void
 glsl_to_tgsi_visitor::get_deref_offsets(ir_dereference *ir,
                                         unsigned *array_size,
                                         unsigned *base,
                                         unsigned *index,
-                                        st_src_reg *reladdr)
+                                        st_src_reg *reladdr,
+                                        bool opaque)
 {
    GLuint shader = _mesa_program_enum_to_shader_stage(this->prog->Target);
    unsigned location = 0;
    ir_variable *var = ir->variable_referenced();
 
    memset(reladdr, 0, sizeof(*reladdr));
    reladdr->file = PROGRAM_UNDEFINED;
 
    *base = 0;
    *array_size = 1;
@@ -3985,21 +3987,22 @@ glsl_to_tgsi_visitor::get_deref_offsets(ir_dereference *ir,
 
    /*
     * If we end up with no indirect then adjust the base to the index,
     * and set the array size to 1.
     */
    if (reladdr->file == PROGRAM_UNDEFINED) {
       *base = *index;
       *array_size = 1;
    }
 
-   if (location != 0xffffffff) {
+   if (opaque) {
+      assert(location != 0xffffffff);
       *base += this->shader_program->UniformStorage[location].opaque[shader].index;
       *index += this->shader_program->UniformStorage[location].opaque[shader].index;
    }
 }
 
 st_src_reg
 glsl_to_tgsi_visitor::canonicalize_gather_offset(st_src_reg offset)
 {
    if (offset.reladdr || offset.reladdr2) {
       st_src_reg tmp = get_temp(glsl_type::ivec2_type);
@@ -4239,21 +4242,21 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
       coord_dst.writemask = WRITEMASK_XYZW;
    } else if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
        opcode == TGSI_OPCODE_TXF) {
       /* TGSI stores LOD or LOD bias in the last channel of the coords. */
       coord_dst.writemask = WRITEMASK_W;
       emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, lod_info);
       coord_dst.writemask = WRITEMASK_XYZW;
    }
 
    get_deref_offsets(ir->sampler, &sampler_array_size, &sampler_base,
-                     &sampler_index, &reladdr);
+                     &sampler_index, &reladdr, true);
    if (reladdr.file != PROGRAM_UNDEFINED)
       emit_arl(ir, sampler_reladdr, reladdr);
 
    if (opcode == TGSI_OPCODE_TXD)
       inst = emit_asm(ir, opcode, result_dst, coord, dx, dy);
    else if (opcode == TGSI_OPCODE_TXQ) {
       if (ir->op == ir_query_levels) {
          /* the level is stored in W */
          inst = emit_asm(ir, opcode, st_dst_reg(levels_src), lod_info);
          result_dst.writemask = WRITEMASK_X;
-- 
2.7.4



More information about the mesa-stable mailing list