mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: implement RDNA2 scalar 16-bit sign extension
This commit is contained in:
@@ -53,6 +53,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
|||||||
{0x14u, Opcode::S_FF1_I32_B64},
|
{0x14u, Opcode::S_FF1_I32_B64},
|
||||||
{0x15u, Opcode::S_FLBIT_I32_B32},
|
{0x15u, Opcode::S_FLBIT_I32_B32},
|
||||||
{0x16u, Opcode::S_FLBIT_I32_B64},
|
{0x16u, Opcode::S_FLBIT_I32_B64},
|
||||||
|
{0x1au, Opcode::S_SEXT_I32_I16},
|
||||||
{0x1bu, Opcode::S_BITSET0_B32},
|
{0x1bu, Opcode::S_BITSET0_B32},
|
||||||
{0x1cu, Opcode::S_BITSET0_B64},
|
{0x1cu, Opcode::S_BITSET0_B64},
|
||||||
{0x1du, Opcode::S_BITSET1_B32},
|
{0x1du, Opcode::S_BITSET1_B32},
|
||||||
|
|||||||
@@ -503,6 +503,7 @@ std::string InstructionToString(const Instruction& inst) {
|
|||||||
OperandToString(inst.dst).c_str(),
|
OperandToString(inst.dst).c_str(),
|
||||||
OperandToString(inst.src0).c_str()));
|
OperandToString(inst.src0).c_str()));
|
||||||
case Opcode::S_ABS_I32:
|
case Opcode::S_ABS_I32:
|
||||||
|
case Opcode::S_SEXT_I32_I16:
|
||||||
case Opcode::S_BREV_B32:
|
case Opcode::S_BREV_B32:
|
||||||
case Opcode::S_BREV_B64:
|
case Opcode::S_BREV_B64:
|
||||||
case Opcode::S_BCNT1_I32_B32:
|
case Opcode::S_BCNT1_I32_B32:
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ enum class Opcode {
|
|||||||
S_CMOV_B64,
|
S_CMOV_B64,
|
||||||
S_MOVK_I32,
|
S_MOVK_I32,
|
||||||
S_ABS_I32,
|
S_ABS_I32,
|
||||||
|
S_SEXT_I32_I16,
|
||||||
S_ABSDIFF_I32,
|
S_ABSDIFF_I32,
|
||||||
S_BREV_B32,
|
S_BREV_B32,
|
||||||
S_BREV_B64,
|
S_BREV_B64,
|
||||||
|
|||||||
@@ -134,6 +134,10 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) {
|
|||||||
|
|
||||||
case O::S_ABS_I32:
|
case O::S_ABS_I32:
|
||||||
return SimpleInteger(inst, IR::ValueOpcode::IAbs32, IR::Type::U32, false, false, true);
|
return SimpleInteger(inst, IR::ValueOpcode::IAbs32, IR::Type::U32, false, false, true);
|
||||||
|
case O::S_SEXT_I32_I16:
|
||||||
|
WriteOperand(inst.dst, IR::U32(ir.Emit(IR::ValueOpcode::BitFieldSExtract,
|
||||||
|
{ReadU32(inst.src0), IR::Value(0u), IR::Value(16u)})));
|
||||||
|
return;
|
||||||
case O::S_MUL_I32:
|
case O::S_MUL_I32:
|
||||||
case O::S_MULK_I32:
|
case O::S_MULK_I32:
|
||||||
return SimpleInteger(inst, IR::ValueOpcode::IMul32, IR::Type::U32, false, false, false);
|
return SimpleInteger(inst, IR::ValueOpcode::IMul32, IR::Type::U32, false, false, false);
|
||||||
|
|||||||
@@ -20328,6 +20328,57 @@ TestCase ScalarBrevB32PreservesScc() {
|
|||||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ScalarSextI16Captured() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
TestCase test;
|
||||||
|
test.name = "ScalarSextI16Captured";
|
||||||
|
constexpr u32 wave_size = 64, high = 0x80000001u;
|
||||||
|
test.initial = {0xdead0000u, 0xabcd7fffu, 0x12348000u, 0xabcfffffu};
|
||||||
|
test.expected = test.initial;
|
||||||
|
auto &code = test.code;
|
||||||
|
for (u32 i = 0; i < 4u; ++i) {
|
||||||
|
const auto extended = static_cast<u32>(static_cast<int32_t>(static_cast<int16_t>(test.initial[i])));
|
||||||
|
for (const bool scc : {false, true}) {
|
||||||
|
AppendVMovU32(&code, 30, i * 4u);
|
||||||
|
AppendBufferLoadDword(&code, 3, 30);
|
||||||
|
code.push_back(EncodeVop1(0x02, 11, Vgpr(3)));
|
||||||
|
AppendSMovLiteral(&code, 107, high);
|
||||||
|
code.push_back(EncodeSopc(0x06, InlineU32(scc ? 1u : 0u), InlineU32(1)));
|
||||||
|
code.push_back(EncodeSop1(0x04, 126, 128)); // Scalar operations execute with empty EXEC.
|
||||||
|
code.push_back(0xbeea1a0bu); // Captured s_sext_i32_i16 vcc_lo, s11.
|
||||||
|
code.push_back(EncodeSMovB32(20, 106));
|
||||||
|
code.push_back(EncodeSMovB32(21, 107));
|
||||||
|
code.push_back(EncodeSMovB32(22, 253));
|
||||||
|
code.push_back(EncodeSop1(0x04, 126, 193));
|
||||||
|
AppendVMovU32(&code, 1, 1);
|
||||||
|
code.push_back(EncodeVop2(0x01, 2, InlineU32(0), 1));
|
||||||
|
const u32 expected[] = {extended, high, scc ? 1u : 0u};
|
||||||
|
for (u32 word = 0; word < 3u; ++word) {
|
||||||
|
AppendStoreSgprAtLaneDwordOffset(&code, 20u + word, 0, test.expected.size());
|
||||||
|
test.expected.insert(test.expected.end(), wave_size, expected[word]);
|
||||||
|
}
|
||||||
|
AppendStoreVgprAtLaneDwordOffset(&code, 2, 0, test.expected.size());
|
||||||
|
const uint64_t mask = (uint64_t{high} << 32u) | extended;
|
||||||
|
for (u32 lane = 0; lane < wave_size; ++lane)
|
||||||
|
test.expected.push_back(static_cast<u32>((mask >> lane) & 1u));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppendEnd(&code);
|
||||||
|
test.initial.resize(test.expected.size());
|
||||||
|
test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_READFIRSTLANE_B32, O::S_MOV_B32,
|
||||||
|
O::S_MOV_B64, O::S_CMP_EQ_U32, O::S_SEXT_I32_I16,
|
||||||
|
O::V_CNDMASK_B32, O::V_MOV_B32, O::V_ADD_NC_U32,
|
||||||
|
O::V_LSHLREV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
|
test.decoded_counts = {{"S_SEXT_I32_I16", 8u}};
|
||||||
|
test.required_spirv = {"OpBitFieldSExtract"};
|
||||||
|
test.compute_info.threads_num[0] = wave_size;
|
||||||
|
test.compute_info.threads_num[1] = test.compute_info.threads_num[2] = 1;
|
||||||
|
test.compute_info.thread_ids_num = 1;
|
||||||
|
test.compute_info.wave_size = wave_size;
|
||||||
|
test.has_compute_info = true;
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase ScalarBrevB64OperandsAndMasks(u32 wave_size) {
|
TestCase ScalarBrevB64OperandsAndMasks(u32 wave_size) {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
TestCase test;
|
TestCase test;
|
||||||
@@ -35081,6 +35132,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ScalarBitcmpB64DynamicOperands);
|
AddCase(ScalarBitcmpB64DynamicOperands);
|
||||||
AddCase(ScalarBitcmpB64IntegerConstants);
|
AddCase(ScalarBitcmpB64IntegerConstants);
|
||||||
AddCase(ScalarBrevB32PreservesScc);
|
AddCase(ScalarBrevB32PreservesScc);
|
||||||
|
AddCase(ScalarSextI16Captured);
|
||||||
cases.push_back(ScalarBrevB64OperandsAndMasks(32));
|
cases.push_back(ScalarBrevB64OperandsAndMasks(32));
|
||||||
cases.push_back(ScalarBrevB64OperandsAndMasks(64));
|
cases.push_back(ScalarBrevB64OperandsAndMasks(64));
|
||||||
AddCase(ScalarBfeI32CapturedRawSignExtends);
|
AddCase(ScalarBfeI32CapturedRawSignExtends);
|
||||||
@@ -40720,6 +40772,11 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (argc == 2 && std::strcmp(argv[1], "--scalar-sext-only") == 0) {
|
||||||
|
VulkanHarness vulkan;
|
||||||
|
RunCase(&vulkan, ScalarSextI16Captured());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--flat-d16-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--flat-d16-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, FlatLoadDlcCaptured(32));
|
RunCase(&vulkan, FlatLoadDlcCaptured(32));
|
||||||
|
|||||||
Reference in New Issue
Block a user