diff --git a/src/graphics/shader/recompiler/decompiler/VectorAluOps.cpp b/src/graphics/shader/recompiler/decompiler/VectorAluOps.cpp index 78208d6..6fd1dbf 100644 --- a/src/graphics/shader/recompiler/decompiler/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/decompiler/VectorAluOps.cpp @@ -824,7 +824,7 @@ constexpr Vop2SdwaRule VOP2_SDWA_RULES[] = { SdwaSelWords() | SdwaSelFull(), true, true}, {Opcode::VMulI32I24, SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false}, {Opcode::VMulU32U24, SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false}, - {Opcode::VMinU32, SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false}, + {Opcode::VMinU32, SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false}, {Opcode::VMaxU32, SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false}, {Opcode::VLshrrevB32, SdwaSelFull(), SdwaSelFull(), SdwaSelWords() | SdwaSelFull(), false, false}, diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index a220f6e..ebb030b 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -10158,6 +10158,31 @@ TestCase Vop2SdwaSubNcPreservesByteAndWordDestinations() { {O::VMovB32, O::VSubNcU32, O::BufferStoreDword, O::SEndpgm}}; } +TestCase Vop2SdwaMinU32PreservesWordDestination() { + using O = ShaderOpcode; + + std::vector code; + AppendVMovLiteral(&code, 10, 0xa1b2c3d4u); + AppendVMovU32(&code, 12, 7); + code.push_back(0x261418f9u); + code.push_back(0x0686149fu); + AppendStoreVgpr(&code, 10, 0); + AppendVMovLiteral(&code, 10, 0xa1b2c3d4u); + AppendVMovU32(&code, 12, 64); + code.push_back(0x261418f9u); + code.push_back(0x0686149fu); + AppendStoreVgpr(&code, 10, 1); + AppendEnd(&code); + + TestCase test; + test.name = "Vop2SdwaMinU32PreservesWordDestination"; + test.code = code; + test.expected = {0xa1b20007u, 0xa1b2001fu}; + test.opcodes = {O::VMovB32, O::VMinU32, O::BufferStoreDword, O::SEndpgm}; + test.required_spirv = {"OpULessThan", "OpSelect", "OpBitwiseOr"}; + return test; +} + TestCase VectorShiftCountsMaskLowBits() { using O = ShaderOpcode; @@ -15120,6 +15145,7 @@ std::vector MakeCases() { AddCase(VectorIntegerOps); AddCase(Vop2SdwaSubNcExactByte2Destination); AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations); + AddCase(Vop2SdwaMinU32PreservesWordDestination); AddCase(VectorShiftCountsMaskLowBits); AddCase(VectorVop3IntegerOps); AddCase(VectorBfeI32ArithmeticShiftMasksField); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index b485810..328ed10 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -2426,6 +2426,8 @@ void TestNewShaderRecompilerBootB16PackedAndSdwaOpcodes() { 0x0d860688u, // v_add_nc_u32 v6, 8, sign-extended v6.hi 0x4c1616f9u, 0x0686128du, // v_sub_nc_u32 v11.byte2, 13, v11; preserve other destination bytes + 0x261418f9u, + 0x0686149fu, // v_min_u32 v10.word0, 31, v12; preserve upper destination word 0xbf810000u, }; @@ -2476,6 +2478,8 @@ void TestNewShaderRecompilerBootB16PackedAndSdwaOpcodes() { "new decoder did not decode V_ADD_NC_U32 SDWA sign-extended high word"); Check(Common::ContainsStr(result.decoded_dump, "v_sub_nc_u32 v11.sdwa(sel=2"), "new decoder did not decode V_SUB_NC_U32 SDWA byte-2 destination"); + Check(Common::ContainsStr(result.decoded_dump, "v_min_u32 v10.sdwa(sel=4"), + "new decoder did not decode V_MIN_U32 SDWA low-word destination"); Check(!Common::ContainsStr(result.decoded_dump, "unsupported family=VOP2 opcode=0x00"), "literal/SDWA extension words were decoded as phantom VOP2 instructions"); Check(!Common::ContainsStr(result.decoded_dump, @@ -2511,6 +2515,8 @@ void TestNewShaderRecompilerBootB16PackedAndSdwaOpcodes() { "V_ADD_NC_U32 SDWA sign-extended high word did not lower to IR"); Check(Common::ContainsStr(result.ir_dump, "ISubU32 v11.sdwa(sel=2"), "V_SUB_NC_U32 SDWA byte-2 destination did not lower to IR"); + Check(Common::ContainsStr(result.ir_dump, "UMinU32 v10.sdwa(sel=4"), + "V_MIN_U32 SDWA low-word destination did not lower to IR"); Check(SpirvContainsOpcode(result.spirv, 128), "SPIR-V binary does not contain OpIAdd for U16 operations"); Check(SpirvContainsOpcode(result.spirv, 202),