Skip to content

Commit a49c65f

Browse files
committed
BUFFER_ATOMIC_CMPSWAP
1 parent 3b3026f commit a49c65f

File tree

6 files changed

+37
-0
lines changed

6 files changed

+37
-0
lines changed

src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,22 @@ Id BufferAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id
6868
});
6969
}
7070

71+
Id BufferAtomicU32CmpSwap(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value,
72+
Id cmp_value,
73+
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id, Id, Id)) {
74+
const auto& buffer = ctx.buffers[handle];
75+
if (Sirit::ValidId(buffer.offset)) {
76+
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
77+
}
78+
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
79+
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U32];
80+
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index);
81+
const auto [scope, semantics]{AtomicArgs(ctx)};
82+
return BufferAtomicU32BoundsCheck(ctx, index, buffer.size_dwords, [&] {
83+
return (ctx.*atomic_func)(ctx.U32[1], ptr, scope, semantics, semantics, value, cmp_value);
84+
});
85+
}
86+
7187
Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value,
7288
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
7389
const auto& texture = ctx.images[handle & 0xFFFF];
@@ -175,6 +191,12 @@ Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre
175191
return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicExchange);
176192
}
177193

194+
Id EmitBufferAtomicCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value,
195+
Id cmp_value) {
196+
return BufferAtomicU32CmpSwap(ctx, inst, handle, address, value, cmp_value,
197+
&Sirit::Module::OpAtomicCompareExchange);
198+
}
199+
178200
Id EmitImageAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value) {
179201
return ImageAtomicU32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicIAdd);
180202
}

src/shader_recompiler/backend/spirv/emit_spirv_instructions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ Id EmitBufferAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addres
9696
Id EmitBufferAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
9797
Id EmitBufferAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
9898
Id EmitBufferAtomicSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value);
99+
Id EmitBufferAtomicCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value,
100+
Id cmp_value);
99101
Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp, Id index);
100102
Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp);
101103
void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, Id value, u32 comp);

src/shader_recompiler/frontend/translate/vector_memory.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,10 @@ void Translator::BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst) {
331331
switch (op) {
332332
case AtomicOp::Swap:
333333
return ir.BufferAtomicSwap(handle, address, vdata_val, buffer_info);
334+
case AtomicOp::CmpSwap: {
335+
IR::Value cmp_val = ir.GetVectorReg(vdata + 1);
336+
return ir.BufferAtomicCmpSwap(handle, address, vdata_val, cmp_val, buffer_info);
337+
}
334338
case AtomicOp::Add:
335339
return ir.BufferAtomicIAdd(handle, address, vdata_val, buffer_info);
336340
case AtomicOp::Smin:

src/shader_recompiler/ir/ir_emitter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,11 @@ Value IREmitter::BufferAtomicSwap(const Value& handle, const Value& address, con
513513
return Inst(Opcode::BufferAtomicSwap32, Flags{info}, handle, address, value);
514514
}
515515

516+
Value IREmitter::BufferAtomicCmpSwap(const Value& handle, const Value& address, const Value& vdata,
517+
const Value& cmp_value, BufferInstInfo info) {
518+
return Inst(Opcode::BufferAtomicCmpSwap32, Flags{info}, handle, address, vdata, cmp_value);
519+
}
520+
516521
U32 IREmitter::DataAppend(const U32& counter) {
517522
return Inst<U32>(Opcode::DataAppend, counter, Imm32(0));
518523
}

src/shader_recompiler/ir/ir_emitter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ class IREmitter {
150150
const Value& value, BufferInstInfo info);
151151
[[nodiscard]] Value BufferAtomicSwap(const Value& handle, const Value& address,
152152
const Value& value, BufferInstInfo info);
153+
[[nodiscard]] Value BufferAtomicCmpSwap(const Value& handle, const Value& address,
154+
const Value& value, const Value& cmp_value,
155+
BufferInstInfo info);
153156

154157
[[nodiscard]] U32 DataAppend(const U32& counter);
155158
[[nodiscard]] U32 DataConsume(const U32& counter);

src/shader_recompiler/ir/opcodes.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ OPCODE(BufferAtomicAnd32, U32, Opaq
126126
OPCODE(BufferAtomicOr32, U32, Opaque, Opaque, U32, )
127127
OPCODE(BufferAtomicXor32, U32, Opaque, Opaque, U32, )
128128
OPCODE(BufferAtomicSwap32, U32, Opaque, Opaque, U32, )
129+
OPCODE(BufferAtomicCmpSwap32, U32, Opaque, Opaque, U32, U32, )
129130

130131
// Vector utility
131132
OPCODE(CompositeConstructU32x2, U32x2, U32, U32, )

0 commit comments

Comments
 (0)