diff --git a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp index 787d7622..cd51ab32 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ScalarAluOps.cpp @@ -105,6 +105,7 @@ constexpr OpcodeMap SOPP_OPCODE_LIST[] = { {0x10u, Opcode::S_SENDMSG}, {0x12u, Opcode::S_TRAP}, {0x16u, Opcode::S_TTRACEDATA}, + {0x17u, Opcode::S_CBRANCH_CDBGSYS}, {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 c6f08e54..1056cf25 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -187,6 +187,8 @@ std::string FormatExp(const Instruction& inst) { bool IsConditionalBranch(Opcode opcode) { switch (opcode) { + // DevKit NGG should be disabled. + case Opcode::S_CBRANCH_CDBGSYS: return false; case Opcode::S_CBRANCH_SCC0: case Opcode::S_CBRANCH_SCC1: case Opcode::S_CBRANCH_VCCZ: @@ -554,6 +556,7 @@ std::string InstructionToString(const Instruction& inst) { case Opcode::S_CBRANCH_VCCNZ: case Opcode::S_CBRANCH_EXECZ: case Opcode::S_CBRANCH_EXECNZ: + case Opcode::S_CBRANCH_CDBGSYS: 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 6bce89a6..20e7d066 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -581,6 +581,7 @@ enum class Opcode { S_CBRANCH_VCCNZ, S_CBRANCH_EXECZ, S_CBRANCH_EXECNZ, + S_CBRANCH_CDBGSYS, 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 c62e0dae..fa554dd7 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Scalar.cpp @@ -227,6 +227,7 @@ bool Translator::EmitScalar(const Decoder::Instruction& inst) { case O::S_CBRANCH_VCCNZ: case O::S_CBRANCH_EXECZ: case O::S_CBRANCH_EXECNZ: + case O::S_CBRANCH_CDBGSYS: case O::S_ENDPGM: return true; default: return false; } diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index f374e8e0..1ac6d123 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -1795,6 +1795,39 @@ void TestSopkCompareImmediateExtension() { } } +void TestDisabledSystemDebugBranch() { + 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(Common::ContainsStr(result.decoded_dump, "S_CBRANCH_CDBGSYS 0x00000440") && + Common::ContainsStr(result.ir_dump, "StoreBufferU32"), + "disabled system debug branch lost its identity or fallthrough write"); + CheckSpirvBinaryValidates(result.spirv); +} + void TestNewShaderRecompilerRdna2ScalarOpcodes() { const uint32_t shader[] = { EncodeSMovB32(2, 135), // s2 = 7 @@ -13469,6 +13502,7 @@ int main() { TestNewShaderRecompilerBufferLoadsGuardedByExec(); TestNewShaderRecompilerBufferAtomicsGuardedByBounds(); TestCapturedBufferAtomicsX2(); + TestDisabledSystemDebugBranch(); TestNewShaderRecompilerPixelImageSampleLodSelection(); TestNewShaderRecompilerBranchConditionForms(); TestNewShaderRecompilerSetpcBranch();