[Mesa-dev] [PATCH 6/7] st/mesa: convert GLSL image intrinsics into TGSI

Ilia Mirkin imirkin at alum.mit.edu
Sat Jan 30 17:55:46 PST 2016


Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---
 src/mesa/main/mtypes.h                     |   1 +
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 226 ++++++++++++++++++++++++++++-
 2 files changed, 223 insertions(+), 4 deletions(-)

diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 101283c..adaa2e9 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1863,6 +1863,7 @@ typedef enum
    PROGRAM_UNDEFINED,   /**< Invalid/TBD value */
    PROGRAM_IMMEDIATE,   /**< Immediate value, used by TGSI */
    PROGRAM_BUFFER,      /**< for shader buffers, compile-time only */
+   PROGRAM_IMAGE,       /**< for shader images, compile-time only */
    PROGRAM_FILE_MAX
 } gl_register_file;
 
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index baf3504..f0762b0 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -39,6 +39,7 @@
 #include "main/shaderobj.h"
 #include "main/uniforms.h"
 #include "main/shaderapi.h"
+#include "main/shaderimage.h"
 #include "program/prog_instruction.h"
 #include "program/sampler.h"
 
@@ -50,6 +51,7 @@
 #include "util/u_memory.h"
 #include "st_program.h"
 #include "st_mesa_to_tgsi.h"
+#include "st_format.h"
 
 
 #define PROGRAM_ANY_CONST ((1 << PROGRAM_STATE_VAR) |    \
@@ -261,6 +263,7 @@ public:
    int tex_target; /**< One of TEXTURE_*_INDEX */
    glsl_base_type tex_type;
    GLboolean tex_shadow;
+   unsigned image_format;
 
    st_src_reg tex_offsets[MAX_GLSL_TEXTURE_OFFSET];
    unsigned tex_offset_num_offset;
@@ -394,6 +397,9 @@ public:
    glsl_base_type sampler_types[PIPE_MAX_SAMPLERS];
    int sampler_targets[PIPE_MAX_SAMPLERS];   /**< One of TGSI_TEXTURE_* */
    int buffers_used;
+   int images_used;
+   int image_targets[PIPE_MAX_SHADER_IMAGES];
+   unsigned image_formats[PIPE_MAX_SHADER_IMAGES];
    bool indirect_addr_consts;
    int wpos_transform_const;
 
@@ -450,6 +456,7 @@ public:
    void visit_atomic_counter_intrinsic(ir_call *);
    void visit_ssbo_intrinsic(ir_call *);
    void visit_membar_intrinsic(ir_call *);
+   void visit_image_intrinsic(ir_call *);
 
    st_src_reg result;
 
@@ -3332,6 +3339,171 @@ glsl_to_tgsi_visitor::visit_membar_intrinsic(ir_call *ir)
 }
 
 void
+glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir)
+{
+   const char *callee = ir->callee->function_name();
+   exec_node *param = ir->actual_parameters.get_head();
+
+   ir_dereference *img = (ir_dereference *)param;
+   const ir_variable *imgvar = img->variable_referenced();
+   const glsl_type *type = imgvar->type->without_array();
+   ir_rvalue *image_index = _mesa_get_sampler_array_nonconst_index(img);
+
+   st_src_reg image(
+         PROGRAM_IMAGE,
+         0,
+         GLSL_TYPE_UINT);
+
+   image.index = _mesa_get_sampler_uniform_value(img,
+                                                 this->shader_program,
+                                                 this->prog);
+   if (image_index) {
+      image_index->accept(this);
+      emit_arl(ir, sampler_reladdr, this->result);
+      image.reladdr = ralloc(mem_ctx, st_src_reg);
+      memcpy(image.reladdr, &sampler_reladdr, sizeof(sampler_reladdr));
+   }
+
+   st_dst_reg dst = undef_dst;
+   if (ir->return_deref) {
+      ir->return_deref->accept(this);
+      dst = st_dst_reg(this->result);
+      dst.writemask = (1 << ir->return_deref->type->vector_elements) - 1;
+   }
+
+   glsl_to_tgsi_instruction *inst;
+
+   if (!strcmp("__intrinsic_image_size", callee)) {
+      dst.writemask = WRITEMASK_XYZ;
+      inst = emit_asm(ir, TGSI_OPCODE_RESQ, dst);
+   } else if (!strcmp("__intrinsic_image_samples", callee)) {
+      st_src_reg res = get_temp(glsl_type::ivec4_type);
+      st_dst_reg dstres = st_dst_reg(res);
+      dstres.writemask = WRITEMASK_W;
+      emit_asm(ir, TGSI_OPCODE_RESQ, dstres);
+      res.swizzle = SWIZZLE_WWWW;
+      inst = emit_asm(ir, TGSI_OPCODE_MOV, dst, res);
+   } else {
+      st_src_reg arg1 = undef_src, arg2 = undef_src;
+      st_src_reg coord;
+      st_dst_reg coord_dst;
+      coord = get_temp(glsl_type::ivec4_type);
+      coord_dst = st_dst_reg(coord);
+      coord_dst.writemask = (1 << type->coordinate_components()) - 1;
+      param = param->get_next();
+      ((ir_dereference *)param)->accept(this);
+      emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, this->result);
+      coord.swizzle = SWIZZLE_XXXX;
+      switch (type->coordinate_components()) {
+      case 4: assert(!"unexpected coord count");
+      /* fallthrough */
+      case 3: coord.swizzle |= SWIZZLE_Z << 6;
+      /* fallthrough */
+      case 2: coord.swizzle |= SWIZZLE_Y << 3;
+      }
+
+      if (type->sampler_dimensionality == GLSL_SAMPLER_DIM_MS) {
+         param = param->get_next();
+         ((ir_dereference *)param)->accept(this);
+         st_src_reg sample = this->result;
+         sample.swizzle = SWIZZLE_XXXX;
+         coord_dst.writemask = WRITEMASK_W;
+         emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, sample);
+         coord.swizzle |= SWIZZLE_W << 9;
+      }
+
+      param = param->get_next();
+      if (!param->is_tail_sentinel()) {
+         ((ir_dereference *)param)->accept(this);
+         arg1 = this->result;
+         param = param->get_next();
+      }
+
+      if (!param->is_tail_sentinel()) {
+         ((ir_dereference *)param)->accept(this);
+         arg2 = this->result;
+         param = param->get_next();
+      }
+
+      assert(param->is_tail_sentinel());
+
+      unsigned opcode;
+      if (!strcmp("__intrinsic_image_load", callee))
+         opcode = TGSI_OPCODE_LOAD;
+      else if (!strcmp("__intrinsic_image_store", callee))
+         opcode = TGSI_OPCODE_STORE;
+      else if (!strcmp("__intrinsic_image_atomic_add", callee))
+         opcode = TGSI_OPCODE_ATOMUADD;
+      else if (!strcmp("__intrinsic_image_atomic_min", callee))
+         opcode = TGSI_OPCODE_ATOMIMIN;
+      else if (!strcmp("__intrinsic_image_atomic_max", callee))
+         opcode = TGSI_OPCODE_ATOMIMAX;
+      else if (!strcmp("__intrinsic_image_atomic_and", callee))
+         opcode = TGSI_OPCODE_ATOMAND;
+      else if (!strcmp("__intrinsic_image_atomic_or", callee))
+         opcode = TGSI_OPCODE_ATOMOR;
+      else if (!strcmp("__intrinsic_image_atomic_xor", callee))
+         opcode = TGSI_OPCODE_ATOMXOR;
+      else if (!strcmp("__intrinsic_image_atomic_exchange", callee))
+         opcode = TGSI_OPCODE_ATOMXCHG;
+      else if (!strcmp("__intrinsic_image_atomic_comp_swap", callee))
+         opcode = TGSI_OPCODE_ATOMCAS;
+      else {
+         assert(!"Unexpected intrinsic");
+         return;
+      }
+
+      inst = emit_asm(ir, opcode, dst, coord, arg1, arg2);
+      if (opcode == TGSI_OPCODE_STORE)
+         inst->dst[0].writemask = WRITEMASK_XYZW;
+   }
+
+   inst->buffer = image;
+   if (image_index) {
+      inst->sampler_array_size =
+         img->as_dereference_array()->array->type->array_size();
+   } else {
+      inst->sampler_array_size = 1;
+   }
+
+   switch (type->sampler_dimensionality) {
+   case GLSL_SAMPLER_DIM_1D:
+      inst->tex_target = (type->sampler_array)
+         ? TEXTURE_1D_ARRAY_INDEX : TEXTURE_1D_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_2D:
+      inst->tex_target = (type->sampler_array)
+         ? TEXTURE_2D_ARRAY_INDEX : TEXTURE_2D_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_3D:
+      inst->tex_target = TEXTURE_3D_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_CUBE:
+      inst->tex_target = (type->sampler_array)
+         ? TEXTURE_CUBE_ARRAY_INDEX : TEXTURE_CUBE_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_RECT:
+      inst->tex_target = TEXTURE_RECT_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_BUF:
+      inst->tex_target = TEXTURE_BUFFER_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_EXTERNAL:
+      inst->tex_target = TEXTURE_EXTERNAL_INDEX;
+      break;
+   case GLSL_SAMPLER_DIM_MS:
+      inst->tex_target = (type->sampler_array)
+         ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
+      break;
+   default:
+      assert(!"Should not get here.");
+   }
+
+   inst->image_format = st_mesa_format_to_pipe_format(st_context(ctx),
+         _mesa_get_shader_image_format(imgvar->data.image_format));
+}
+
+void
 glsl_to_tgsi_visitor::visit(ir_call *ir)
 {
    glsl_to_tgsi_instruction *call_inst;
@@ -3372,6 +3544,22 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
       return;
    }
 
+   if (!strcmp("__intrinsic_image_load", callee) ||
+       !strcmp("__intrinsic_image_store", callee) ||
+       !strcmp("__intrinsic_image_atomic_add", callee) ||
+       !strcmp("__intrinsic_image_atomic_min", callee) ||
+       !strcmp("__intrinsic_image_atomic_max", callee) ||
+       !strcmp("__intrinsic_image_atomic_and", callee) ||
+       !strcmp("__intrinsic_image_atomic_or", callee) ||
+       !strcmp("__intrinsic_image_atomic_xor", callee) ||
+       !strcmp("__intrinsic_image_atomic_exchange", callee) ||
+       !strcmp("__intrinsic_image_atomic_comp_swap", callee) ||
+       !strcmp("__intrinsic_image_size", callee) ||
+       !strcmp("__intrinsic_image_samples", callee)) {
+      visit_image_intrinsic(ir);
+      return;
+   }
+
    entry = get_function_signature(sig);
    /* Process in parameters. */
    foreach_two_lists(formal_node, &sig->parameters,
@@ -3879,6 +4067,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
    num_address_regs = 0;
    samplers_used = 0;
    buffers_used = 0;
+   images_used = 0;
    indirect_addr_consts = false;
    wpos_transform_const = -1;
    glsl_version = 0;
@@ -3914,6 +4103,7 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog)
 {
    v->samplers_used = 0;
    v->buffers_used = 0;
+   v->images_used = 0;
 
    foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) {
       if (inst->info->is_tex) {
@@ -3934,8 +4124,18 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog)
       if (inst->buffer.file != PROGRAM_UNDEFINED && (
                 is_resource_instruction(inst->op) ||
                 inst->op == TGSI_OPCODE_STORE)) {
-         if (inst->buffer.file == PROGRAM_BUFFER)
+         if (inst->buffer.file == PROGRAM_BUFFER) {
             v->buffers_used |= 1 << inst->buffer.index;
+         } else {
+            assert(inst->buffer.file == PROGRAM_IMAGE);
+            for (int i = 0; i < inst->sampler_array_size; i++) {
+               unsigned idx = inst->buffer.index + i;
+               v->images_used |= 1 << idx;
+               v->image_targets[idx] =
+                  st_translate_texture_target(inst->tex_target, false);
+               v->image_formats[idx] = inst->image_format;
+            }
+         }
       }
    }
    prog->SamplersUsed = v->samplers_used;
@@ -4715,6 +4915,7 @@ struct st_translate {
    struct ureg_dst address[3];
    struct ureg_src samplers[PIPE_MAX_SAMPLERS];
    struct ureg_src buffers[PIPE_MAX_SHADER_BUFFERS];
+   struct ureg_src images[PIPE_MAX_SHADER_IMAGES];
    struct ureg_src systemValues[SYSTEM_VALUE_MAX];
    struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET];
    unsigned *array_sizes;
@@ -5204,7 +5405,10 @@ compile_tgsi_instruction(struct st_translate *t,
       for (i = num_src - 1; i >= 0; i--)
          src[i + 1] = src[i];
       num_src++;
-      src[0] = t->buffers[inst->buffer.index];
+      if (inst->buffer.file == PROGRAM_BUFFER)
+         src[0] = t->buffers[inst->buffer.index];
+      else
+         src[0] = t->images[inst->buffer.index];
       if (inst->buffer.reladdr)
          src[0] = ureg_src_indirect(src[0], ureg_src(t->address[2]));
       assert(src[0].File != TGSI_FILE_NULL);
@@ -5212,14 +5416,20 @@ compile_tgsi_instruction(struct st_translate *t,
                        inst->buffer_access);
       break;
 
-   case TGSI_OPCODE_STORE:
-      dst[0] = ureg_writemask(ureg_dst(t->buffers[inst->buffer.index]), inst->dst[0].writemask);
+   case TGSI_OPCODE_STORE: {
+      struct ureg_src tdst;
+      if (inst->buffer.file == PROGRAM_BUFFER)
+         tdst = t->buffers[inst->buffer.index];
+      else
+         tdst = t->images[inst->buffer.index];
+      dst[0] = ureg_writemask(ureg_dst(tdst), inst->dst[0].writemask);
       if (inst->buffer.reladdr)
          dst[0] = ureg_dst_indirect(dst[0], ureg_src(t->address[2]));
       assert(dst[0].File != TGSI_FILE_NULL);
       ureg_memory_insn(ureg, inst->op, dst, num_dst, src, num_src,
                        inst->buffer_access);
       break;
+   }
 
    case TGSI_OPCODE_SCS:
       dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XY);
@@ -5865,6 +6075,14 @@ st_translate_program(
       }
    }
 
+   for (i = 0; i < program->shader->NumImages; i++) {
+      if (program->images_used & (1 << i)) {
+         t->images[i] = ureg_DECL_image(ureg, i,
+                                        program->image_targets[i],
+                                        program->image_formats[i],
+                                        true, false);
+      }
+   }
 
 
    /* Emit each instruction in turn:
-- 
2.4.10



More information about the mesa-dev mailing list