From 1375d650a735c9a6e39a5d81369d7bd33da0c835 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 16 Aug 2026 10:50:30 +0200 Subject: [PATCH] graphics: support RDNA2 dependency waits --- .../frontend/decode/ScalarAluOps.cpp | 31 +++++----- .../frontend/decode/ShaderDecoder.cpp | 2 + .../frontend/decode/ShaderDecoder.h | 1 + .../shader/recompiler/ir/ShaderIR.cpp | 2 + tests/ShaderRecompilerComputeTests.cpp | 58 +++++++++++++++++++ 5 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp index 534f92ec8..c0cb3ca3c 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp @@ -60,12 +60,15 @@ constexpr OpcodeMap SOPK_OPCODE_LIST[] = { }; constexpr OpcodeMap SOPP_OPCODE_LIST[] = { - {0x00u, Opcode::SNop}, {0x01u, Opcode::SEndpgm}, {0x02u, Opcode::SBranch}, - {0x04u, Opcode::SCbranchScc0}, {0x05u, Opcode::SCbranchScc1}, {0x06u, Opcode::SCbranchVccz}, - {0x07u, Opcode::SCbranchVccnz}, {0x08u, Opcode::SCbranchExecz}, {0x09u, Opcode::SCbranchExecnz}, - {0x0au, Opcode::SBarrier}, {0x0cu, Opcode::SWaitcnt}, {0x0eu, Opcode::SSleep}, - {0x10u, Opcode::SSendmsg}, {0x12u, Opcode::STrap}, {0x16u, Opcode::STtraceData}, - {0x20u, Opcode::SInstPrefetch}, + {0x00u, Opcode::SNop}, {0x01u, Opcode::SEndpgm}, + {0x02u, Opcode::SBranch}, {0x04u, Opcode::SCbranchScc0}, + {0x05u, Opcode::SCbranchScc1}, {0x06u, Opcode::SCbranchVccz}, + {0x07u, Opcode::SCbranchVccnz}, {0x08u, Opcode::SCbranchExecz}, + {0x09u, Opcode::SCbranchExecnz}, {0x0au, Opcode::SBarrier}, + {0x0cu, Opcode::SWaitcnt}, {0x0eu, Opcode::SSleep}, + {0x10u, Opcode::SSendmsg}, {0x12u, Opcode::STrap}, + {0x16u, Opcode::STtraceData}, {0x20u, Opcode::SInstPrefetch}, + {0x23u, Opcode::SWaitcntDepctr}, }; constexpr auto SOP1_OPS = Detail::MakeOpcodeTable<0x100>(SOP1_OPCODE_LIST); @@ -252,14 +255,14 @@ void DecodeSopp(uint32_t pc, std::span code, uint32_t word_index inst.src0.signed_val = inst.opcode == Opcode::STrap ? static_cast(inst.src0.value) : static_cast(static_cast(simm)); - inst.src_count = (inst.opcode == Opcode::SNop || inst.opcode == Opcode::SWaitcnt || - inst.opcode == Opcode::SSleep || inst.opcode == Opcode::SSendmsg || - inst.opcode == Opcode::STrap || inst.opcode == Opcode::STtraceData || - inst.opcode == Opcode::SInstPrefetch) - ? 1 - : 0; - inst.branch_offset = static_cast(static_cast(simm)) * 4; - inst.branch_target = pc + 4u + static_cast(inst.branch_offset); + inst.src_count = (inst.opcode == Opcode::SNop || inst.opcode == Opcode::SWaitcnt || + inst.opcode == Opcode::SWaitcntDepctr || inst.opcode == Opcode::SSleep || + inst.opcode == Opcode::SSendmsg || inst.opcode == Opcode::STrap || + inst.opcode == Opcode::STtraceData || inst.opcode == Opcode::SInstPrefetch) + ? 1 + : 0; + inst.branch_offset = static_cast(static_cast(simm)) * 4; + inst.branch_target = pc + 4u + static_cast(inst.branch_offset); SetRawWords(inst, code, word_index, 1); if (inst.opcode == Opcode::Unsupported) { diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index 9ff41bb3d..e0cb60a19 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -944,6 +944,7 @@ std::string OpcodeToString(Opcode opcode) { case Opcode::VInterpMovF32: return "v_interp_mov_f32"; case Opcode::SNop: return "s_nop"; case Opcode::SWaitcnt: return "s_waitcnt"; + case Opcode::SWaitcntDepctr: return "s_waitcnt_depctr"; case Opcode::SBarrier: return "s_barrier"; case Opcode::SBranch: return "s_branch"; case Opcode::SCbranchScc0: return "s_cbranch_scc0"; @@ -1058,6 +1059,7 @@ std::string InstructionToString(const Instruction& inst) { OperandToString(inst.src1).c_str())); case Opcode::SNop: case Opcode::SWaitcnt: + case Opcode::SWaitcntDepctr: case Opcode::SSleep: case Opcode::STrap: case Opcode::SSendmsg: diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index 182c95dfb..3ff8dbe90 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -531,6 +531,7 @@ enum class Opcode { SNop, SWaitcnt, + SWaitcntDepctr, SBarrier, SBranch, SCbranchScc0, diff --git a/src/graphics/shader/recompiler/ir/ShaderIR.cpp b/src/graphics/shader/recompiler/ir/ShaderIR.cpp index ef6824e3d..9f87e0f10 100644 --- a/src/graphics/shader/recompiler/ir/ShaderIR.cpp +++ b/src/graphics/shader/recompiler/ir/ShaderIR.cpp @@ -992,6 +992,7 @@ bool LowerControlInstruction(const Decoder::Instruction& decoded, BasicBlock& bl case Decoder::Opcode::SNop: return LowerControlMarker(decoded, block, Opcode::ControlNop, true, error); case Decoder::Opcode::SWaitcnt: + case Decoder::Opcode::SWaitcntDepctr: return LowerControlMarker(decoded, block, Opcode::Waitcnt, true, error); case Decoder::Opcode::SBarrier: return LowerControlMarker(decoded, block, Opcode::Barrier, false, error); @@ -1075,6 +1076,7 @@ bool IsControlOpcode(Decoder::Opcode opcode) { switch (opcode) { case Decoder::Opcode::SNop: case Decoder::Opcode::SWaitcnt: + case Decoder::Opcode::SWaitcntDepctr: case Decoder::Opcode::SBarrier: case Decoder::Opcode::SSendmsg: case Decoder::Opcode::SSetregB32: diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index f2b4a69d0..1db2d6f58 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -863,6 +863,7 @@ struct TestCase { std::vector expected_gds; std::vector> decoded_counts; std::vector> ir_counts; + std::vector> native_ir_counts; u32 expected_storage_mip_descriptors = 0; }; @@ -1087,6 +1088,32 @@ CompiledShader CompileCase(const TestCase &test) { text + " count=" + std::to_string(actual) + ", expected=" + std::to_string(expected)); } + if (!test.native_ir_counts.empty()) { + ShaderRecompiler::Decoder::Program decoded; + ShaderRecompiler::CFG::Graph cfg; + ShaderRecompiler::IR::Program native; + std::string native_error; + Require(test.name, "native decode", + ShaderRecompiler::Decoder::DecodeProgram(test.code, decoded, + &native_error), + native_error); + Require(test.name, "native CFG", + ShaderRecompiler::CFG::BuildGraph(decoded, cfg, &native_error) && + ShaderRecompiler::CFG::Structurize(cfg, &native_error), + native_error); + Require(test.name, "native lowering", + ShaderRecompiler::IR::LowerProgram(decoded, cfg, options.stage, + options.wave_size, native, + &native_error), + native_error); + const auto native_ir = ShaderRecompiler::IR::ProgramToString(native); + for (const auto &[text, expected] : test.native_ir_counts) { + const auto actual = CountText(native_ir, text); + Require(test.name, "native IR", actual == expected, + text + " count=" + std::to_string(actual) + + ", expected=" + std::to_string(expected)); + } + } if (test.expected_storage_mip_descriptors != 0) { const auto image = std::ranges::find_if( result.program.info.images, [](const auto &resource) { @@ -10877,6 +10904,31 @@ TestCase ScalarTrapDisabledFallsThroughExactRaw() { return test; } +TestCase ScalarWaitcntDepctrCapturedVmVsrc() { + using O = ShaderOpcode; + + std::vector code; + AppendVMovU32(&code, 7, 7); + AppendVMovU32(&code, 31, 0); + AppendBufferStoreDword(&code, 7, 31); + code.push_back(0xbfa3ffe3u); // s_waitcnt_depctr vm_vsrc(0) + AppendVMovU32(&code, 7, 42); + AppendStoreVgpr(&code, 7, 1); + AppendEnd(&code); + + TestCase test; + test.name = "ScalarWaitcntDepctrCapturedVmVsrc"; + test.code = std::move(code); + test.initial = {0, 0}; + test.expected = {7, 42}; + test.opcodes = {O::VMovB32, O::BufferStoreDword, O::SWaitcntDepctr, + O::SEndpgm}; + test.decoded_counts = {{"0x00000010: s_waitcnt_depctr 0x0000ffe3\n", 1}}; + test.native_ir_counts = {{"0x00000010: Waitcnt null, 0x0000ffe3", 1}}; + test.forbidden_spirv = {"OpControlBarrier", "OpMemoryBarrier"}; + return test; +} + TestCase ScalarExtendedArithmetic() { using O = ShaderOpcode; @@ -17569,6 +17621,7 @@ std::vector MakeCases() { AddCase(ScalarShiftCountsMaskLowBits); AddCase(Rdna2ScalarOpcodes); AddCase(ScalarTrapDisabledFallsThroughExactRaw); + AddCase(ScalarWaitcntDepctrCapturedVmVsrc); AddCase(ScalarExtendedArithmetic); AddCase(ScalarArithmeticSccCarryBorrowOverflow); AddCase(ScalarMinMaxSccComparisonEdges); @@ -21046,6 +21099,11 @@ int main(int argc, char **argv) { RunCase(&vulkan, Vop3CvtPkI16I32Captured()); return 0; } + if (argc == 2 && std::strcmp(argv[1], "--waitcnt-depctr-only") == 0) { + VulkanHarness vulkan; + RunCase(&vulkan, ScalarWaitcntDepctrCapturedVmVsrc()); + return 0; + } if (argc == 2 && std::strcmp(argv[1], "--sff1-b64-only") == 0) { VulkanHarness vulkan; RunCase(&vulkan, ScalarBitfieldPack());