From 3b9e176b700ca2af543751c70b9489b71f967e5b Mon Sep 17 00:00:00 2001 From: foufouadi Date: Fri, 28 Aug 2026 16:08:27 +0000 Subject: [PATCH] shader: support VOP1/VOP2 DPP8 fetch-inactive --- .../frontend/decode/VectorAluOps.cpp | 13 +++-- tests/ShaderRecompilerComputeTests.cpp | 52 +++++++++++-------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp index 8cf75eea..abc25519 100644 --- a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp @@ -776,9 +776,10 @@ void DecodeVop1Sdwa(uint32_t pc, std::span code, uint32_t word_i void ApplyDppModifier(Operand& operand, uint32_t modifier, uint32_t encoding) { operand.dpp = true; - if (encoding == 233u) { - operand.dpp8 = true; - operand.dpp_ctrl = modifier >> 8u; + if (encoding == 233u || encoding == 234u) { + operand.dpp8 = true; + operand.dpp_ctrl = modifier >> 8u; + operand.dpp_fetch_inactive = encoding == 234u; return; } operand.negate = ((modifier >> 20u) & 0x1u) != 0u; @@ -1686,7 +1687,8 @@ void DecodeVop2(uint32_t pc, std::span code, uint32_t word_index return; } switch (src0) { - case 233u: DecodeVop2Dpp(pc, code, word_index, opcode, vdst, vsrc1, inst); return; + case 233u: + case 234u: DecodeVop2Dpp(pc, code, word_index, opcode, vdst, vsrc1, inst); return; case 249u: DecodeVop2Sdwa(pc, code, word_index, opcode, vdst, vsrc1, inst); return; case 250u: DecodeVop2Dpp(pc, code, word_index, opcode, vdst, vsrc1, inst); return; default: break; @@ -1721,7 +1723,8 @@ void DecodeVop1(uint32_t pc, std::span code, uint32_t word_index return; } switch (src0) { - case 233u: DecodeVop1Dpp(pc, code, word_index, opcode, vdst, inst); return; + case 233u: + case 234u: DecodeVop1Dpp(pc, code, word_index, opcode, vdst, inst); return; case 249u: DecodeVop1Sdwa(pc, code, word_index, opcode, vdst, inst); return; case 250u: DecodeVop1Dpp(pc, code, word_index, opcode, vdst, inst); return; default: break; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 3aa13065..972bb582 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -24786,11 +24786,12 @@ TestCase VectorPermlane16FetchInactiveFi() { return test; } -TestCase VectorDpp8Captured(bool masked_exec) { +TestCase VectorDpp8Captured(bool masked_exec, u32 wave_size = 64, bool fi = false) { using O = ShaderOpcode; constexpr u32 sentinel = 0xaaaaaaaau; - const u32 masks[] = {masked_exec ? 0x0f0f0f0fu : 0xffffffffu, - masked_exec ? 0xf0f0f0f0u : 0xffffffffu}; + // Both wave halves contain active and inactive lane-3 sources for the ADD. + const u32 masks[] = {masked_exec ? 0x0f0ff0f0u : 0xffffffffu, + masked_exec ? 0xf0f00f0fu : 0xffffffffu}; std::vector code; AppendVMovU32(&code, 5, 100); code.push_back(EncodeVop2(0x25, 5, Vgpr(0), 5)); @@ -24799,20 +24800,21 @@ TestCase VectorDpp8Captured(bool masked_exec) { AppendVMovLiteral(&code, 3, sentinel); AppendVMovLiteral(&code, 8, sentinel); AppendSMovLiteral(&code, 126, masks[0]); - AppendSMovLiteral(&code, 127, masks[1]); + if (wave_size == 64) AppendSMovLiteral(&code, 127, masks[1]); // Captured DPP8 selectors broadcast each group's upper/lower four lanes. - code.push_back(EncodeVop1(0x01, 2, 233)); + const u32 encoding = fi ? 234u : 233u; + code.push_back(EncodeVop1(0x01, 2, encoding)); code.push_back(0xfacfac05u); - code.push_back(EncodeVop1(0x01, 3, 233)); + code.push_back(EncodeVop1(0x01, 3, encoding)); code.push_back(0x68868805u); // CS 6babb2a8915d35c4, pc 0xcc: add lane 3 of each group to its own v7. - code.push_back(0x4a100ee9u); + code.push_back(EncodeVop2(0x25, 8, encoding, 7)); code.push_back(0x6db6db07u); AppendSMovLiteral(&code, 126, 0xffffffffu); - AppendSMovLiteral(&code, 127, 0xffffffffu); + if (wave_size == 64) AppendSMovLiteral(&code, 127, 0xffffffffu); code.push_back(EncodeVop2(0x1a, 6, InlineU32(2), 0)); AppendBufferStoreDword(&code, 2, 6); - AppendVMovU32(&code, 7, 64u * sizeof(u32)); + AppendVMovU32(&code, 7, wave_size * sizeof(u32)); code.push_back(EncodeVop2(0x25, 6, Vgpr(7), 6)); AppendBufferStoreDword(&code, 3, 6); code.push_back(EncodeVop2(0x25, 6, Vgpr(7), 6)); @@ -24820,11 +24822,13 @@ TestCase VectorDpp8Captured(bool masked_exec) { AppendEnd(&code); TestCase test; - test.name = masked_exec ? "VectorDpp8CapturedMaskedExec" - : "VectorDpp8Captured"; + const char *names[2][2] = { + {"VectorDpp8Wave32MaskedExec", "VectorDpp8Wave64MaskedExec"}, + {"VectorDpp8FiWave32MaskedExec", "VectorDpp8FiWave64MaskedExec"}}; + test.name = masked_exec ? names[fi][wave_size == 64] : "VectorDpp8Captured"; test.code = std::move(code); - test.expected.resize(192, sentinel); - for (u32 lane = 0; lane < 64; ++lane) { + test.expected.resize(3 * wave_size, sentinel); + for (u32 lane = 0; lane < wave_size; ++lane) { const auto mask = masks[lane / 32u]; if ((mask & (1u << (lane % 32u))) == 0) { continue; @@ -24833,20 +24837,20 @@ TestCase VectorDpp8Captured(bool masked_exec) { (lane & ~7u) | (lane & 3u)}; for (u32 permutation = 0; permutation < 2; ++permutation) { const auto source = sources[permutation]; - test.expected[permutation * 64u + lane] = - (mask & (1u << (source % 32u))) != 0 ? 100u + source : 0u; + test.expected[permutation * wave_size + lane] = + fi || (mask & (1u << (source % 32u))) != 0 ? 100u + source : 0u; } const u32 source = (lane & ~7u) | 3u; - test.expected[128u + lane] = 100u + lane; - if ((mask & (1u << (source % 32u))) != 0) { - test.expected[128u + lane] += 100u + source; + test.expected[2 * wave_size + lane] = 100u + lane; + if (fi || (mask & (1u << (source % 32u))) != 0) { + test.expected[2 * wave_size + lane] += 100u + source; } } test.opcodes = {O::V_MOV_B32, O::V_ADD_NC_U32, O::S_MOV_B32, O::V_LSHLREV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; test.decoded_counts = {{".dpp8(", 3}}; - test.compute_info.wave_size = 64; - test.compute_info.threads_num[0] = 64; + test.compute_info.wave_size = wave_size; + test.compute_info.threads_num[0] = wave_size; test.compute_info.threads_num[1] = 1; test.compute_info.threads_num[2] = 1; test.compute_info.thread_ids_num = 1; @@ -37171,7 +37175,9 @@ std::vector MakeCases() { AddCase(VectorPermlane16FetchInactiveZero); AddCase(VectorPermlane16FetchInactiveFi); cases.push_back(VectorDpp8Captured(false)); - cases.push_back(VectorDpp8Captured(true)); + for (const u32 wave_size : {32u, 64u}) + for (const bool fi : {false, true}) + cases.push_back(VectorDpp8Captured(true, wave_size, fi)); AddCase(VectorDppQuadPermuteReverse); AddCase(VectorDppRowXmask); cases.push_back(VectorDppRowShare(32)); @@ -42852,7 +42858,9 @@ int main(int argc, char **argv) { if (argc == 2 && std::strcmp(argv[1], "--dpp-only") == 0) { VulkanHarness vulkan; RunCase(&vulkan, VectorDpp8Captured(false)); - RunCase(&vulkan, VectorDpp8Captured(true)); + for (const u32 wave_size : {32u, 64u}) + for (const bool fi : {false, true}) + RunCase(&vulkan, VectorDpp8Captured(true, wave_size, fi)); RunCase(&vulkan, VectorDppQuadPermuteReverse()); RunCase(&vulkan, VectorDppRowXmask()); RunCase(&vulkan, VectorDppRowShare(32));