[Mesa-dev] [PATCH 11/11] glsl_to_tgsi: skip UARL for 1D registers if the driver doesn't need it

Marek Olšák maraeo at gmail.com
Fri Sep 29 12:25:34 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp       | 45 +++++++++++++++++++-----
 src/mesa/state_tracker/st_glsl_to_tgsi_private.h |  8 +++++
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index e9d98ed..879ae65 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -186,20 +186,21 @@ public:
    bool indirect_addr_consts;
    int wpos_transform_const;
 
    int glsl_version;
    bool native_integers;
    bool have_sqrt;
    bool have_fma;
    bool use_shared_memory;
    bool has_tex_txf_lz;
    bool precise;
+   bool need_uarl;
 
    variable_storage *find_variable_storage(ir_variable *var);
 
    int add_constant(gl_register_file file, gl_constant_value values[8],
                     int size, int datatype, uint16_t *swizzle_out);
 
    st_src_reg get_temp(const glsl_type *type);
    void reladdr_to_temp(ir_instruction *ir, st_src_reg *reg, int *num_reladdr);
 
    st_src_reg st_src_reg_for_double(double val);
@@ -796,22 +797,26 @@ glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, unsigned op,
 
    emit_scalar(ir, op, dst, src0, undef);
 }
 
 void
 glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir,
                                st_dst_reg dst, st_src_reg src0)
 {
    int op = TGSI_OPCODE_ARL;
 
-   if (src0.type == GLSL_TYPE_INT || src0.type == GLSL_TYPE_UINT)
-      op = TGSI_OPCODE_UARL;
+   if (src0.type == GLSL_TYPE_INT || src0.type == GLSL_TYPE_UINT) {
+      if (this->need_uarl || !src0.is_legal_tgsi_address_operand())
+         op = TGSI_OPCODE_UARL;
+      else
+         return;
+   }
 
    assert(dst.file == PROGRAM_ADDRESS);
    if (dst.index >= this->num_address_regs)
       this->num_address_regs = dst.index + 1;
 
    emit_asm(NULL, op, dst, src0);
 }
 
 int
 glsl_to_tgsi_visitor::add_constant(gl_register_file file,
@@ -5319,20 +5324,21 @@ struct st_translate {
    unsigned *array_sizes;
    struct inout_decl *input_decls;
    unsigned num_input_decls;
    struct inout_decl *output_decls;
    unsigned num_output_decls;
 
    const ubyte *inputMapping;
    const ubyte *outputMapping;
 
    unsigned procType;  /**< PIPE_SHADER_VERTEX/FRAGMENT */
+   bool need_uarl;
 };
 
 /** Map Mesa's SYSTEM_VALUE_x to TGSI_SEMANTIC_x */
 unsigned
 _mesa_sysval_to_semantic(unsigned sysval)
 {
    switch (sysval) {
    /* Vertex shader */
    case SYSTEM_VALUE_VERTEX_ID:
       return TGSI_SEMANTIC_VERTEXID;
@@ -5515,20 +5521,33 @@ dst_register(struct st_translate *t, gl_register_file file, unsigned index,
 
    case PROGRAM_ADDRESS:
       return t->address[index];
 
    default:
       assert(!"unknown dst register file");
       return ureg_dst_undef();
    }
 }
 
+static struct ureg_src
+translate_src(struct st_translate *t, const st_src_reg *src_reg);
+
+static struct ureg_src
+translate_addr(struct st_translate *t, const st_src_reg *reladdr,
+               unsigned addr_index)
+{
+   if (t->need_uarl || !reladdr->is_legal_tgsi_address_operand())
+      return ureg_src(t->address[addr_index]);
+
+   return translate_src(t, reladdr);
+}
+
 /**
  * Create a TGSI ureg_dst register from an st_dst_reg.
  */
 static struct ureg_dst
 translate_dst(struct st_translate *t,
               const st_dst_reg *dst_reg,
               bool saturate)
 {
    struct ureg_dst dst = dst_register(t, dst_reg->file, dst_reg->index,
                                       dst_reg->array_id);
@@ -5536,26 +5555,27 @@ translate_dst(struct st_translate *t,
    if (dst.File == TGSI_FILE_NULL)
       return dst;
 
    dst = ureg_writemask(dst, dst_reg->writemask);
 
    if (saturate)
       dst = ureg_saturate(dst);
 
    if (dst_reg->reladdr != NULL) {
       assert(dst_reg->file != PROGRAM_TEMPORARY);
-      dst = ureg_dst_indirect(dst, ureg_src(t->address[0]));
+      dst = ureg_dst_indirect(dst, translate_addr(t, dst_reg->reladdr, 0));
    }
 
    if (dst_reg->has_index2) {
       if (dst_reg->reladdr2)
-         dst = ureg_dst_dimension_indirect(dst, ureg_src(t->address[1]),
+         dst = ureg_dst_dimension_indirect(dst,
+                                           translate_addr(t, dst_reg->reladdr2, 1),
                                            dst_reg->index2D);
       else
          dst = ureg_dst_dimension(dst, dst_reg->index2D);
    }
 
    return dst;
 }
 
 /**
  * Create a TGSI ureg_src register from an st_src_reg.
@@ -5644,41 +5664,42 @@ translate_src(struct st_translate *t, const st_src_reg *src_reg)
    default:
       assert(!"unknown src register file");
       return ureg_src_undef();
    }
 
    if (src_reg->has_index2) {
       /* 2D indexes occur with geometry shader inputs (attrib, vertex)
        * and UBO constant buffers (buffer, position).
        */
       if (src_reg->reladdr2)
-         src = ureg_src_dimension_indirect(src, ureg_src(t->address[1]),
+         src = ureg_src_dimension_indirect(src,
+                                           translate_addr(t, src_reg->reladdr2, 1),
                                            src_reg->index2D);
       else
          src = ureg_src_dimension(src, src_reg->index2D);
    }
 
    src = ureg_swizzle(src,
                       GET_SWZ(src_reg->swizzle, 0) & 0x3,
                       GET_SWZ(src_reg->swizzle, 1) & 0x3,
                       GET_SWZ(src_reg->swizzle, 2) & 0x3,
                       GET_SWZ(src_reg->swizzle, 3) & 0x3);
 
    if (src_reg->abs)
       src = ureg_abs(src);
 
    if ((src_reg->negate & 0xf) == NEGATE_XYZW)
       src = ureg_negate(src);
 
    if (src_reg->reladdr != NULL) {
       assert(src_reg->file != PROGRAM_TEMPORARY);
-      src = ureg_src_indirect(src, ureg_src(t->address[0]));
+      src = ureg_src_indirect(src, translate_addr(t, src_reg->reladdr, 0));
    }
 
    return src;
 }
 
 static struct tgsi_texture_offset
 translate_tex_offset(struct st_translate *t,
                      const st_src_reg *in_offset)
 {
    struct tgsi_texture_offset offset;
@@ -5752,21 +5773,22 @@ compile_tgsi_instruction(struct st_translate *t,
    case TGSI_OPCODE_LODQ:
       if (inst->resource.file == PROGRAM_SAMPLER) {
          src[num_src] = t->samplers[inst->resource.index];
       } else {
          /* Bindless samplers. */
          src[num_src] = translate_src(t, &inst->resource);
       }
       assert(src[num_src].File != TGSI_FILE_NULL);
       if (inst->resource.reladdr)
          src[num_src] =
-            ureg_src_indirect(src[num_src], ureg_src(t->address[2]));
+            ureg_src_indirect(src[num_src],
+                              translate_addr(t, inst->resource.reladdr, 2));
       num_src++;
       for (i = 0; i < (int)inst->tex_offset_num_offset; i++) {
          texoffsets[i] = translate_tex_offset(t, &inst->tex_offsets[i]);
       }
       tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
 
       ureg_tex_insn(ureg,
                     inst->op,
                     dst, num_dst,
                     tex_target,
@@ -5801,21 +5823,22 @@ compile_tgsi_instruction(struct st_translate *t,
          assert(inst->resource.file != PROGRAM_UNDEFINED);
          if (inst->resource.file == PROGRAM_IMAGE) {
             src[0] = t->images[inst->resource.index];
          } else {
             /* Bindless images. */
             src[0] = translate_src(t, &inst->resource);
          }
          tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
       }
       if (inst->resource.reladdr)
-         src[0] = ureg_src_indirect(src[0], ureg_src(t->address[2]));
+         src[0] = ureg_src_indirect(src[0],
+                                    translate_addr(t, inst->resource.reladdr, 2));
       assert(src[0].File != TGSI_FILE_NULL);
       ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
                        inst->buffer_access,
                        tex_target, inst->image_format);
       break;
 
    case TGSI_OPCODE_STORE:
       if (inst->resource.file == PROGRAM_MEMORY) {
          dst[0] = ureg_dst(t->shared_memory);
       } else if (inst->resource.file == PROGRAM_BUFFER) {
@@ -5824,21 +5847,22 @@ compile_tgsi_instruction(struct st_translate *t,
          if (inst->resource.file == PROGRAM_IMAGE) {
             dst[0] = ureg_dst(t->images[inst->resource.index]);
          } else {
             /* Bindless images. */
             dst[0] = ureg_dst(translate_src(t, &inst->resource));
          }
          tex_target = st_translate_texture_target(inst->tex_target, inst->tex_shadow);
       }
       dst[0] = ureg_writemask(dst[0], inst->dst[0].writemask);
       if (inst->resource.reladdr)
-         dst[0] = ureg_dst_indirect(dst[0], ureg_src(t->address[2]));
+         dst[0] = ureg_dst_indirect(dst[0],
+                                    translate_addr(t, inst->resource.reladdr, 2));
       assert(dst[0].File != TGSI_FILE_NULL);
       ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
                        inst->buffer_access,
                        tex_target, inst->image_format);
       break;
 
    default:
       ureg_insn(ureg,
                 inst->op,
                 dst, num_dst,
@@ -6143,36 +6167,38 @@ st_translate_program(
    const ubyte inputMapping[],
    const ubyte inputSlotToAttr[],
    const ubyte inputSemanticName[],
    const ubyte inputSemanticIndex[],
    const ubyte interpMode[],
    GLuint numOutputs,
    const ubyte outputMapping[],
    const ubyte outputSemanticName[],
    const ubyte outputSemanticIndex[])
 {
+   struct pipe_screen *screen = st_context(ctx)->pipe->screen;
    struct st_translate *t;
    unsigned i;
    struct gl_program_constants *frag_const =
       &ctx->Const.Program[MESA_SHADER_FRAGMENT];
    enum pipe_error ret = PIPE_OK;
 
    assert(numInputs <= ARRAY_SIZE(t->inputs));
    assert(numOutputs <= ARRAY_SIZE(t->outputs));
 
    t = CALLOC_STRUCT(st_translate);
    if (!t) {
       ret = PIPE_ERROR_OUT_OF_MEMORY;
       goto out;
    }
 
    t->procType = procType;
+   t->need_uarl = !screen->get_param(screen, PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS);
    t->inputMapping = inputMapping;
    t->outputMapping = outputMapping;
    t->ureg = ureg;
    t->num_temp_arrays = program->next_array;
    if (t->num_temp_arrays)
       t->arrays = (struct ureg_dst*)
                   calloc(t->num_temp_arrays, sizeof(t->arrays[0]));
 
    /*
     * Declare input attributes.
@@ -6584,20 +6610,21 @@ get_mesa_program_tgsi(struct gl_context *ctx,
    v->options = options;
    v->glsl_version = ctx->Const.GLSLVersion;
    v->native_integers = ctx->Const.NativeIntegers;
 
    v->have_sqrt = pscreen->get_shader_param(pscreen, ptarget,
                                             PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED);
    v->have_fma = pscreen->get_shader_param(pscreen, ptarget,
                                            PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED);
    v->has_tex_txf_lz = pscreen->get_param(pscreen,
                                           PIPE_CAP_TGSI_TEX_TXF_LZ);
+   v->need_uarl = !pscreen->get_param(pscreen, PIPE_CAP_TGSI_ANY_REG_AS_ADDRESS);
 
    v->variables = _mesa_hash_table_create(v->mem_ctx, _mesa_hash_pointer,
                                           _mesa_key_pointer_equal);
    skip_merge_registers =
       pscreen->get_shader_param(pscreen, ptarget,
                                 PIPE_SHADER_CAP_TGSI_SKIP_MERGE_REGISTERS);
 
    _mesa_generate_parameters_list_for_uniforms(ctx, shader_program, shader,
                                                prog->Parameters);
 
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi_private.h b/src/mesa/state_tracker/st_glsl_to_tgsi_private.h
index b9112e5..d57525d 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi_private.h
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi_private.h
@@ -67,20 +67,28 @@ public:
     * Is this the second half of a double register pair?
     * currently used for input mapping only.
     */
    unsigned double_reg2:1;
    unsigned is_double_vertex_input:1;
    unsigned array_id:10;
    /** Register index should be offset by the integer in this reg. */
    st_src_reg *reladdr;
    st_src_reg *reladdr2;
 
+   bool is_legal_tgsi_address_operand() const
+   {
+      /* 2D registers can't be used as an address operand, or if the address
+       * operand itself is a result of indirect addressing.
+       */
+      return (type == GLSL_TYPE_INT || type == GLSL_TYPE_UINT) &&
+             !has_index2 && !reladdr && !reladdr2;
+   }
 };
 
 class st_dst_reg {
 public:
    st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type, int index);
 
    st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type);
 
    st_dst_reg();
    st_dst_reg(const st_dst_reg &reg);
-- 
2.7.4



More information about the mesa-dev mailing list