[Mesa-dev] [PATCH v3 13/19] st/mesa: add intrinsics for shared variables

Samuel Pitoiset samuel.pitoiset at gmail.com
Wed Feb 10 18:10:42 UTC 2016


This adds GLSL intrinsics for load/store and atomic operations.

Changes from v2:
 - use PROGRAM_MEMORY instead of PROGRAM_BUFFER

Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Reviewed-by: Ilia Mirkin <imirkin at alum.mit.edu> (v1)
---
 src/mesa/state_tracker/st_extensions.c     |  3 +
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 91 ++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)

diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c
index 556cd65..6736ebc 100644
--- a/src/mesa/state_tracker/st_extensions.c
+++ b/src/mesa/state_tracker/st_extensions.c
@@ -264,6 +264,9 @@ void st_init_limits(struct pipe_screen *screen,
 
       options->LowerClipDistance = true;
       options->LowerBufferInterfaceBlocks = true;
+
+      if (sh == PIPE_SHADER_COMPUTE)
+         options->LowerShaderSharedVariables = true;
    }
 
    c->LowerTessLevel = true;
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 8827dd1..e0a38c4 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -450,6 +450,7 @@ public:
    void visit_atomic_counter_intrinsic(ir_call *);
    void visit_ssbo_intrinsic(ir_call *);
    void visit_membar_intrinsic(ir_call *);
+   void visit_shared_intrinsic(ir_call *);
 
    st_src_reg result;
 
@@ -3340,6 +3341,82 @@ glsl_to_tgsi_visitor::visit_membar_intrinsic(ir_call *ir)
 }
 
 void
+glsl_to_tgsi_visitor::visit_shared_intrinsic(ir_call *ir)
+{
+   const char *callee = ir->callee->function_name();
+   exec_node *param = ir->actual_parameters.get_head();
+
+   ir_rvalue *offset = ((ir_instruction *)param)->as_rvalue();
+
+   st_src_reg buffer(PROGRAM_MEMORY, 0, GLSL_TYPE_UINT);
+
+   /* Calculate the surface offset */
+   offset->accept(this);
+   st_src_reg off = this->result;
+
+   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_load_shared", callee)) {
+      inst = emit_asm(ir, TGSI_OPCODE_LOAD, dst, off);
+      inst->buffer = buffer;
+   } else if (!strcmp("__intrinsic_store_shared", callee)) {
+      param = param->get_next();
+      ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
+      val->accept(this);
+
+      param = param->get_next();
+      ir_constant *write_mask = ((ir_instruction *)param)->as_constant();
+      assert(write_mask);
+      dst.writemask = write_mask->value.u[0];
+
+      dst.type = this->result.type;
+      inst = emit_asm(ir, TGSI_OPCODE_STORE, dst, off, this->result);
+      inst->buffer = buffer;
+   } else {
+      param = param->get_next();
+      ir_rvalue *val = ((ir_instruction *)param)->as_rvalue();
+      val->accept(this);
+
+      st_src_reg data = this->result, data2 = undef_src;
+      unsigned opcode;
+      if (!strcmp("__intrinsic_atomic_add_shared", callee))
+         opcode = TGSI_OPCODE_ATOMUADD;
+      else if (!strcmp("__intrinsic_atomic_min_shared", callee))
+         opcode = TGSI_OPCODE_ATOMIMIN;
+      else if (!strcmp("__intrinsic_atomic_max_shared", callee))
+         opcode = TGSI_OPCODE_ATOMIMAX;
+      else if (!strcmp("__intrinsic_atomic_and_shared", callee))
+         opcode = TGSI_OPCODE_ATOMAND;
+      else if (!strcmp("__intrinsic_atomic_or_shared", callee))
+         opcode = TGSI_OPCODE_ATOMOR;
+      else if (!strcmp("__intrinsic_atomic_xor_shared", callee))
+         opcode = TGSI_OPCODE_ATOMXOR;
+      else if (!strcmp("__intrinsic_atomic_exchange_shared", callee))
+         opcode = TGSI_OPCODE_ATOMXCHG;
+      else if (!strcmp("__intrinsic_atomic_comp_swap_shared", callee)) {
+         opcode = TGSI_OPCODE_ATOMCAS;
+         param = param->get_next();
+         val = ((ir_instruction *)param)->as_rvalue();
+         val->accept(this);
+         data2 = this->result;
+      } else {
+         assert(!"Unexpected intrinsic");
+         return;
+      }
+
+      inst = emit_asm(ir, opcode, dst, off, data, data2);
+      inst->buffer = buffer;
+   }
+}
+
+void
 glsl_to_tgsi_visitor::visit(ir_call *ir)
 {
    glsl_to_tgsi_instruction *call_inst;
@@ -3380,6 +3457,20 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
       return;
    }
 
+   if (!strcmp("__intrinsic_load_shared", callee) ||
+       !strcmp("__intrinsic_store_shared", callee) ||
+       !strcmp("__intrinsic_atomic_add_shared", callee) ||
+       !strcmp("__intrinsic_atomic_min_shared", callee) ||
+       !strcmp("__intrinsic_atomic_max_shared", callee) ||
+       !strcmp("__intrinsic_atomic_and_shared", callee) ||
+       !strcmp("__intrinsic_atomic_or_shared", callee) ||
+       !strcmp("__intrinsic_atomic_xor_shared", callee) ||
+       !strcmp("__intrinsic_atomic_exchange_shared", callee) ||
+       !strcmp("__intrinsic_atomic_comp_swap_shared", callee)) {
+      visit_shared_intrinsic(ir);
+      return;
+   }
+
    entry = get_function_signature(sig);
    /* Process in parameters. */
    foreach_two_lists(formal_node, &sig->parameters,
-- 
2.6.4



More information about the mesa-dev mailing list