Recognize null-destination SWAPPC shader handoffs

Credits:
BlackCAT (@psnwd):
https://github.com/KytyPS5/KytyPS5/pull/613
YuhiAida (@YuhiAida):
https://github.com/KytyPS5/KytyPS5/pull/655
This commit is contained in:
nmzik
2026-09-17 08:45:21 +04:00
parent e0ecffed70
commit 235e24d44f
2 changed files with 19 additions and 12 deletions
@@ -137,6 +137,10 @@ void DecodeSop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
inst.family = Family::SOP1;
inst.opcode_id = opcode;
inst.opcode = Detail::LookupOpcode(SOP1_OPS, opcode);
if (opcode == 0x21u && sdst == 125u) {
// S_SWAPPC_B64 with NULL discards the return PC, so it is a plain jump.
inst.opcode = Opcode::S_SETPC_B64;
}
SetRawWords(inst, code, word_index, 1);
if (inst.opcode == Opcode::UNSUPPORTED) {
+15 -12
View File
@@ -9435,7 +9435,7 @@ void TestNewShaderRecompilerSetpcBranch() {
void TestFusedShaderHandoffPreservesRegisters() {
using namespace ShaderRecompiler;
const uint32_t front[] = {
uint32_t front[] = {
EncodeSMovB32(12, 255), 0x1003u, // three vertices and one primitive
EncodeSop1(0x20, 0, 6), // merged-stage handoff through s[6:7]
0xffffffffu, // front shader metadata must not be decoded
@@ -9454,20 +9454,23 @@ void TestFusedShaderHandoffPreservesRegisters() {
options.stage = ShaderType::Mesh;
options.input_info.vertex = &input;
options.back_code = back;
auto translated = TranslateProgram(front, options);
uint32_t allocations = 0;
for (const auto* block: translated.program.blocks) {
for (const auto& inst: *block) {
if (inst.GetOpcode() != IR::ValueOpcode::MeshAllocate) {
continue;
for (const auto handoff: {EncodeSop1(0x20, 0, 6), 0xbefd2106u}) {
front[2] = handoff; // SETPC or captured SWAPPC with NULL destination
auto translated = TranslateProgram(front, options);
uint32_t allocations = 0;
for (const auto* block: translated.program.blocks) {
for (const auto& inst: *block) {
if (inst.GetOpcode() != IR::ValueOpcode::MeshAllocate) {
continue;
}
const auto value = inst.Arg(0).Resolve();
Check(value.IsImmediate() && value.U32() == 0x1003u,
"fused back shader lost the front shader's scalar register value");
allocations++;
}
const auto value = inst.Arg(0).Resolve();
Check(value.IsImmediate() && value.U32() == 0x1003u,
"fused back shader lost the front shader's scalar register value");
allocations++;
}
Check(allocations == 1u, "fused shader omitted the back shader allocation");
}
Check(allocations == 1u, "fused shader omitted the back shader allocation");
}
void TestMeshExportStorage() {