mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
shader: implement 32-bit RDNA2 IMAGE_ATOMIC_CMPSWAP (#952)
* shader: implement 32-bit RDNA2 image atomic compare-and-swap * shader: share atomic emission and correct image barriers --------- Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
@@ -192,6 +192,7 @@ constexpr MimgGatherInfo MIMG_GATHER_OPCODE_LIST[] = {
|
||||
|
||||
constexpr Detail::OpcodeMap MIMG_ATOMIC_OPCODE_LIST[] = {
|
||||
{0x0fu, Opcode::IMAGE_ATOMIC_SWAP},
|
||||
{0x10u, Opcode::IMAGE_ATOMIC_CMPSWAP},
|
||||
{0x11u, Opcode::IMAGE_ATOMIC_ADD},
|
||||
{0x14u, Opcode::IMAGE_ATOMIC_SMIN},
|
||||
{0x15u, Opcode::IMAGE_ATOMIC_UMIN},
|
||||
@@ -359,6 +360,10 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
SetUnsupported(inst, Family::MIMG, opcode,
|
||||
"MIMG image gather requires exactly one dmask bit");
|
||||
}
|
||||
if (inst.opcode == Opcode::IMAGE_ATOMIC_CMPSWAP && inst.dmask != 0x3u) {
|
||||
SetUnsupported(inst, Family::MIMG, opcode,
|
||||
"MIMG image compare-and-swap requires 32-bit DMASK 0x3");
|
||||
}
|
||||
const bool supports_d16 = sample != nullptr || gather != nullptr || opcode == 0x00u ||
|
||||
opcode == 0x01u || opcode == 0x08u || opcode == 0x09u;
|
||||
if (d16 && !supports_d16) {
|
||||
|
||||
@@ -574,6 +574,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::IMAGE_SAMPLE:
|
||||
case Opcode::IMAGE_STORE:
|
||||
case Opcode::IMAGE_STORE_MIP:
|
||||
case Opcode::IMAGE_ATOMIC_CMPSWAP:
|
||||
case Opcode::IMAGE_ATOMIC_SWAP:
|
||||
case Opcode::IMAGE_ATOMIC_ADD:
|
||||
case Opcode::IMAGE_ATOMIC_SMIN:
|
||||
|
||||
@@ -599,6 +599,7 @@ enum class Opcode {
|
||||
IMAGE_STORE,
|
||||
IMAGE_STORE_MIP,
|
||||
IMAGE_ATOMIC_SWAP,
|
||||
IMAGE_ATOMIC_CMPSWAP,
|
||||
IMAGE_ATOMIC_ADD,
|
||||
IMAGE_ATOMIC_SMIN,
|
||||
IMAGE_ATOMIC_UMIN,
|
||||
|
||||
@@ -558,9 +558,18 @@ void Translator::IMAGE_ATOMIC(const Decoder::Instruction& inst, IR::ValueOpcode
|
||||
const auto memory = MemoryInfoFromDecoded(inst);
|
||||
const auto resource = GetImageResource(memory);
|
||||
const auto address = MakeImageAddress(inst, MemorySourceAt(inst, 1));
|
||||
const auto result =
|
||||
ir.Emit(opcode, {resource, address, ReadU32(MemorySourceAt(inst, 0)), ir.GetExec()},
|
||||
AddMemoryInfo(memory, inst.pc));
|
||||
const auto data = MemorySourceAt(inst, 0);
|
||||
const auto flags = AddMemoryInfo(memory, inst.pc);
|
||||
IR::Value result;
|
||||
if (opcode == IR::ValueOpcode::ImageAtomicCompareSwap32) {
|
||||
// VDATA supplies the replacement; VDATA+1 supplies the comparison.
|
||||
result = ir.Emit(opcode,
|
||||
{resource, address, ReadU32(data), ReadU32(OffsetOperand(data, 1u)),
|
||||
ir.GetExec()},
|
||||
flags);
|
||||
} else {
|
||||
result = ir.Emit(opcode, {resource, address, ReadU32(data), ir.GetExec()}, flags);
|
||||
}
|
||||
if (inst.glc) {
|
||||
WriteOperand(inst.dst, result);
|
||||
}
|
||||
@@ -1030,6 +1039,8 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
case Decoder::Opcode::DS_WRXCHG_RTN_B32:
|
||||
return DS_ATOMIC(inst, IR::ValueOpcode::SharedAtomicSwap32, true);
|
||||
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_CMPSWAP:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicCompareSwap32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_SWAP:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicSwap32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_ADD:
|
||||
|
||||
Reference in New Issue
Block a user