mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-08-19 06:52:36 +00:00
shader: implement RDNA2 V_MED3_I16
This commit is contained in:
@@ -647,6 +647,7 @@ std::string OpcodeToString(Opcode opcode) {
|
||||
case Opcode::VMed3I32: return "v_med3_i32";
|
||||
case Opcode::VMed3U32: return "v_med3_u32";
|
||||
case Opcode::VMed3F16: return "v_med3_f16";
|
||||
case Opcode::VMed3I16: return "v_med3_i16";
|
||||
case Opcode::VSadU32: return "v_sad_u32";
|
||||
case Opcode::VAdd3U32: return "v_add3_u32";
|
||||
case Opcode::VLshlAddU32: return "v_lshl_add_u32";
|
||||
|
||||
@@ -232,6 +232,7 @@ enum class Opcode {
|
||||
VMed3I32,
|
||||
VMed3U32,
|
||||
VMed3F16,
|
||||
VMed3I16,
|
||||
VSadU32,
|
||||
VAdd3U32,
|
||||
VLshlAddU32,
|
||||
|
||||
@@ -254,29 +254,30 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = {
|
||||
{0x155u, Opcode::VMax3I32}, {0x156u, Opcode::VMax3U32},
|
||||
{0x354u, Opcode::VMax3F16}, {0x157u, Opcode::VMed3F32},
|
||||
{0x158u, Opcode::VMed3I32}, {0x159u, Opcode::VMed3U32},
|
||||
{0x357u, Opcode::VMed3F16}, {0x15du, Opcode::VSadU32},
|
||||
{0x15eu, Opcode::VCvtPkU8F32}, {0x178u, Opcode::VXor3B32},
|
||||
{0x12fu, Opcode::VCvtPkrtzF16F32}, {0x169u, Opcode::VMulLoU32},
|
||||
{0x16au, Opcode::VMulHiU32}, {0x16bu, Opcode::VMulLoI32},
|
||||
{0x16cu, Opcode::VMulHiI32}, {0x303u, Opcode::VAddNcU16},
|
||||
{0x304u, Opcode::VSubNcU16}, {0x307u, Opcode::VLshrrevB16},
|
||||
{0x308u, Opcode::VAshrrevI16}, {0x309u, Opcode::VMaxU16},
|
||||
{0x30au, Opcode::VMaxI16}, {0x30bu, Opcode::VMinU16},
|
||||
{0x30cu, Opcode::VMinI16}, {0x30du, Opcode::VAddNcI16},
|
||||
{0x30eu, Opcode::VSubNcI16}, {0x30fu, Opcode::VAddI32},
|
||||
{0x310u, Opcode::VSubI32}, {0x311u, Opcode::VPackB32F16},
|
||||
{0x314u, Opcode::VLshlrevB16}, {0x319u, Opcode::VSubrevI32},
|
||||
{0x345u, Opcode::VXadU32}, {0x346u, Opcode::VLshlAddU32},
|
||||
{0x347u, Opcode::VAddLshlU32}, {0x360u, Opcode::VReadlaneB32},
|
||||
{0x361u, Opcode::VWritelaneB32}, {0x362u, Opcode::VLdexpF32},
|
||||
{0x363u, Opcode::VBfmB32}, {0x364u, Opcode::VBcntU32B32},
|
||||
{0x365u, Opcode::VMbcntLoU32B32}, {0x366u, Opcode::VMbcntHiU32B32},
|
||||
{0x368u, Opcode::VCvtPknormI16F32}, {0x369u, Opcode::VCvtPknormU16F32},
|
||||
{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},
|
||||
{0x357u, Opcode::VMed3F16}, {0x358u, Opcode::VMed3I16},
|
||||
{0x15du, Opcode::VSadU32}, {0x15eu, Opcode::VCvtPkU8F32},
|
||||
{0x178u, Opcode::VXor3B32}, {0x12fu, Opcode::VCvtPkrtzF16F32},
|
||||
{0x169u, Opcode::VMulLoU32}, {0x16au, Opcode::VMulHiU32},
|
||||
{0x16bu, Opcode::VMulLoI32}, {0x16cu, Opcode::VMulHiI32},
|
||||
{0x303u, Opcode::VAddNcU16}, {0x304u, Opcode::VSubNcU16},
|
||||
{0x307u, Opcode::VLshrrevB16}, {0x308u, Opcode::VAshrrevI16},
|
||||
{0x309u, Opcode::VMaxU16}, {0x30au, Opcode::VMaxI16},
|
||||
{0x30bu, Opcode::VMinU16}, {0x30cu, Opcode::VMinI16},
|
||||
{0x30du, Opcode::VAddNcI16}, {0x30eu, Opcode::VSubNcI16},
|
||||
{0x30fu, Opcode::VAddI32}, {0x310u, Opcode::VSubI32},
|
||||
{0x311u, Opcode::VPackB32F16}, {0x314u, Opcode::VLshlrevB16},
|
||||
{0x319u, Opcode::VSubrevI32}, {0x345u, Opcode::VXadU32},
|
||||
{0x346u, Opcode::VLshlAddU32}, {0x347u, Opcode::VAddLshlU32},
|
||||
{0x360u, Opcode::VReadlaneB32}, {0x361u, Opcode::VWritelaneB32},
|
||||
{0x362u, Opcode::VLdexpF32}, {0x363u, Opcode::VBfmB32},
|
||||
{0x364u, Opcode::VBcntU32B32}, {0x365u, Opcode::VMbcntLoU32B32},
|
||||
{0x366u, Opcode::VMbcntHiU32B32}, {0x368u, Opcode::VCvtPknormI16F32},
|
||||
{0x369u, Opcode::VCvtPknormU16F32}, {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);
|
||||
@@ -371,6 +372,10 @@ bool IsNativeVop3F16TernaryOpcode(Opcode opcode) {
|
||||
opcode == Opcode::VFmaF16;
|
||||
}
|
||||
|
||||
bool IsNativeVop3I16TernaryOpcode(Opcode opcode) {
|
||||
return opcode == Opcode::VMed3I16;
|
||||
}
|
||||
|
||||
bool IsNativeVop3B16BinaryOpcode(Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Opcode::VAddNcU16:
|
||||
@@ -1283,6 +1288,14 @@ void ApplyNativeVop3TernaryModifiers(Instruction& inst, uint32_t op_sel, uint32_
|
||||
inst.dst.sdwa_sel = ((op_sel & 0x8u) != 0) ? 5u : 4u;
|
||||
}
|
||||
|
||||
void ApplyNativeVop3I16TernarySelectors(Instruction& inst, uint32_t op_sel) {
|
||||
Operand* sources[] = {&inst.src0, &inst.src1, &inst.src2};
|
||||
for (uint32_t i = 0; i < 3u; i++) {
|
||||
sources[i]->op_sel = ((op_sel >> i) & 1u) != 0;
|
||||
}
|
||||
inst.dst.sdwa_sel = (op_sel & 0x8u) != 0 ? 5u : 4u;
|
||||
}
|
||||
|
||||
void ApplyNativeVop3B16BinaryModifiers(Instruction& inst, uint32_t op_sel) {
|
||||
inst.src0.op_sel = (op_sel & 0x1u) != 0;
|
||||
inst.src1.op_sel = (op_sel & 0x2u) != 0;
|
||||
@@ -1375,6 +1388,9 @@ bool HasUnsupportedNativeVop3Modifiers(Opcode opcode, bool permlane, bool mad_mi
|
||||
if (IsNativeVop3F16TernaryOpcode(opcode)) {
|
||||
return opcode != Opcode::VFmaF16 && (clamp != 0u || omod != 0u);
|
||||
}
|
||||
if (IsNativeVop3I16TernaryOpcode(opcode)) {
|
||||
return abs != 0u || clamp != 0u || omod != 0u || neg != 0u;
|
||||
}
|
||||
if (IsNativeVop3B16BinaryOpcode(opcode)) {
|
||||
return abs != 0u || clamp != 0u || omod != 0u || neg != 0u;
|
||||
}
|
||||
@@ -1595,6 +1611,7 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
const bool vop3b_uses_sdst = carry_in_out || vop3b_carry_out || vop3b_mad_u64;
|
||||
const bool mad_mix = false;
|
||||
const bool f16_ternary = IsNativeVop3F16TernaryOpcode(inst.opcode);
|
||||
const bool i16_ternary = IsNativeVop3I16TernaryOpcode(inst.opcode);
|
||||
const bool b16_binary = IsNativeVop3B16BinaryOpcode(inst.opcode);
|
||||
const bool pack_b32_f16 = inst.opcode == Opcode::VPackB32F16;
|
||||
const bool permlane = IsPermlaneOpcode(inst.opcode);
|
||||
@@ -1721,6 +1738,8 @@ bool DecodeVop3(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg);
|
||||
} else if (f16_ternary) {
|
||||
ApplyNativeVop3TernaryModifiers(inst, op_sel, abs, neg);
|
||||
} else if (i16_ternary) {
|
||||
ApplyNativeVop3I16TernarySelectors(inst, op_sel);
|
||||
} else if (b16_binary) {
|
||||
ApplyNativeVop3B16BinaryModifiers(inst, op_sel);
|
||||
} else if (pack_b32_f16) {
|
||||
|
||||
@@ -32,6 +32,11 @@ bool Translator::TranslateInteger16Operation(const IR::Instruction& inst) {
|
||||
case IR::Opcode::ISubI16:
|
||||
result = ir.ISub(ReadU16AsU32(inst.src[0], false), ReadU16AsU32(inst.src[1], false));
|
||||
break;
|
||||
case IR::Opcode::IMed3I16:
|
||||
result = ir.Emit(IR::ValueOpcode::SMedTri32,
|
||||
{ReadU16AsU32(inst.src[0], true), ReadU16AsU32(inst.src[1], true),
|
||||
ReadU16AsU32(inst.src[2], true)});
|
||||
break;
|
||||
case IR::Opcode::IMinI16:
|
||||
case IR::Opcode::IMaxI16:
|
||||
case IR::Opcode::UMinU16:
|
||||
|
||||
@@ -166,6 +166,7 @@ constexpr LowerMap LOWER_OPS[] = {
|
||||
{Decoder::Opcode::VMed3I32, Opcode::IMed3I32},
|
||||
{Decoder::Opcode::VMed3U32, Opcode::UMed3U32},
|
||||
{Decoder::Opcode::VMed3F16, Opcode::Med3F16},
|
||||
{Decoder::Opcode::VMed3I16, Opcode::IMed3I16},
|
||||
{Decoder::Opcode::VSadU32, Opcode::SadU32},
|
||||
{Decoder::Opcode::VAdd3U32, Opcode::IAdd3U32},
|
||||
{Decoder::Opcode::VLshlAddU32, Opcode::ShiftLeftAddU32},
|
||||
|
||||
@@ -251,6 +251,7 @@ IR_OPCODE(IAddU16, General, Integer16)
|
||||
IR_OPCODE(ISubI16, General, Integer16)
|
||||
IR_OPCODE(IMinI16, General, Integer16)
|
||||
IR_OPCODE(IMaxI16, General, Integer16)
|
||||
IR_OPCODE(IMed3I16, General, Integer16)
|
||||
IR_OPCODE(UMinU16, General, Integer16)
|
||||
IR_OPCODE(UMaxU16, General, Integer16)
|
||||
IR_OPCODE(RcpF32, General, Float)
|
||||
|
||||
@@ -11995,6 +11995,33 @@ TestCase Vop3CvtPkI16I32Captured() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop3Med3I16Captured() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
std::vector<u32> code;
|
||||
AppendVMovLiteral(&code, 5, 0x8ad003e8u); // high=-30000, low=1000
|
||||
AppendSMovLiteral(&code, 25, 0xb1e04e20u); // high=-20000, low=20000
|
||||
AppendSMovLiteral(&code, 27, 0x7530fc18u); // high=30000, low=-1000
|
||||
AppendVMovLiteral(&code, 3, 0x1234cafeu);
|
||||
code.push_back(0xd7584803u);
|
||||
code.push_back(0x006c3305u); // v_med3_i16 v3.hi, v5.hi, s25.lo, s27.lo
|
||||
AppendStoreVgpr(&code, 3, 0);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "Vop3Med3I16Captured";
|
||||
test.code = std::move(code);
|
||||
test.expected = {0xfc18cafeu};
|
||||
test.opcodes = {O::VMovB32, O::SMovB32, O::VMed3I16, O::BufferStoreDword,
|
||||
O::SEndpgm};
|
||||
test.decoded_counts = {{"0x00000020: v_med3_i16 v3.sdwa(sel=5,sext=0), "
|
||||
"v5.opsel(lo=1,hi=0,neghi=0), s25, s27\n",
|
||||
1}};
|
||||
test.native_ir_counts = {{"IMed3I16", 1}};
|
||||
test.required_spirv = {"OpSLessThan"};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop2SdwaMinU32PreservesWordDestination() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -17757,6 +17784,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(Vop2SdwaAshrrevCapturedWord0SignExtends);
|
||||
AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations);
|
||||
AddCase(Vop3CvtPkI16I32Captured);
|
||||
AddCase(Vop3Med3I16Captured);
|
||||
AddCase(Vop2SdwaMinU32PreservesWordDestination);
|
||||
AddCase(VectorShiftCountsMaskLowBits);
|
||||
AddCase(VectorVop3IntegerOps);
|
||||
@@ -21240,6 +21268,11 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, Vop3CvtPkI16I32Captured());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--med3-i16-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, Vop3Med3I16Captured());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--waitcnt-depctr-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, ScalarWaitcntDepctrCapturedVmVsrc());
|
||||
|
||||
Reference in New Issue
Block a user