diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp index 14df6cd39..9ff41bb3d 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.cpp @@ -664,6 +664,7 @@ std::string OpcodeToString(Opcode opcode) { case Opcode::VCvtPknormI16F32: return "v_cvt_pknorm_i16_f32"; case Opcode::VCvtPknormU16F32: return "v_cvt_pknorm_u16_f32"; case Opcode::VCvtPkU16U32: return "v_cvt_pk_u16_u32"; + case Opcode::VCvtPkI16I32: return "v_cvt_pk_i16_i32"; case Opcode::VPkMadI16: return "v_pk_mad_i16"; case Opcode::VPkMulLoU16: return "v_pk_mul_lo_u16"; case Opcode::VPkAddI16: return "v_pk_add_i16"; diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index f93532db5..182c95dfb 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -249,6 +249,7 @@ enum class Opcode { VCvtPknormI16F32, VCvtPknormU16F32, VCvtPkU16U32, + VCvtPkI16I32, VPkMadI16, VPkMulLoU16, VPkAddI16, diff --git a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp index ab6a00e05..5aac76b9c 100644 --- a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp @@ -272,11 +272,11 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = { {0x363u, Opcode::VBfmB32}, {0x364u, Opcode::VBcntU32B32}, {0x365u, Opcode::VMbcntLoU32B32}, {0x366u, Opcode::VMbcntHiU32B32}, {0x368u, Opcode::VCvtPknormI16F32}, {0x369u, Opcode::VCvtPknormU16F32}, - {0x36au, Opcode::VCvtPkU16U32}, {0x36fu, Opcode::VLshlOrB32}, - {0x371u, Opcode::VAndOrB32}, {0x372u, Opcode::VOr3B32}, - {0x377u, Opcode::VPermlane16B32}, {0x378u, Opcode::VPermlanex16B32}, - {0x34bu, Opcode::VFmaF16}, {0x36du, Opcode::VAdd3U32}, - {0x14fu, Opcode::VAlignbyteB32}, + {0x36au, Opcode::VCvtPkU16U32}, {0x36bu, Opcode::VCvtPkI16I32}, + {0x36fu, Opcode::VLshlOrB32}, {0x371u, Opcode::VAndOrB32}, + {0x372u, Opcode::VOr3B32}, {0x377u, Opcode::VPermlane16B32}, + {0x378u, Opcode::VPermlanex16B32}, {0x34bu, Opcode::VFmaF16}, + {0x36du, Opcode::VAdd3U32}, {0x14fu, Opcode::VAlignbyteB32}, }; constexpr auto VOP3_OPS = Detail::MakeOpcodeTable<0x400>(VOP3_OPCODE_LIST); @@ -1208,7 +1208,8 @@ uint32_t NativeVop3SourceCount(Opcode opcode) { case Opcode::VBcntU32B32: case Opcode::VCvtPknormI16F32: case Opcode::VCvtPknormU16F32: - case Opcode::VCvtPkU16U32: return 2; + case Opcode::VCvtPkU16U32: + case Opcode::VCvtPkI16I32: return 2; default: return 3; } } diff --git a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp index f4d2b3941..cfe2ae777 100644 --- a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp +++ b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp @@ -201,6 +201,7 @@ constexpr LowerMap LOWER_OPS[] = { {Decoder::Opcode::VCvtPknormI16F32, Opcode::PackSnorm2x16F32}, {Decoder::Opcode::VCvtPknormU16F32, Opcode::PackUnorm2x16F32}, {Decoder::Opcode::VCvtPkU16U32, Opcode::PackU16U32}, + {Decoder::Opcode::VCvtPkI16I32, Opcode::PackU16U32}, {Decoder::Opcode::VCvtPkU8F32, Opcode::PackU8F32}, {Decoder::Opcode::VPackB32F16, Opcode::PackB32F16}, {Decoder::Opcode::VPkMadI16, Opcode::PackedMadI16}, diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 9476a9143..f2b4a69d0 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -11809,6 +11809,34 @@ TestCase Vop2SdwaSubNcPreservesByteAndWordDestinations() { {O::VMovB32, O::VSubNcU32, O::BufferStoreDword, O::SEndpgm}}; } +TestCase Vop3CvtPkI16I32Captured() { + using O = ShaderOpcode; + + std::vector code; + AppendBufferLoadDword(&code, 7, 30); + AppendVMovU32(&code, 30, 4); + AppendBufferLoadDword(&code, 16, 30); + code.push_back(0xd76b0005u); + code.push_back(0x00022107u); // v_cvt_pk_i16_i32 v5, v7, v16 + AppendStoreVgpr(&code, 5, 2); + AppendEnd(&code); + + TestCase test; + test.name = "Vop3CvtPkI16I32Captured"; + test.code = std::move(code); + test.initial = {0x00018001u, 0xfffe7ffeu, 0}; + test.expected = {0x00018001u, 0xfffe7ffeu, 0x7ffe8001u}; + test.opcodes = {O::BufferLoadDword, O::VMovB32, O::VCvtPkI16I32, + O::BufferStoreDword, O::SEndpgm}; + test.decoded_counts = { + {"0x00000014: v_cvt_pk_i16_i32 v5, v7, v16\n", 1}}; + test.ir_counts = {{" = BitwiseAnd32 ", 2}, + {" = ShiftLeftLogical32 ", 1}, + {" = BitwiseOr32 ", 1}}; + test.required_spirv = {"OpBitwiseAnd", "OpShiftLeftLogical", "OpBitwiseOr"}; + return test; +} + TestCase Vop2SdwaMinU32PreservesWordDestination() { using O = ShaderOpcode; @@ -17567,6 +17595,7 @@ std::vector MakeCases() { AddCase(Vop2SdwaAddNcCapturedHighWordDestination); AddCase(Vop2SdwaAshrrevCapturedWord0SignExtends); AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations); + AddCase(Vop3CvtPkI16I32Captured); AddCase(Vop2SdwaMinU32PreservesWordDestination); AddCase(VectorShiftCountsMaskLowBits); AddCase(VectorVop3IntegerOps); @@ -21012,6 +21041,11 @@ int main(int argc, char **argv) { RunCase(&vulkan, Vop2SdwaAshrrevCapturedWord0SignExtends()); return 0; } + if (argc == 2 && std::strcmp(argv[1], "--cvt-pk-i16-only") == 0) { + VulkanHarness vulkan; + RunCase(&vulkan, Vop3CvtPkI16I32Captured()); + return 0; + } if (argc == 2 && std::strcmp(argv[1], "--sff1-b64-only") == 0) { VulkanHarness vulkan; RunCase(&vulkan, ScalarBitfieldPack());