diff --git a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp index b625e57f..fed2e6f1 100644 --- a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp @@ -1126,8 +1126,10 @@ void DecodeVop2Dpp(uint32_t pc, std::span code, uint32_t word_in DecodeVectorGpr(vsrc1, inst.src1); DecodeScalarSource(src0 + 256u, pc, inst.src0); ApplyDppModifier(inst.src0, modifier, code[word_index] & 0x1ffu); - inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; - inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; + if (!inst.src0.dpp8) { + inst.src1.negate = ((modifier >> 22u) & 0x1u) != 0u; + inst.src1.absolute = ((modifier >> 23u) & 0x1u) != 0u; + } const bool packed_fmac = inst.opcode == Opcode::V_PK_FMAC_F16; if (packed_fmac) { inst.src0.negate_hi = inst.src0.negate; @@ -1582,6 +1584,7 @@ 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 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; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 266ef64f..7a51c1fa 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -23333,8 +23333,10 @@ TestCase VectorDpp8Captured(bool masked_exec) { std::vector code; AppendVMovU32(&code, 5, 100); code.push_back(EncodeVop2(0x25, 5, Vgpr(0), 5)); + code.push_back(EncodeVop1(0x01, 7, Vgpr(5))); AppendVMovLiteral(&code, 2, sentinel); AppendVMovLiteral(&code, 3, sentinel); + AppendVMovLiteral(&code, 8, sentinel); AppendSMovLiteral(&code, 126, masks[0]); AppendSMovLiteral(&code, 127, masks[1]); // Captured DPP8 selectors broadcast each group's upper/lower four lanes. @@ -23342,6 +23344,9 @@ TestCase VectorDpp8Captured(bool masked_exec) { code.push_back(0xfacfac05u); code.push_back(EncodeVop1(0x01, 3, 233)); 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(0x6db6db07u); AppendSMovLiteral(&code, 126, 0xffffffffu); AppendSMovLiteral(&code, 127, 0xffffffffu); code.push_back(EncodeVop2(0x1a, 6, InlineU32(2), 0)); @@ -23349,13 +23354,15 @@ TestCase VectorDpp8Captured(bool masked_exec) { AppendVMovU32(&code, 7, 64u * sizeof(u32)); code.push_back(EncodeVop2(0x25, 6, Vgpr(7), 6)); AppendBufferStoreDword(&code, 3, 6); + code.push_back(EncodeVop2(0x25, 6, Vgpr(7), 6)); + AppendBufferStoreDword(&code, 8, 6); AppendEnd(&code); TestCase test; test.name = masked_exec ? "VectorDpp8CapturedMaskedExec" : "VectorDpp8Captured"; test.code = std::move(code); - test.expected.resize(128, sentinel); + test.expected.resize(192, sentinel); for (u32 lane = 0; lane < 64; ++lane) { const auto mask = masks[lane / 32u]; if ((mask & (1u << (lane % 32u))) == 0) { @@ -23368,10 +23375,15 @@ TestCase VectorDpp8Captured(bool masked_exec) { test.expected[permutation * 64u + lane] = (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.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(", 2}}; + test.decoded_counts = {{".dpp8(", 3}}; test.compute_info.wave_size = 64; test.compute_info.threads_num[0] = 64; test.compute_info.threads_num[1] = 1;