mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
shader: allow SDWA byte destinations for bitwise VOP2 ops
This commit is contained in:
@@ -997,7 +997,8 @@ constexpr Vop2SdwaRule VOP2_SDWA_RULES[] = {
|
|||||||
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false},
|
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false},
|
||||||
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
||||||
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
{SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), false, false},
|
||||||
{SdwaSelWords() | SdwaSelFull(), SdwaSelAll(), SdwaSelAll(), true, false},
|
// Bitwise: WriteRawU32 inserts a byte or word destination like any other partial write.
|
||||||
|
{SdwaSelAll(), SdwaSelAll(), SdwaSelAll(), true, false},
|
||||||
};
|
};
|
||||||
static_assert(sizeof(VOP2_SDWA_RULES) / sizeof(VOP2_SDWA_RULES[0]) ==
|
static_assert(sizeof(VOP2_SDWA_RULES) / sizeof(VOP2_SDWA_RULES[0]) ==
|
||||||
static_cast<size_t>(Vop2SdwaProfile::Count));
|
static_cast<size_t>(Vop2SdwaProfile::Count));
|
||||||
|
|||||||
@@ -22142,6 +22142,75 @@ TestCase Vop1SdwaNotPartialSourcesAndDestinations() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase Vop2SdwaBitwiseByteDestinations(u32 wave_size) {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
// Low result bytes of AND, OR, XOR, XNOR for the two runtime inputs.
|
||||||
|
constexpr std::array<u32, 4> result_bytes{0xa4u, 0xbeu, 0x1au, 0xe5u};
|
||||||
|
constexpr std::array<u32, 4> alias_expected{
|
||||||
|
0xc350e5a6u, 0xc3fce5a6u, 0xc3ace5a6u, 0xc353e5a6u};
|
||||||
|
constexpr u32 sentinel = 0xa1b2c3d4u;
|
||||||
|
TestCase test;
|
||||||
|
test.name = wave_size == 64 ? "Vop2SdwaBitwiseByteDestinationsWave64"
|
||||||
|
: "Vop2SdwaBitwiseByteDestinationsWave32";
|
||||||
|
test.initial = {0xc3d4e5a6u, 0x9b785abcu};
|
||||||
|
test.expected = test.initial;
|
||||||
|
auto &code = test.code;
|
||||||
|
const auto store = [&](u32 reg, u32 expected) {
|
||||||
|
AppendStoreVgpr(&code, reg, static_cast<u32>(test.expected.size()));
|
||||||
|
test.expected.push_back(expected);
|
||||||
|
};
|
||||||
|
for (u32 op = 0; op < 4; ++op) {
|
||||||
|
AppendVMovU32(&code, 30, 0);
|
||||||
|
AppendBufferLoadDword(&code, 12, 30);
|
||||||
|
AppendVMovU32(&code, 30, 4);
|
||||||
|
AppendBufferLoadDword(&code, 13, 30);
|
||||||
|
for (u32 selector = 0; selector < 4; ++selector) {
|
||||||
|
for (u32 unused = 0; unused < 3; ++unused) {
|
||||||
|
AppendVMovLiteral(&code, 26, sentinel);
|
||||||
|
code.push_back(EncodeVop2(0x1b + op, 26, 249, 13));
|
||||||
|
code.push_back(EncodeVop2Sdwa(12, selector, unused));
|
||||||
|
// RDNA2 table 88: pad, sign extend above/zero below, or preserve.
|
||||||
|
const u32 shift = selector * 8u;
|
||||||
|
u32 expected = result_bytes[op] << shift;
|
||||||
|
if (unused == 1 && (result_bytes[op] & 0x80u) != 0) {
|
||||||
|
expected = (0xffffff00u | result_bytes[op]) << shift;
|
||||||
|
} else if (unused == 2) {
|
||||||
|
expected |= sentinel & ~(0xffu << shift);
|
||||||
|
}
|
||||||
|
store(26, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Read source byte2 and word1 before overwriting source0's byte2.
|
||||||
|
code.push_back(EncodeVop2(0x1b + op, 12, 249, 13));
|
||||||
|
code.push_back(EncodeVop2Sdwa(12, 2, 2, 2, 5));
|
||||||
|
store(12, alias_expected[op]);
|
||||||
|
// Source1 may also alias the destination.
|
||||||
|
AppendVMovU32(&code, 30, 0);
|
||||||
|
AppendBufferLoadDword(&code, 12, 30);
|
||||||
|
code.push_back(EncodeVop2(0x1b + op, 13, 249, 13));
|
||||||
|
code.push_back(EncodeVop2Sdwa(12, 1, 2));
|
||||||
|
store(13, 0x9b7800bcu | (result_bytes[op] << 8u));
|
||||||
|
for (u32 unused = 0; unused < 3; ++unused) {
|
||||||
|
AppendVMovLiteral(&code, 26, sentinel);
|
||||||
|
code.push_back(EncodeSMovB32(126, InlineU32(0)));
|
||||||
|
code.push_back(EncodeVop2(0x1b + op, 26, 249, 13));
|
||||||
|
code.push_back(EncodeVop2Sdwa(12, 2, unused));
|
||||||
|
code.push_back(EncodeSMovB32(126, InlineU32(1)));
|
||||||
|
store(26, sentinel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppendEnd(&code);
|
||||||
|
test.initial.resize(test.expected.size());
|
||||||
|
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::BUFFER_LOAD_DWORD,
|
||||||
|
O::V_AND_B32, O::V_OR_B32, O::V_XOR_B32, O::V_XNOR_B32,
|
||||||
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
|
test.required_spirv = {"OpBitwiseAnd", "OpBitwiseOr", "OpBitwiseXor", "OpNot",
|
||||||
|
"OpBitFieldInsert", "OpBitFieldSExtract"};
|
||||||
|
test.compute_info.wave_size = wave_size;
|
||||||
|
test.has_compute_info = true;
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase Vop1SdwaMovByteDestinations() {
|
TestCase Vop1SdwaMovByteDestinations() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -36334,6 +36403,8 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(Vop1SdwaNotCapturedByte0Source);
|
AddCase(Vop1SdwaNotCapturedByte0Source);
|
||||||
AddCase(Vop1SdwaNotPreservesHighWordDestination);
|
AddCase(Vop1SdwaNotPreservesHighWordDestination);
|
||||||
AddCase(Vop1SdwaNotPartialSourcesAndDestinations);
|
AddCase(Vop1SdwaNotPartialSourcesAndDestinations);
|
||||||
|
cases.push_back(Vop2SdwaBitwiseByteDestinations(32));
|
||||||
|
cases.push_back(Vop2SdwaBitwiseByteDestinations(64));
|
||||||
AddCase(Vop1SdwaMovByteDestinations);
|
AddCase(Vop1SdwaMovByteDestinations);
|
||||||
cases.push_back(Vop1SdwaMovByteSources(32));
|
cases.push_back(Vop1SdwaMovByteSources(32));
|
||||||
cases.push_back(Vop1SdwaMovByteSources(64));
|
cases.push_back(Vop1SdwaMovByteSources(64));
|
||||||
@@ -42415,6 +42486,13 @@ int main(int argc, char **argv) {
|
|||||||
RunCase(&vulkan, ScalarZeroShiftWithRuntimeCount());
|
RunCase(&vulkan, ScalarZeroShiftWithRuntimeCount());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (argc == 2 && std::strcmp(argv[1], "--sdwa-bitwise-only") == 0) {
|
||||||
|
VulkanHarness vulkan;
|
||||||
|
RunCase(&vulkan, Vop2SdwaBitwiseByteDestinations(32));
|
||||||
|
RunCase(&vulkan, Vop2SdwaBitwiseByteDestinations(64));
|
||||||
|
RunCase(&vulkan, Vop1SdwaNotPartialSourcesAndDestinations());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--sdwa-mov-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--sdwa-mov-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, Vop1SdwaMovByteDestinations());
|
RunCase(&vulkan, Vop1SdwaMovByteDestinations());
|
||||||
|
|||||||
Reference in New Issue
Block a user