mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
shader: support scalar byte sign extension
This commit is contained in:
1 parent
c3a12397b0
commit
9e666e4dd2
5 files changed
+69
-12
No files matched your search
@@ -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},
|
||||||
|
{0x19u, Opcode::S_SEXT_I32_I8},
|
||||||
{0x1au, Opcode::S_SEXT_I32_I16},
|
{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},
|
||||||
|
|||||||
@@ -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_I8:
|
||||||
case Opcode::S_SEXT_I32_I16:
|
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:
|
||||||
|
|||||||
@@ -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_I8,
|
||||||
S_SEXT_I32_I16,
|
S_SEXT_I32_I16,
|
||||||
S_ABSDIFF_I32,
|
S_ABSDIFF_I32,
|
||||||
S_BREV_B32,
|
S_BREV_B32,
|
||||||
|
|||||||
@@ -134,10 +134,14 @@ 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:
|
case O::S_SEXT_I32_I8:
|
||||||
|
case O::S_SEXT_I32_I16: {
|
||||||
|
// Sign extension leaves SCC unchanged.
|
||||||
|
const auto bits = inst.opcode == O::S_SEXT_I32_I8 ? 8u : 16u;
|
||||||
WriteOperand(inst.dst, IR::U32(ir.Emit(IR::ValueOpcode::BitFieldSExtract,
|
WriteOperand(inst.dst, IR::U32(ir.Emit(IR::ValueOpcode::BitFieldSExtract,
|
||||||
{ReadU32(inst.src0), IR::Value(0u), IR::Value(16u)})));
|
{ReadU32(inst.src0), IR::Value(0u), IR::Value(bits)})));
|
||||||
return;
|
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);
|
||||||
|
|||||||
@@ -20590,16 +20590,23 @@ 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() {
|
TestCase ScalarSextMasks(u32 bits, u32 wave_size) {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
TestCase test;
|
TestCase test;
|
||||||
test.name = "ScalarSextI16Captured";
|
test.name = bits == 8 ? (wave_size == 32 ? "ScalarSextI8MasksWave32"
|
||||||
constexpr u32 wave_size = 64, high = 0x80000001u;
|
: "ScalarSextI8MasksWave64")
|
||||||
test.initial = {0xdead0000u, 0xabcd7fffu, 0x12348000u, 0xabcfffffu};
|
: (wave_size == 32 ? "ScalarSextI16MasksWave32"
|
||||||
|
: "ScalarSextI16MasksWave64");
|
||||||
|
constexpr u32 high = 0x80000001u;
|
||||||
|
test.initial = bits == 8
|
||||||
|
? std::vector<u32>{0xdeadff00u, 0xabcdff7fu, 0x12340080u, 0xabcf00ffu}
|
||||||
|
: std::vector<u32>{0xdead0000u, 0xabcd7fffu, 0x12348000u, 0xabcfffffu};
|
||||||
|
const u32 extended_values[] = {0u, bits == 8 ? 0x7fu : 0x7fffu,
|
||||||
|
bits == 8 ? 0xffffff80u : 0xffff8000u, 0xffffffffu};
|
||||||
test.expected = test.initial;
|
test.expected = test.initial;
|
||||||
auto &code = test.code;
|
auto &code = test.code;
|
||||||
for (u32 i = 0; i < 4u; ++i) {
|
for (u32 i = 0; i < 4u; ++i) {
|
||||||
const auto extended = static_cast<u32>(static_cast<int32_t>(static_cast<int16_t>(test.initial[i])));
|
const auto extended = extended_values[i];
|
||||||
for (const bool scc : {false, true}) {
|
for (const bool scc : {false, true}) {
|
||||||
AppendVMovU32(&code, 30, i * 4u);
|
AppendVMovU32(&code, 30, i * 4u);
|
||||||
AppendBufferLoadDword(&code, 3, 30);
|
AppendBufferLoadDword(&code, 3, 30);
|
||||||
@@ -20607,7 +20614,8 @@ TestCase ScalarSextI16Captured() {
|
|||||||
AppendSMovLiteral(&code, 107, high);
|
AppendSMovLiteral(&code, 107, high);
|
||||||
code.push_back(EncodeSopc(0x06, InlineU32(scc ? 1u : 0u), InlineU32(1)));
|
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(EncodeSop1(0x04, 126, 128)); // Scalar operations execute with empty EXEC.
|
||||||
code.push_back(0xbeea1a0bu); // Captured s_sext_i32_i16 vcc_lo, s11.
|
// The I16 word is captured s_sext_i32_i16 vcc_lo, s11.
|
||||||
|
code.push_back(bits == 8 ? 0xbeea190bu : 0xbeea1a0bu);
|
||||||
code.push_back(EncodeSMovB32(20, 106));
|
code.push_back(EncodeSMovB32(20, 106));
|
||||||
code.push_back(EncodeSMovB32(21, 107));
|
code.push_back(EncodeSMovB32(21, 107));
|
||||||
code.push_back(EncodeSMovB32(22, 253));
|
code.push_back(EncodeSMovB32(22, 253));
|
||||||
@@ -20628,10 +20636,12 @@ TestCase ScalarSextI16Captured() {
|
|||||||
AppendEnd(&code);
|
AppendEnd(&code);
|
||||||
test.initial.resize(test.expected.size());
|
test.initial.resize(test.expected.size());
|
||||||
test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_READFIRSTLANE_B32, O::S_MOV_B32,
|
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::S_MOV_B64, O::S_CMP_EQ_U32,
|
||||||
|
bits == 8 ? O::S_SEXT_I32_I8 : O::S_SEXT_I32_I16,
|
||||||
O::V_CNDMASK_B32, O::V_MOV_B32, O::V_ADD_NC_U32,
|
O::V_CNDMASK_B32, O::V_MOV_B32, O::V_ADD_NC_U32,
|
||||||
O::V_LSHLREV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
O::V_LSHLREV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
test.decoded_counts = {{"S_SEXT_I32_I16", 8u}};
|
test.decoded_counts = {{bits == 8 ? "S_SEXT_I32_I8 vcc_lo, s11"
|
||||||
|
: "S_SEXT_I32_I16 vcc_lo, s11", 8u}};
|
||||||
test.required_spirv = {"OpBitFieldSExtract"};
|
test.required_spirv = {"OpBitFieldSExtract"};
|
||||||
test.compute_info.threads_num[0] = wave_size;
|
test.compute_info.threads_num[0] = wave_size;
|
||||||
test.compute_info.threads_num[1] = test.compute_info.threads_num[2] = 1;
|
test.compute_info.threads_num[1] = test.compute_info.threads_num[2] = 1;
|
||||||
@@ -20641,6 +20651,38 @@ TestCase ScalarSextI16Captured() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ScalarSextConstantsAndAliases() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
TestCase test;
|
||||||
|
test.name = "ScalarSextConstantsAndAliases";
|
||||||
|
auto &code = test.code;
|
||||||
|
for (const u32 opcode : {0x19u, 0x1au}) {
|
||||||
|
const u32 literal = opcode == 0x19u ? 0x12345680u : 0x12348000u;
|
||||||
|
const u32 extended = opcode == 0x19u ? 0xffffff80u : 0xffff8000u;
|
||||||
|
for (const bool scc : {false, true}) {
|
||||||
|
code.push_back(EncodeSopc(0x06, InlineU32(scc ? 1u : 0u), InlineU32(1)));
|
||||||
|
code.push_back(EncodeSop1(opcode, 10, 255));
|
||||||
|
code.push_back(literal);
|
||||||
|
code.push_back(EncodeSop1(opcode, 10, 10)); // In-place source/destination.
|
||||||
|
code.push_back(EncodeSop1(opcode, 11, InlineU32(0)));
|
||||||
|
code.push_back(EncodeSop1(opcode, 12, InlineU32(64)));
|
||||||
|
code.push_back(EncodeSop1(opcode, 13, 193)); // Inline -1.
|
||||||
|
code.push_back(EncodeSMovB32(14, 253));
|
||||||
|
const u32 expected[] = {extended, 0, 64, 0xffffffffu, scc ? 1u : 0u};
|
||||||
|
for (u32 word = 0; word < 5u; ++word) {
|
||||||
|
AppendStoreSgpr(&code, 10u + word, test.expected.size());
|
||||||
|
test.expected.push_back(expected[word]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppendEnd(&code);
|
||||||
|
test.initial.resize(test.expected.size());
|
||||||
|
test.opcodes = {O::S_CMP_EQ_U32, O::S_SEXT_I32_I8, O::S_SEXT_I32_I16,
|
||||||
|
O::S_MOV_B32, O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
|
test.decoded_counts = {{"S_SEXT_I32_I8", 10u}, {"S_SEXT_I32_I16", 10u}};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase ScalarBrevB64OperandsAndMasks(u32 wave_size) {
|
TestCase ScalarBrevB64OperandsAndMasks(u32 wave_size) {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
TestCase test;
|
TestCase test;
|
||||||
@@ -35779,7 +35821,11 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ScalarBitcmpB64DynamicOperands);
|
AddCase(ScalarBitcmpB64DynamicOperands);
|
||||||
AddCase(ScalarBitcmpB64IntegerConstants);
|
AddCase(ScalarBitcmpB64IntegerConstants);
|
||||||
AddCase(ScalarBrevB32PreservesScc);
|
AddCase(ScalarBrevB32PreservesScc);
|
||||||
AddCase(ScalarSextI16Captured);
|
for (const u32 bits : {8u, 16u}) {
|
||||||
|
cases.push_back(ScalarSextMasks(bits, 32));
|
||||||
|
cases.push_back(ScalarSextMasks(bits, 64));
|
||||||
|
}
|
||||||
|
AddCase(ScalarSextConstantsAndAliases);
|
||||||
cases.push_back(ScalarBrevB64OperandsAndMasks(32));
|
cases.push_back(ScalarBrevB64OperandsAndMasks(32));
|
||||||
cases.push_back(ScalarBrevB64OperandsAndMasks(64));
|
cases.push_back(ScalarBrevB64OperandsAndMasks(64));
|
||||||
AddCase(ScalarBfeI32CapturedRawSignExtends);
|
AddCase(ScalarBfeI32CapturedRawSignExtends);
|
||||||
@@ -41524,7 +41570,11 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--scalar-sext-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--scalar-sext-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, ScalarSextI16Captured());
|
for (const u32 bits : {8u, 16u}) {
|
||||||
|
RunCase(&vulkan, ScalarSextMasks(bits, 32));
|
||||||
|
RunCase(&vulkan, ScalarSextMasks(bits, 64));
|
||||||
|
}
|
||||||
|
RunCase(&vulkan, ScalarSextConstantsAndAliases());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--flat-d16-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--flat-d16-only") == 0) {
|
||||||
|
|||||||
Reference in new issue
Block a user