r600/sfn: Add support for SSBO load and store
authorGert Wollny <gert.wollny@collabora.com>
Sat, 28 Dec 2019 15:48:45 +0000 (16:48 +0100)
committerMarge Bot <eric+marge@anholt.net>
Mon, 10 Feb 2020 19:09:08 +0000 (19:09 +0000)
Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3225>

src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp
src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h
src/gallium/drivers/r600/sfn/sfn_shader_base.cpp

index 0b5bc5f..302e8ef 100644 (file)
@@ -27,6 +27,10 @@ bool EmitSSBOInstruction::do_emit(nir_instr* instr)
       return emit_atomic_inc(intr);
    case nir_intrinsic_atomic_counter_pre_dec:
       return emit_atomic_pre_dec(intr);
+   case nir_intrinsic_load_ssbo:
+       return emit_load_ssbo(intr);
+    case nir_intrinsic_store_ssbo:
+      return emit_store_ssbo(intr);
    default:
       return false;
    }
@@ -165,6 +169,96 @@ bool EmitSSBOInstruction::emit_atomic_pre_dec(const nir_intrinsic_instr *instr)
    return true;
 }
 
+bool EmitSSBOInstruction::emit_load_ssbo(const nir_intrinsic_instr* instr)
+{
+   GPRVector dest = make_dest(instr);
+
+   /** src0 not used, should be some offset */
+   auto addr = from_nir_with_fetch_constant(instr->src[1], 0);
+   PValue addr_temp = create_register_from_nir_src(instr->src[1], 1);
+
+   /** Should be lowered in nir */
+   emit_instruction(new AluInstruction(op2_lshr_int, addr_temp, {addr, PValue(new LiteralValue(2))},
+                    {alu_write, alu_last_instr}));
+
+   const EVTXDataFormat formats[4] = {
+      fmt_32,
+      fmt_32_32,
+      fmt_32_32_32,
+      fmt_32_32_32_32
+   };
+
+   const std::array<int,4> dest_swt[4] = {
+      {0,7,7,7},
+      {0,1,7,7},
+      {0,1,2,7},
+      {0,1,2,3}
+   };
+
+   /* TODO fix resource index */
+   auto ir = new FetchInstruction(dest, addr_temp,
+                                  R600_IMAGE_REAL_RESOURCE_OFFSET, from_nir(instr->src[0], 0),
+                                  formats[instr->num_components-1], vtx_nf_int);
+   ir->set_dest_swizzle(dest_swt[instr->num_components - 1]);
+   ir->set_flag(vtx_use_tc);
+
+   emit_instruction(ir);
+   return true;
+}
+
+bool EmitSSBOInstruction::emit_store_ssbo(const nir_intrinsic_instr* instr)
+{
+
+   GPRVector::Swizzle swz = {7,7,7,7};
+   for (int i = 0; i <  instr->src[0].ssa->num_components; ++i)
+      swz[i] = i;
+
+   auto orig_addr = from_nir(instr->src[2], 0);
+
+   int temp1 = allocate_temp_register();
+   GPRVector addr_vec(temp1, {0,1,2,7});
+
+   auto rat_id = from_nir(instr->src[1], 0);
+
+   emit_instruction(new AluInstruction(op2_lshr_int, addr_vec.reg_i(0), orig_addr,
+                                       PValue(new LiteralValue(2)), write));
+   emit_instruction(new AluInstruction(op1_mov, addr_vec.reg_i(1), Value::zero, write));
+   emit_instruction(new AluInstruction(op1_mov, addr_vec.reg_i(2), Value::zero, last_write));
+
+
+//#define WRITE_AS_VECTOR
+#ifdef WRITE_AS_VECTOR
+   std::unique_ptr<GPRVector> value(vec_from_nir_with_fetch_constant(instr->src[0],
+                                    (1 << instr->src[0].ssa->num_components) - 1, swz));
+
+   /* TODO fix resource index */
+   int nelements = instr->src[0].ssa->num_components - 1;
+   if (nelements == 2)
+      nelements = 3;
+   auto ir = new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED,
+                                *value, addr_vec, 0, rat_id, 11,
+                                (1 << instr->src[0].ssa->num_components) - 1,
+                                0, false);
+   emit_instruction(ir);
+#else
+
+   PValue value(from_nir_with_fetch_constant(instr->src[0], 0));
+   GPRVector out_vec({value, value, value, value});
+   emit_instruction(new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED,
+                                       out_vec, addr_vec, 0, rat_id, 1,
+                                       1, 0, false));
+   for (int i = 1; i < instr->src[0].ssa->num_components; ++i) {
+      emit_instruction(new AluInstruction(op1_mov, out_vec.reg_i(0), from_nir(instr->src[0], i), write));
+      emit_instruction(new AluInstruction(op2_add_int, addr_vec.reg_i(0),
+                                          {addr_vec.reg_i(0), Value::one_i}, last_write));
+      emit_instruction(new RatInstruction(cf_mem_rat, RatInstruction::STORE_TYPED,
+                                          out_vec, addr_vec, 0, rat_id, 1,
+                                          1, 0, false));
+   }
+#endif
+   return true;
+}
+
 GPRVector EmitSSBOInstruction::make_dest(const nir_intrinsic_instr* ir)
 {
    GPRVector::Values v;
index 300f2ec..f2951c9 100644 (file)
@@ -17,6 +17,8 @@ private:
    bool emit_atomic_inc(const nir_intrinsic_instr* instr);
    bool emit_atomic_pre_dec(const nir_intrinsic_instr* instr);
 
+   bool emit_load_ssbo(const nir_intrinsic_instr* instr);
+   bool emit_store_ssbo(const nir_intrinsic_instr* instr);
    ESDOp get_opcode(nir_intrinsic_op opcode);
 
    GPRVector make_dest(const nir_intrinsic_instr* instr);
index 7ea7bc6..0e2d1a8 100644 (file)
@@ -462,7 +462,10 @@ bool ShaderFromNirProcessor::emit_intrinsic_instruction(nir_intrinsic_instr* ins
    case nir_intrinsic_atomic_counter_post_dec:
    case nir_intrinsic_atomic_counter_inc:
    case nir_intrinsic_atomic_counter_pre_dec:
+   case nir_intrinsic_store_ssbo:
       m_sel.info.writes_memory = true;
+      /* fallthrough */
+   case nir_intrinsic_load_ssbo:
       return m_ssbo_instr.emit(&instr->instr);
       break;
    case nir_intrinsic_copy_deref: