From 110ee7ff93a42624b1e89065ec75b7649047715e Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Sat, 28 Dec 2019 16:48:45 +0100 Subject: [PATCH] r600/sfn: Add support for SSBO load and store Signed-off-by: Gert Wollny Part-of: --- .../drivers/r600/sfn/sfn_emitssboinstruction.cpp | 94 ++++++++++++++++++++++ .../drivers/r600/sfn/sfn_emitssboinstruction.h | 2 + src/gallium/drivers/r600/sfn/sfn_shader_base.cpp | 3 + 3 files changed, 99 insertions(+) diff --git a/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp b/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp index 0b5bc5f..302e8ef 100644 --- a/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp @@ -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 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 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; diff --git a/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h b/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h index 300f2ec..f2951c9 100644 --- a/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h +++ b/src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h @@ -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); diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp b/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp index 7ea7bc6..0e2d1a8 100644 --- a/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_shader_base.cpp @@ -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: -- 2.7.4