From 64dcbe0ea12225ff07e11ebfbc5e913ab30a17b9 Mon Sep 17 00:00:00 2001 From: nmzik Date: Thu, 1 Oct 2026 07:06:51 +0400 Subject: [PATCH] shader: decode the combined conditional-debug branch Co-authored-by: Mac Co-authored-by: Senaxx Co-authored-by: BlackCAT <52720489+psnwd@users.noreply.github.com> --- .../frontend/decode/ScalarAluOps.cpp | 1 + .../frontend/decode/ShaderDecoder.cpp | 6 +- .../frontend/decode/ShaderDecoder.h | 1 + .../recompiler/frontend/translate/Scalar.cpp | 1 + tests/shaderCfgTests.cpp | 66 ++++++++++--------- 5 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp index b7a4994ba..ae474665d 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp @@ -108,6 +108,7 @@ constexpr OpcodeMap SOPP_OPCODE_LIST[] = { {0x12u, Opcode::S_TRAP}, {0x16u, Opcode::S_TTRACEDATA}, {0x17u, Opcode::S_CBRANCH_CDBGSYS}, + {0x19u, Opcode::S_CBRANCH_CDBGSYS_OR_USER}, {0x20u, Opcode::S_INST_PREFETCH}, {0x23u, Opcode::S_WAITCNT_DEPCTR}, }; diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index 04ce1ff35..dae75e56e 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -184,8 +184,9 @@ std::string FormatExp(const Instruction& inst) { bool IsConditionalBranch(Opcode opcode) { switch (opcode) { - // DevKit NGG should be disabled. - case Opcode::S_CBRANCH_CDBGSYS: return false; + // Conditional shader debugging is disabled. + case Opcode::S_CBRANCH_CDBGSYS: + case Opcode::S_CBRANCH_CDBGSYS_OR_USER: return false; case Opcode::S_CBRANCH_SCC0: case Opcode::S_CBRANCH_SCC1: case Opcode::S_CBRANCH_VCCZ: @@ -560,6 +561,7 @@ std::string InstructionToString(const Instruction& inst) { case Opcode::S_CBRANCH_EXECZ: case Opcode::S_CBRANCH_EXECNZ: case Opcode::S_CBRANCH_CDBGSYS: + case Opcode::S_CBRANCH_CDBGSYS_OR_USER: return WithUnsupportedReason(inst, fmt::format("0x{:08x}: {} 0x{:08x}", inst.pc, magic_enum::enum_name(inst.opcode), inst.branch_target)); diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index bed287fd2..949cde89f 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -608,6 +608,7 @@ enum class Opcode { S_CBRANCH_EXECZ, S_CBRANCH_EXECNZ, S_CBRANCH_CDBGSYS, + S_CBRANCH_CDBGSYS_OR_USER, S_SENDMSG, S_SETREG_B32, S_SLEEP, diff --git a/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp b/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp index d18bc4193..5fdf858e8 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp @@ -231,6 +231,7 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) { case O::S_CBRANCH_EXECZ: case O::S_CBRANCH_EXECNZ: case O::S_CBRANCH_CDBGSYS: + case O::S_CBRANCH_CDBGSYS_OR_USER: case O::S_ENDPGM: return; default: return FailMissingTranslation(inst); } diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index c3e76cccf..e8b92335e 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -1884,37 +1884,41 @@ void TestSopkCompareImmediateExtension() { } } -void TestDisabledSystemDebugBranch() { +void TestDisabledDebugBranches() { using namespace ShaderRecompiler; - // Relocate PPSA08709 MS pc 0x530 to zero, retaining its displacement to the - // system validation helper immediately after the main shader's S_ENDPGM. - std::array shader; - shader.fill(EncodeSopp(0x00)); - shader[0] = 0xbf97010fu; - shader[1] = EncodeVop1(0x01, 1, 129); - shader[2] = EncodeMubuf0(0x1c, 0, false); - shader[3] = EncodeMubuf1(1, 0, 0); - shader[271] = EncodeSopp(0x01); - shader[272] = 0xffffffffu; // System-only helper must not be decoded. - shader[273] = 0xffffffffu; - Decoder::Program decoded; - Decoder::DecodeProgram(shader, decoded); - Check(decoded.instructions.front().opcode == Decoder::Opcode::S_CBRANCH_CDBGSYS && - decoded.instructions.front().branch_target == 0x440u && - decoded.instructions.back().pc == 0x43cu && - decoded.instructions.back().opcode == Decoder::Opcode::S_ENDPGM, - "disabled system debug branch reached its post-ENDPGM validation helper"); - auto graph = CFG::BuildGraph(decoded); - Check(graph.blocks.size() == 1u && graph.FindBlockByPc(0x440u) == nullptr && - graph.blocks.front().terminator.kind == CFG::TerminatorKind::Return, - "disabled system debug branch changed normal shader control flow"); - auto options = MakeCompileOptions(ShaderType::Compute); - options.dump_ir = true; - auto result = RecompileForTest(shader, options); - Check((result.decoded_dump.find("S_CBRANCH_CDBGSYS 0x00000440") != std::string::npos) && - (result.ir_dump.find("StoreBufferU32") != std::string::npos), - "disabled system debug branch lost its identity or fallthrough write"); - CheckSpirvBinaryValidates(result.spirv); + // Both debug branches fall through when conditional shader debugging is disabled. + // Retain the post-ENDPGM helper displacement from PPSA08709 and exercise the + // OR_USER variant encountered in PPSA03671 with the same body. + for (const auto opcode : {Decoder::Opcode::S_CBRANCH_CDBGSYS, + Decoder::Opcode::S_CBRANCH_CDBGSYS_OR_USER}) { + std::array shader; + shader.fill(EncodeSopp(0x00)); + shader[0] = EncodeSopp(opcode == Decoder::Opcode::S_CBRANCH_CDBGSYS ? 0x17 : 0x19, 0x10f); + shader[1] = EncodeVop1(0x01, 1, 129); + shader[2] = EncodeMubuf0(0x1c, 0, false); + shader[3] = EncodeMubuf1(1, 0, 0); + shader[271] = EncodeSopp(0x01); + shader[272] = 0xffffffffu; // Debug-only helper must not be decoded. + shader[273] = 0xffffffffu; + Decoder::Program decoded; + Decoder::DecodeProgram(shader, decoded); + Check(decoded.instructions.front().opcode == opcode && + decoded.instructions.front().branch_target == 0x440u && + decoded.instructions.back().pc == 0x43cu && + decoded.instructions.back().opcode == Decoder::Opcode::S_ENDPGM, + "disabled debug branch reached its post-ENDPGM validation helper"); + auto graph = CFG::BuildGraph(decoded); + Check(graph.blocks.size() == 1u && graph.FindBlockByPc(0x440u) == nullptr && + graph.blocks.front().terminator.kind == CFG::TerminatorKind::Return, + "disabled debug branch changed normal shader control flow"); + auto options = MakeCompileOptions(ShaderType::Compute); + options.dump_ir = true; + auto result = RecompileForTest(shader, options); + Check((result.decoded_dump.find(" 0x00000440") != std::string::npos) && + (result.ir_dump.find("StoreBufferU32") != std::string::npos), + "disabled debug branch lost its identity or fallthrough write"); + CheckSpirvBinaryValidates(result.spirv); + } } void TestNewShaderRecompilerRdna2ScalarOpcodes() { @@ -14142,7 +14146,7 @@ int main() { TestNewShaderRecompilerBufferLoadsGuardedByExec(); TestNewShaderRecompilerBufferAtomicsGuardedByBounds(); TestCapturedBufferAtomicsX2(); - TestDisabledSystemDebugBranch(); + TestDisabledDebugBranches(); TestNewShaderRecompilerPixelImageSampleLodSelection(); TestNewShaderRecompilerBranchConditionForms(); TestNewShaderRecompilerSetpcBranch();