mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 06:16:55 +01:00
shader: support high products of 24-bit integers
This commit is contained in:
@@ -26425,6 +26425,102 @@ TestCase Vop2SdwaMinI32CapturedByte0(u32 wave_size) {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorMulHi24(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
namespace D = ShaderRecompiler::Decoder;
|
||||
constexpr std::array<u32, 8> lhs{0x7f7fffffu, 0xa5800000u, 0x12ffffffu, 0xab000000u,
|
||||
0x00010000u, 0xffabcdefu, 0x80000001u, 0x7fffffffu};
|
||||
constexpr std::array<u32, 8> rhs{0x00800000u, 0xcd800000u, 0x55000001u, 0x99ffffffu,
|
||||
0xab010000u, 0x00ffffffu, 0xfffffffeu, 0xffffffffu};
|
||||
TestCase test;
|
||||
test.name = wave_size == 32 ? "VectorMulHi24Wave32" : "VectorMulHi24Wave64";
|
||||
for (u32 lane = 0; lane < wave_size; ++lane) test.initial.push_back(lhs[lane % lhs.size()]);
|
||||
for (u32 lane = 0; lane < wave_size; ++lane) test.initial.push_back(rhs[lane % rhs.size()]);
|
||||
test.expected = test.initial;
|
||||
auto &code = test.code;
|
||||
code.push_back(EncodeVop2(0x1a, 30, InlineU32(2), 0));
|
||||
AppendBufferLoadDword(&code, 2, 30);
|
||||
AppendVMovU32(&code, 20, wave_size * sizeof(u32));
|
||||
code.push_back(EncodeVop2(0x25, 30, Vgpr(20), 30));
|
||||
AppendBufferLoadDword(&code, 3, 30);
|
||||
for (bool sign : {true, false}) {
|
||||
const u32 opcode = sign ? 0x0a : 0x0c;
|
||||
for (u32 modifier = 0; modifier < 13; ++modifier) {
|
||||
const u32 words[] = {
|
||||
EncodeVop3Word0(0x100 + opcode, 7, modifier < 3 ? 1u << modifier : 0,
|
||||
modifier >= 9 ? 1u << (modifier - 9) : 0),
|
||||
EncodeVop3Word1(Vgpr(5), Vgpr(6), 0,
|
||||
modifier >= 6 && modifier < 9 ? modifier - 5 : 0,
|
||||
modifier >= 3 && modifier < 6 ? 1u << (modifier - 3) : 0)};
|
||||
D::Instruction decoded;
|
||||
D::DecodeInstruction(words, 0, decoded);
|
||||
Require(test.name, "integer modifiers", decoded.opcode == O::UNSUPPORTED,
|
||||
"24-bit high multiply accepted unsupported modifiers");
|
||||
}
|
||||
for (u32 variant = 0; variant < 10; ++variant) {
|
||||
code.push_back(EncodeVop1(0x01, 5, Vgpr(2)));
|
||||
code.push_back(EncodeVop1(0x01, 6, Vgpr(3)));
|
||||
AppendVMovLiteral(&code, 7, 0xa5a5beefu);
|
||||
u32 dst = 7;
|
||||
switch (variant) {
|
||||
case 0: dst = 5; code.push_back(EncodeVop2(opcode, dst, Vgpr(5), 6)); break;
|
||||
case 1: dst = 6; AppendVop3(&code, 0x100 + opcode, dst, Vgpr(5), Vgpr(6)); break;
|
||||
case 2: AppendVop3(&code, 0x100 + opcode, dst, Vgpr(5), Vgpr(6), 0, 0, 0, true); break;
|
||||
case 3:
|
||||
code.push_back(EncodeVop2(opcode, dst, 255, 6));
|
||||
code.push_back(0x00ffffffu);
|
||||
break;
|
||||
case 4:
|
||||
AppendVop3(&code, 0x100 + opcode, dst, Vgpr(5), 255);
|
||||
code.push_back(0x00800000u);
|
||||
break;
|
||||
case 5:
|
||||
AppendSMovLiteral(&code, 20, 0xffff0001u);
|
||||
AppendVop3(&code, 0x100 + opcode, dst, Vgpr(5), 20);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
code.push_back(EncodeVop2(opcode, dst, 249, 6));
|
||||
code.push_back(EncodeVop2Sdwa(5, variant == 7 ? 5 : 6, variant == 7 ? 2 : 0,
|
||||
variant == 8 ? 4 : 6, 6, variant == 8));
|
||||
break;
|
||||
case 9:
|
||||
code.push_back(EncodeVop2(opcode, dst, 250, 6));
|
||||
code.push_back(EncodeVop2Dpp(5, 0x01b)); // Reverse each quad's source lanes.
|
||||
break;
|
||||
}
|
||||
AppendStoreVgprAtLaneDwordOffset(&code, dst, 0, static_cast<u32>(test.expected.size()));
|
||||
for (u32 lane = 0; lane < wave_size; ++lane) {
|
||||
const u32 source_lane = variant == 9 ? lane ^ 3u : lane;
|
||||
u32 a = lhs[source_lane % lhs.size()], b = rhs[lane % rhs.size()];
|
||||
if (variant == 3) a = 0x00ffffffu;
|
||||
if (variant == 4) b = 0x00800000u;
|
||||
if (variant == 5) b = 0xffff0001u;
|
||||
if (variant == 8) a = (a & 0x8000u) ? a | 0xffff0000u : a & 0xffffu;
|
||||
const auto extend24 = [sign](u32 value) -> int64_t {
|
||||
const int64_t low = value & 0x00ffffffu;
|
||||
return sign && (value & 0x00800000u) ? low - 0x01000000 : low;
|
||||
};
|
||||
const uint64_t product = static_cast<uint64_t>(extend24(a) * extend24(b));
|
||||
const u32 high = static_cast<u32>(product >> 32);
|
||||
test.expected.push_back(variant == 7 ? 0xbeefu | (high << 16) : high);
|
||||
}
|
||||
}
|
||||
}
|
||||
AppendEnd(&code);
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::V_LSHLREV_B32, O::V_ADD_NC_U32,
|
||||
O::BUFFER_LOAD_DWORD, O::V_MUL_HI_I32_I24, O::V_MUL_HI_U32_U24,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.compute_info.threads_num[0] = wave_size;
|
||||
test.compute_info.threads_num[1] = 1;
|
||||
test.compute_info.threads_num[2] = 1;
|
||||
test.compute_info.thread_ids_num = 1;
|
||||
test.has_compute_info = true;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase Vop2SdwaMulI24Destinations(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
constexpr std::array<u32, 5> sources{
|
||||
@@ -46282,6 +46378,8 @@ std::vector<TestCase> MakeCases() {
|
||||
cases.push_back(Vop2SdwaMaxI32CapturedHighWord(64));
|
||||
cases.push_back(Vop2SdwaMinI32CapturedByte0(32));
|
||||
cases.push_back(Vop2SdwaMinI32CapturedByte0(64));
|
||||
cases.push_back(VectorMulHi24(32));
|
||||
cases.push_back(VectorMulHi24(64));
|
||||
cases.push_back(Vop2SdwaMulI24Destinations(32));
|
||||
cases.push_back(Vop2SdwaMulI24Destinations(64));
|
||||
cases.push_back(Vop2SdwaMulU24Destinations(32));
|
||||
@@ -52727,6 +52825,17 @@ int main(int argc, char **argv) {
|
||||
std::setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
EnsureConfigInitialized();
|
||||
CheckLeastRecentlyUsedCacheOrdering();
|
||||
if (argc == 2 && std::strcmp(argv[1], "--mul-hi24-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, VectorMulHi24(32));
|
||||
RunCase(&vulkan, VectorMulHi24(64));
|
||||
RunCase(&vulkan, Vop2SdwaMulI24Destinations(32));
|
||||
RunCase(&vulkan, Vop2SdwaMulI24Destinations(64));
|
||||
RunCase(&vulkan, Vop2SdwaMulU24Destinations(32));
|
||||
RunCase(&vulkan, Vop2SdwaMulU24Destinations(64));
|
||||
RunCase(&vulkan, VectorVop3IntegerOps());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--mad-u16-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, Vop3MadU16(32));
|
||||
|
||||
Reference in New Issue
Block a user