mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-05 15:55:01 -06:00
Recompiler: Implement IMAGE_ATOMIC_CMPSWAP (#4109)
* To implement ImageAtomicCmpSwap ...but it doesn't work, so here it shall stay. * a fix * Clang * Add to MayHaveSideEffects I missed this while digging through IR code.
This commit is contained in:
parent
df6bb8562e
commit
85476e55ea
@ -140,6 +140,15 @@ Id ImageAtomicF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id va
|
|||||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||||
return (ctx.*atomic_func)(ctx.F32[1], pointer, scope, semantics, value);
|
return (ctx.*atomic_func)(ctx.F32[1], pointer, scope, semantics, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id ImageAtomicU32CmpSwap(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value,
|
||||||
|
Id cmp_value,
|
||||||
|
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id, Id, Id)) {
|
||||||
|
const auto& texture = ctx.images[handle & 0xFFFF];
|
||||||
|
const Id pointer{ctx.OpImageTexelPointer(ctx.image_u32, texture.id, coords, ctx.ConstU32(0U))};
|
||||||
|
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||||
|
return (ctx.*atomic_func)(ctx.F32[1], pointer, scope, semantics, semantics, value, cmp_value);
|
||||||
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
Id EmitSharedAtomicIAdd32(EmitContext& ctx, Id offset, Id value) {
|
Id EmitSharedAtomicIAdd32(EmitContext& ctx, Id offset, Id value) {
|
||||||
@ -420,6 +429,12 @@ Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id co
|
|||||||
return ImageAtomicU32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicExchange);
|
return ImageAtomicU32(ctx, inst, handle, coords, value, &Sirit::Module::OpAtomicExchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id EmitImageAtomicCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value,
|
||||||
|
Id cmp_value) {
|
||||||
|
return ImageAtomicU32CmpSwap(ctx, inst, handle, coords, value, cmp_value,
|
||||||
|
&Sirit::Module::OpAtomicCompareExchange);
|
||||||
|
}
|
||||||
|
|
||||||
Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding) {
|
Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding) {
|
||||||
const auto& buffer = ctx.buffers[binding];
|
const auto& buffer = ctx.buffers[binding];
|
||||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
||||||
|
|||||||
@ -456,6 +456,8 @@ Id EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords,
|
|||||||
Id EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
Id EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||||
Id EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
Id EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||||
Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
|
||||||
|
Id EmitImageAtomicCmpSwap32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value,
|
||||||
|
Id cmp_value);
|
||||||
Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id cube_coords);
|
Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id cube_coords);
|
||||||
Id EmitLaneId(EmitContext& ctx);
|
Id EmitLaneId(EmitContext& ctx);
|
||||||
Id EmitWarpId(EmitContext& ctx);
|
Id EmitWarpId(EmitContext& ctx);
|
||||||
|
|||||||
@ -3430,8 +3430,8 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
|
|||||||
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Uint32},
|
ScalarType::Uint32},
|
||||||
// 16 = IMAGE_ATOMIC_CMPSWAP
|
// 16 = IMAGE_ATOMIC_CMPSWAP
|
||||||
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
|
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Undefined},
|
ScalarType::Uint32},
|
||||||
// 17 = IMAGE_ATOMIC_ADD
|
// 17 = IMAGE_ATOMIC_ADD
|
||||||
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
{InstClass::VectorMemImgNoSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
|
||||||
ScalarType::Uint32},
|
ScalarType::Uint32},
|
||||||
|
|||||||
@ -137,6 +137,8 @@ void Translator::EmitVectorMemory(const GcnInst& inst) {
|
|||||||
// Image atomic operations
|
// Image atomic operations
|
||||||
case Opcode::IMAGE_ATOMIC_SWAP:
|
case Opcode::IMAGE_ATOMIC_SWAP:
|
||||||
return IMAGE_ATOMIC(AtomicOp::Swap, inst);
|
return IMAGE_ATOMIC(AtomicOp::Swap, inst);
|
||||||
|
case Opcode::IMAGE_ATOMIC_CMPSWAP:
|
||||||
|
return IMAGE_ATOMIC(AtomicOp::CmpSwap, inst);
|
||||||
case Opcode::IMAGE_ATOMIC_ADD:
|
case Opcode::IMAGE_ATOMIC_ADD:
|
||||||
return IMAGE_ATOMIC(AtomicOp::Add, inst);
|
return IMAGE_ATOMIC(AtomicOp::Add, inst);
|
||||||
case Opcode::IMAGE_ATOMIC_SMIN:
|
case Opcode::IMAGE_ATOMIC_SMIN:
|
||||||
@ -520,6 +522,10 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
|
|||||||
switch (op) {
|
switch (op) {
|
||||||
case AtomicOp::Swap:
|
case AtomicOp::Swap:
|
||||||
return ir.ImageAtomicExchange(handle, body, value, {});
|
return ir.ImageAtomicExchange(handle, body, value, {});
|
||||||
|
case AtomicOp::CmpSwap: {
|
||||||
|
const IR::Value cmp_val = ir.GetVectorReg(val_reg + 1);
|
||||||
|
return ir.ImageAtomicCmpSwap(handle, body, value, cmp_val, info);
|
||||||
|
}
|
||||||
case AtomicOp::Add:
|
case AtomicOp::Add:
|
||||||
return ir.ImageAtomicIAdd(handle, body, value, info);
|
return ir.ImageAtomicIAdd(handle, body, value, info);
|
||||||
case AtomicOp::Smin:
|
case AtomicOp::Smin:
|
||||||
|
|||||||
@ -2055,6 +2055,11 @@ Value IREmitter::ImageAtomicExchange(const Value& handle, const Value& coords, c
|
|||||||
return Inst(Opcode::ImageAtomicExchange32, Flags{info}, handle, coords, value);
|
return Inst(Opcode::ImageAtomicExchange32, Flags{info}, handle, coords, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value IREmitter::ImageAtomicCmpSwap(const Value& handle, const Value& coords, const Value& value,
|
||||||
|
const Value& cmp_value, TextureInstInfo info) {
|
||||||
|
return Inst(Opcode::ImageAtomicCmpSwap32, Flags{info}, handle, coords, value, cmp_value);
|
||||||
|
}
|
||||||
|
|
||||||
Value IREmitter::ImageSampleRaw(const Value& image_handle, const Value& sampler_handle,
|
Value IREmitter::ImageSampleRaw(const Value& image_handle, const Value& sampler_handle,
|
||||||
const Value& address1, const Value& address2, const Value& address3,
|
const Value& address1, const Value& address2, const Value& address3,
|
||||||
const Value& address4, TextureInstInfo info) {
|
const Value& address4, TextureInstInfo info) {
|
||||||
|
|||||||
@ -360,6 +360,9 @@ public:
|
|||||||
TextureInstInfo info);
|
TextureInstInfo info);
|
||||||
[[nodiscard]] Value ImageAtomicExchange(const Value& handle, const Value& coords,
|
[[nodiscard]] Value ImageAtomicExchange(const Value& handle, const Value& coords,
|
||||||
const Value& value, TextureInstInfo info);
|
const Value& value, TextureInstInfo info);
|
||||||
|
[[nodiscard]] Value ImageAtomicCmpSwap(const Value& handle, const Value& coords,
|
||||||
|
const Value& value, const Value& cmp_value,
|
||||||
|
TextureInstInfo info);
|
||||||
|
|
||||||
[[nodiscard]] Value ImageSampleRaw(const Value& image_handle, const Value& sampler_handle,
|
[[nodiscard]] Value ImageSampleRaw(const Value& image_handle, const Value& sampler_handle,
|
||||||
const Value& address1, const Value& address2,
|
const Value& address1, const Value& address2,
|
||||||
|
|||||||
@ -123,6 +123,7 @@ bool Inst::MayHaveSideEffects() const noexcept {
|
|||||||
case Opcode::ImageAtomicOr32:
|
case Opcode::ImageAtomicOr32:
|
||||||
case Opcode::ImageAtomicXor32:
|
case Opcode::ImageAtomicXor32:
|
||||||
case Opcode::ImageAtomicExchange32:
|
case Opcode::ImageAtomicExchange32:
|
||||||
|
case Opcode::ImageAtomicCmpSwap32:
|
||||||
case Opcode::DebugPrint:
|
case Opcode::DebugPrint:
|
||||||
case Opcode::EmitVertex:
|
case Opcode::EmitVertex:
|
||||||
case Opcode::EmitPrimitive:
|
case Opcode::EmitPrimitive:
|
||||||
|
|||||||
@ -436,6 +436,7 @@ OPCODE(ImageAtomicAnd32, U32, Opaq
|
|||||||
OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, )
|
OPCODE(ImageAtomicOr32, U32, Opaque, Opaque, U32, )
|
||||||
OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, )
|
OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, )
|
||||||
OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, )
|
OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, )
|
||||||
|
OPCODE(ImageAtomicCmpSwap32, U32, Opaque, Opaque, U32, U32, )
|
||||||
|
|
||||||
// Cube operations - optional, usable if profile.supports_native_cube_calc
|
// Cube operations - optional, usable if profile.supports_native_cube_calc
|
||||||
OPCODE(CubeFaceIndex, F32, F32x3, )
|
OPCODE(CubeFaceIndex, F32, F32x3, )
|
||||||
|
|||||||
@ -214,6 +214,7 @@ bool IsImageAtomicInstruction(const IR::Inst& inst) {
|
|||||||
case IR::Opcode::ImageAtomicOr32:
|
case IR::Opcode::ImageAtomicOr32:
|
||||||
case IR::Opcode::ImageAtomicXor32:
|
case IR::Opcode::ImageAtomicXor32:
|
||||||
case IR::Opcode::ImageAtomicExchange32:
|
case IR::Opcode::ImageAtomicExchange32:
|
||||||
|
case IR::Opcode::ImageAtomicCmpSwap32:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user