mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-03 22:58:31 +02:00
r600/sfn: Add support for atomic instructions
v2: fix compilation with gcc-6 Signed-off-by: Gert Wollny <gert.wollny@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3225>
This commit is contained in:
parent
90a7d2e08f
commit
148f0ad4f9
6 changed files with 228 additions and 0 deletions
|
|
@ -101,6 +101,8 @@ CXX_SOURCES = \
|
|||
sfn/sfn_emitaluinstruction.h \
|
||||
sfn/sfn_emitinstruction.cpp \
|
||||
sfn/sfn_emitinstruction.h \
|
||||
sfn/sfn_emitssboinstruction.cpp \
|
||||
sfn/sfn_emitssboinstruction.h \
|
||||
sfn/sfn_emittexinstruction.cpp \
|
||||
sfn/sfn_emittexinstruction.h \
|
||||
sfn/sfn_emitinstruction.h \
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ files_r600 = files(
|
|||
'sfn/sfn_emitaluinstruction.h',
|
||||
'sfn/sfn_emitinstruction.cpp',
|
||||
'sfn/sfn_emitinstruction.h',
|
||||
'sfn/sfn_emitssboinstruction.cpp',
|
||||
'sfn/sfn_emitssboinstruction.h',
|
||||
'sfn/sfn_emittexinstruction.cpp',
|
||||
'sfn/sfn_emittexinstruction.h',
|
||||
'sfn/sfn_emitinstruction.h',
|
||||
|
|
|
|||
177
src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp
Normal file
177
src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.cpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#include "sfn_emitssboinstruction.h"
|
||||
|
||||
#include "sfn_instruction_fetch.h"
|
||||
#include "sfn_instruction_gds.h"
|
||||
#include "sfn_instruction_misc.h"
|
||||
#include "../r600_pipe.h"
|
||||
|
||||
namespace r600 {
|
||||
|
||||
bool EmitSSBOInstruction::do_emit(nir_instr* instr)
|
||||
{
|
||||
const nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||
switch (intr->intrinsic) {
|
||||
case nir_intrinsic_atomic_counter_add:
|
||||
case nir_intrinsic_atomic_counter_and:
|
||||
case nir_intrinsic_atomic_counter_exchange:
|
||||
case nir_intrinsic_atomic_counter_max:
|
||||
case nir_intrinsic_atomic_counter_min:
|
||||
case nir_intrinsic_atomic_counter_or:
|
||||
case nir_intrinsic_atomic_counter_xor:
|
||||
case nir_intrinsic_atomic_counter_comp_swap:
|
||||
return emit_atomic(intr);
|
||||
case nir_intrinsic_atomic_counter_read:
|
||||
case nir_intrinsic_atomic_counter_post_dec:
|
||||
return emit_unary_atomic(intr);
|
||||
case nir_intrinsic_atomic_counter_inc:
|
||||
return emit_atomic_inc(intr);
|
||||
case nir_intrinsic_atomic_counter_pre_dec:
|
||||
return emit_atomic_pre_dec(intr);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitSSBOInstruction::emit_atomic(const nir_intrinsic_instr* instr)
|
||||
{
|
||||
ESDOp op = get_opcode(instr->intrinsic);
|
||||
|
||||
if (DS_OP_INVALID == op)
|
||||
return false;
|
||||
|
||||
GPRVector dest = make_dest(instr);
|
||||
|
||||
int base = nir_intrinsic_base(instr);
|
||||
|
||||
PValue uav_id = from_nir(instr->src[0], 0);
|
||||
|
||||
PValue value = from_nir_with_fetch_constant(instr->src[1], 0);
|
||||
|
||||
GDSInstr *ir = nullptr;
|
||||
if (instr->intrinsic == nir_intrinsic_atomic_counter_comp_swap) {
|
||||
PValue value2 = from_nir_with_fetch_constant(instr->src[1], 1);
|
||||
ir = new GDSInstr(op, dest, value, value2, uav_id, base);
|
||||
} else {
|
||||
ir = new GDSInstr(op, dest, value, uav_id, base);
|
||||
}
|
||||
|
||||
emit_instruction(ir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitSSBOInstruction::emit_unary_atomic(const nir_intrinsic_instr* instr)
|
||||
{
|
||||
ESDOp op = get_opcode(instr->intrinsic);
|
||||
|
||||
if (DS_OP_INVALID == op)
|
||||
return false;
|
||||
|
||||
GPRVector dest = make_dest(instr);
|
||||
|
||||
PValue uav_id = from_nir(instr->src[0], 0);
|
||||
|
||||
auto ir = new GDSInstr(op, dest, uav_id, nir_intrinsic_base(instr));
|
||||
|
||||
emit_instruction(ir);
|
||||
return true;
|
||||
}
|
||||
|
||||
ESDOp EmitSSBOInstruction::get_opcode(const nir_intrinsic_op opcode)
|
||||
{
|
||||
switch (opcode) {
|
||||
case nir_intrinsic_atomic_counter_add:
|
||||
return DS_OP_ADD_RET;
|
||||
case nir_intrinsic_atomic_counter_and:
|
||||
return DS_OP_AND_RET;
|
||||
case nir_intrinsic_atomic_counter_exchange:
|
||||
return DS_OP_XCHG_RET;
|
||||
case nir_intrinsic_atomic_counter_inc:
|
||||
return DS_OP_INC_RET;
|
||||
case nir_intrinsic_atomic_counter_max:
|
||||
return DS_OP_MAX_UINT_RET;
|
||||
case nir_intrinsic_atomic_counter_min:
|
||||
return DS_OP_MIN_UINT_RET;
|
||||
case nir_intrinsic_atomic_counter_or:
|
||||
return DS_OP_OR_RET;
|
||||
case nir_intrinsic_atomic_counter_read:
|
||||
return DS_OP_READ_RET;
|
||||
case nir_intrinsic_atomic_counter_xor:
|
||||
return DS_OP_XOR_RET;
|
||||
case nir_intrinsic_atomic_counter_post_dec:
|
||||
return DS_OP_DEC_RET;
|
||||
case nir_intrinsic_atomic_counter_comp_swap:
|
||||
return DS_OP_CMP_XCHG_RET;
|
||||
case nir_intrinsic_atomic_counter_pre_dec:
|
||||
default:
|
||||
return DS_OP_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool EmitSSBOInstruction::emit_atomic_add(const nir_intrinsic_instr* instr)
|
||||
{
|
||||
GPRVector dest = make_dest(instr);
|
||||
|
||||
PValue value = from_nir_with_fetch_constant(instr->src[1], 0);
|
||||
|
||||
PValue uav_id = from_nir(instr->src[0], 0);
|
||||
|
||||
auto ir = new GDSInstr(DS_OP_ADD_RET, dest, value, uav_id,
|
||||
nir_intrinsic_base(instr));
|
||||
|
||||
emit_instruction(ir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitSSBOInstruction::emit_atomic_inc(const nir_intrinsic_instr* instr)
|
||||
{
|
||||
GPRVector dest = make_dest(instr);
|
||||
|
||||
PValue uav_id = from_nir(instr->src[0], 0);
|
||||
|
||||
|
||||
if (!m_atomic_limit) {
|
||||
int one_tmp = allocate_temp_register();
|
||||
m_atomic_limit = PValue(new GPRValue(one_tmp, 0));
|
||||
emit_instruction(new AluInstruction(op1_mov, m_atomic_limit,
|
||||
PValue(new LiteralValue(0xffffffff)),
|
||||
{alu_write, alu_last_instr}));
|
||||
}
|
||||
|
||||
auto ir = new GDSInstr(DS_OP_INC_RET, dest, m_atomic_limit, uav_id,
|
||||
nir_intrinsic_base(instr));
|
||||
emit_instruction(ir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EmitSSBOInstruction::emit_atomic_pre_dec(const nir_intrinsic_instr *instr)
|
||||
{
|
||||
GPRVector dest = make_dest(instr);
|
||||
|
||||
PValue uav_id = from_nir(instr->src[0], 0);
|
||||
|
||||
int one_tmp = allocate_temp_register();
|
||||
PValue value(new GPRValue(one_tmp, 0));
|
||||
emit_instruction(new AluInstruction(op1_mov, value, Value::one_i,
|
||||
{alu_write, alu_last_instr}));
|
||||
|
||||
auto ir = new GDSInstr(DS_OP_SUB_RET, dest, value, uav_id,
|
||||
nir_intrinsic_base(instr));
|
||||
emit_instruction(ir);
|
||||
|
||||
ir = new GDSInstr(DS_OP_READ_RET, dest, uav_id, nir_intrinsic_base(instr));
|
||||
emit_instruction(ir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GPRVector EmitSSBOInstruction::make_dest(const nir_intrinsic_instr* ir)
|
||||
{
|
||||
GPRVector::Values v;
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i)
|
||||
v[i] = from_nir(ir->dest, i);
|
||||
return GPRVector(v);
|
||||
}
|
||||
|
||||
}
|
||||
29
src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h
Normal file
29
src/gallium/drivers/r600/sfn/sfn_emitssboinstruction.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef SFN_EMITSSBOINSTRUCTION_H
|
||||
#define SFN_EMITSSBOINSTRUCTION_H
|
||||
|
||||
#include "sfn_emitinstruction.h"
|
||||
|
||||
namespace r600 {
|
||||
|
||||
class EmitSSBOInstruction: public EmitInstruction {
|
||||
public:
|
||||
using EmitInstruction::EmitInstruction;
|
||||
private:
|
||||
bool do_emit(nir_instr *instr);
|
||||
|
||||
bool emit_atomic(const nir_intrinsic_instr* instr);
|
||||
bool emit_unary_atomic(const nir_intrinsic_instr* instr);
|
||||
bool emit_atomic_add(const nir_intrinsic_instr* instr);
|
||||
bool emit_atomic_inc(const nir_intrinsic_instr* instr);
|
||||
bool emit_atomic_pre_dec(const nir_intrinsic_instr* instr);
|
||||
|
||||
ESDOp get_opcode(nir_intrinsic_op opcode);
|
||||
|
||||
GPRVector make_dest(const nir_intrinsic_instr* instr);
|
||||
|
||||
PValue m_atomic_limit;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SFN_EMITSSBOINSTRUCTION_H
|
||||
|
|
@ -62,6 +62,7 @@ ShaderFromNirProcessor::ShaderFromNirProcessor(pipe_shader_type ptype,
|
|||
m_sh_info(sh_info),
|
||||
m_tex_instr(*this),
|
||||
m_alu_instr(*this),
|
||||
m_ssbo_instr(*this),
|
||||
m_pending_else(nullptr),
|
||||
m_scratch_size(scratch_size),
|
||||
m_next_hwatomic_loc(0),
|
||||
|
|
@ -449,6 +450,21 @@ bool ShaderFromNirProcessor::emit_intrinsic_instruction(nir_intrinsic_instr* ins
|
|||
return emit_discard_if(instr);
|
||||
case nir_intrinsic_load_ubo_r600:
|
||||
return emit_load_ubo(instr);
|
||||
case nir_intrinsic_atomic_counter_add:
|
||||
case nir_intrinsic_atomic_counter_and:
|
||||
case nir_intrinsic_atomic_counter_exchange:
|
||||
case nir_intrinsic_atomic_counter_max:
|
||||
case nir_intrinsic_atomic_counter_min:
|
||||
case nir_intrinsic_atomic_counter_or:
|
||||
case nir_intrinsic_atomic_counter_xor:
|
||||
case nir_intrinsic_atomic_counter_comp_swap:
|
||||
case nir_intrinsic_atomic_counter_read:
|
||||
case nir_intrinsic_atomic_counter_post_dec:
|
||||
case nir_intrinsic_atomic_counter_inc:
|
||||
case nir_intrinsic_atomic_counter_pre_dec:
|
||||
m_sel.info.writes_memory = true;
|
||||
return m_ssbo_instr.emit(&instr->instr);
|
||||
break;
|
||||
case nir_intrinsic_copy_deref:
|
||||
case nir_intrinsic_load_constant:
|
||||
case nir_intrinsic_load_input:
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "sfn_instruction_cf.h"
|
||||
#include "sfn_emittexinstruction.h"
|
||||
#include "sfn_emitaluinstruction.h"
|
||||
#include "sfn_emitssboinstruction.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
|
@ -174,6 +175,7 @@ private:
|
|||
|
||||
EmitTexInstruction m_tex_instr;
|
||||
EmitAluInstruction m_alu_instr;
|
||||
EmitSSBOInstruction m_ssbo_instr;
|
||||
OutputRegisterMap m_output_register_map;
|
||||
|
||||
IfElseInstruction *m_pending_else;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue