From 91a5ff6cb79035792b6ec397a74d35c562705c3a Mon Sep 17 00:00:00 2001 From: Claxten Date: Tue, 27 Oct 2026 03:04:24 +0100 Subject: [PATCH] shader: decode s_dcache_inv as a no-op --- .../recompiler/frontend/decode/MemoryOps.cpp | 5 ++++- .../recompiler/frontend/decode/ShaderDecoder.cpp | 1 + .../recompiler/frontend/decode/ShaderDecoder.h | 1 + .../recompiler/frontend/translate/Memory.cpp | 2 ++ tests/shaderCfgTests.cpp | 15 +++++++++------ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/decode/MemoryOps.cpp b/src/graphics/shader/recompiler/frontend/decode/MemoryOps.cpp index c3003ab15..296ddc8ed 100644 --- a/src/graphics/shader/recompiler/frontend/decode/MemoryOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/MemoryOps.cpp @@ -22,7 +22,7 @@ constexpr MemoryOpcodeInfo SMEM_OPCODE_LIST[] = { {0x04u, Opcode::S_LOAD_DWORDX16, 16, 32}, {0x08u, Opcode::S_BUFFER_LOAD_DWORD, 1, 32}, {0x09u, Opcode::S_BUFFER_LOAD_DWORDX2, 2, 32}, {0x0au, Opcode::S_BUFFER_LOAD_DWORDX4, 4, 32}, {0x0bu, Opcode::S_BUFFER_LOAD_DWORDX8, 8, 32}, {0x0cu, Opcode::S_BUFFER_LOAD_DWORDX16, 16, 32}, - {0x25u, Opcode::S_MEMREALTIME, 2, 32}, + {0x20u, Opcode::S_DCACHE_INV, 0, 0}, {0x25u, Opcode::S_MEMREALTIME, 2, 32}, }; constexpr MemoryOpcodeInfo MUBUF_OPCODE_LIST[] = { @@ -286,6 +286,9 @@ void DecodeSmem(uint32_t pc, std::span code, uint32_t word_index if (inst.opcode == Opcode::UNSUPPORTED) { SetUnsupported(inst, Family::SMEM, opcode, "SMEM opcode is not implemented"); } + if (inst.opcode == Opcode::S_DCACHE_INV) { + return; + } DecodeScalarDestination(sdst, pc, inst.dst); if (inst.opcode == Opcode::S_MEMREALTIME) { diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index d77c02b07..078e41f5b 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -557,6 +557,7 @@ std::string InstructionToString(const Instruction& inst) { OperandToString(inst.src0).c_str())); case Opcode::S_BARRIER: return WithUnsupportedReason(inst, fmt::format("0x{:08x}: s_barrier", inst.pc)); + case Opcode::S_DCACHE_INV: case Opcode::BUFFER_GL0_INV: case Opcode::BUFFER_GL1_INV: return fmt::format("0x{:08x}: {}", inst.pc, magic_enum::enum_name(inst.opcode)); diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index 6b9032877..8cea8b447 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -544,6 +544,7 @@ enum class Opcode { S_BUFFER_LOAD_DWORDX8, S_BUFFER_LOAD_DWORDX16, S_MEMREALTIME, + S_DCACHE_INV, BUFFER_LOAD_FORMAT_X, BUFFER_LOAD_FORMAT_XY, BUFFER_LOAD_FORMAT_XYZ, diff --git a/src/graphics/shader/recompiler/frontend/translate/Memory.cpp b/src/graphics/shader/recompiler/frontend/translate/Memory.cpp index b4058ce4a..16cd25489 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Memory.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Memory.cpp @@ -941,6 +941,8 @@ void Translator::DS_PERMUTE(const Decoder::Instruction& inst, bool backward) { void Translator::EmitMemory(const Decoder::Instruction& inst) { switch (inst.opcode) { + // Translated scalar loads have no cache of their own to invalidate. + case Decoder::Opcode::S_DCACHE_INV: return; case Decoder::Opcode::BUFFER_GL0_INV: case Decoder::Opcode::BUFFER_GL1_INV: ir.Emit(IR::ValueOpcode::DataCacheInvalidate); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 99a8489f0..f6c5b38ea 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -2001,18 +2001,21 @@ void TestNggVertexEntryState() { void TestNativeDataCacheInvalidation() { using namespace ShaderRecompiler; - // Captured f5edf70dbb1f6057:0x194 and 0x1a4, each followed by S_WAITCNT. + // Captured f5edf70dbb1f6057:0x194 and 0x1a4, each followed by S_WAITCNT. The S_DCACHE_INV + // after them emits no fence. const std::array cache_ops = {0xe1c40000u, 0u, 0xbf8c0000u, - 0xe1c80000u, 0u, 0xbf8c0000u, EncodeSopp(0x01)}; + 0xe1c80000u, 0u, 0xbf8c0000u, + 0xf4800000u, 0xfa000000u, EncodeSopp(0x01)}; Decoder::Program decoded; Decoder::DecodeProgram(cache_ops, decoded); - for (const uint32_t index : {0u, 2u}) { + for (const auto [index, opcode] : {std::pair{0u, Decoder::Opcode::BUFFER_GL0_INV}, + std::pair{2u, Decoder::Opcode::BUFFER_GL1_INV}, + std::pair{4u, Decoder::Opcode::S_DCACHE_INV}}) { const auto &inst = decoded.instructions[index]; - Check(inst.opcode == (index == 0 ? Decoder::Opcode::BUFFER_GL0_INV - : Decoder::Opcode::BUFFER_GL1_INV) && + Check(inst.opcode == opcode && inst.word_count == 2 && inst.src_count == 0 && inst.data_dwords == 0 && inst.dst.kind == Decoder::OperandKind::Unknown, - "RDNA2 cache invalidation acquired a buffer operand or lost its encoding"); + "RDNA2 cache invalidation acquired an operand or lost its encoding"); } auto options = MakeCompileOptions(ShaderType::Compute);