shader: implement BUFFER_ATOMIC_CMPSWAP (#357)

shader: implement RDNA2 buffer atomic compare swap

Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
GodsWill Dev
2026-09-03 17:34:34 -04:00
committed by GitHub
parent 5b8e3b51b0
commit 2fe5c150bc
9 changed files with 142 additions and 49 deletions
@@ -47,6 +47,7 @@ constexpr MemoryOpcodeInfo MUBUF_OPCODE_LIST[] = {
{0x1eu, Opcode::BUFFER_STORE_DWORDX4, 4, 32},
{0x1fu, Opcode::BUFFER_STORE_DWORDX3, 3, 32},
{0x30u, Opcode::BUFFER_ATOMIC_SWAP, 1, 32},
{0x31u, Opcode::BUFFER_ATOMIC_CMPSWAP, 1, 32},
{0x32u, Opcode::BUFFER_ATOMIC_ADD, 1, 32},
{0x33u, Opcode::BUFFER_ATOMIC_SUB, 1, 32},
{0x35u, Opcode::BUFFER_ATOMIC_SMIN, 1, 32},
@@ -592,6 +592,7 @@ std::string InstructionToString(const Instruction& inst) {
case Opcode::TBUFFER_STORE_FORMAT_XYZ:
case Opcode::TBUFFER_STORE_FORMAT_XYZW:
case Opcode::BUFFER_ATOMIC_SWAP:
case Opcode::BUFFER_ATOMIC_CMPSWAP:
case Opcode::BUFFER_ATOMIC_SWAP_X2:
case Opcode::BUFFER_ATOMIC_ADD:
case Opcode::BUFFER_ATOMIC_SUB:
@@ -455,6 +455,7 @@ enum class Opcode {
TBUFFER_STORE_FORMAT_XYZ,
TBUFFER_STORE_FORMAT_XYZW,
BUFFER_ATOMIC_SWAP,
BUFFER_ATOMIC_CMPSWAP,
BUFFER_ATOMIC_SWAP_X2,
BUFFER_ATOMIC_ADD,
BUFFER_ATOMIC_SUB,
@@ -523,12 +523,23 @@ bool Translator::BUFFER_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode
const auto resource = GetBufferResource(memory);
const auto address = ReadBufferAddress(inst, 1);
const auto data_src = MemorySourceAt(inst, 0);
const IR::Value data =
memory.data_dwords == 2u ? IR::Value(ReadU64(data_src)) : IR::Value(ReadU32(data_src));
const auto result = ir.Emit(opcode,
{resource, address.index, address.offset, address.soffset, data,
ir.GetExec()},
AddMemoryInfo(memory, inst.pc));
const auto flags = AddMemoryInfo(memory, inst.pc);
IR::Value result;
if (opcode == IR::ValueOpcode::BufferAtomicCmpSwap32) {
const auto desired = ReadU32(data_src);
const auto comparator = ReadU32(OffsetOperand(data_src, 1u));
result = ir.Emit(opcode,
{resource, address.index, address.offset, address.soffset, desired,
comparator, ir.GetExec()},
flags);
} else {
const IR::Value value =
memory.data_dwords == 2u ? IR::Value(ReadU64(data_src)) : IR::Value(ReadU32(data_src));
result = ir.Emit(opcode,
{resource, address.index, address.offset, address.soffset, value,
ir.GetExec()},
flags);
}
if (inst.glc) {
WriteOperand(inst.dst, result);
}
@@ -922,6 +933,8 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst) {
case Decoder::Opcode::BUFFER_ATOMIC_SWAP:
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicSwap32);
case Decoder::Opcode::BUFFER_ATOMIC_CMPSWAP:
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicCmpSwap32);
case Decoder::Opcode::BUFFER_ATOMIC_SWAP_X2:
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicSwap64);
case Decoder::Opcode::BUFFER_ATOMIC_ADD: