mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: decode v_cmp_class_f16
This commit is contained in:
@@ -19073,6 +19073,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
||||
case Opcode::V_CMPX_NLT_F32:
|
||||
case Opcode::V_CMP_CLASS_F32:
|
||||
case Opcode::V_CMPX_CLASS_F32:
|
||||
case Opcode::V_CMP_CLASS_F16:
|
||||
case Opcode::V_CMPX_CLASS_F16:
|
||||
case Opcode::V_CMP_LT_F16:
|
||||
case Opcode::V_CMP_EQ_F16:
|
||||
@@ -26468,6 +26469,79 @@ TestCase VectorVopcSdwaCmpxClassF32CapturedExecMask() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorCmpClassF16(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
constexpr std::array<u32, 10> values{
|
||||
0x7c01u, 0x7e01u, 0xfc00u, 0xbc00u, 0x8001u,
|
||||
0x8000u, 0x0000u, 0x0001u, 0x3c00u, 0x7c00u};
|
||||
constexpr u32 guard = 0x87654321u;
|
||||
TestCase test;
|
||||
test.name = wave_size == 64 ? "VectorCmpClassF16Wave64" : "VectorCmpClassF16Wave32";
|
||||
for (const auto value : values) {
|
||||
test.initial.insert(test.initial.end(), {0xa55a0000u | value, (value << 16u) | 0x7e01u});
|
||||
}
|
||||
test.expected = test.initial;
|
||||
auto &code = test.code;
|
||||
const auto compare = [&](std::initializer_list<u32> words, u32 expected,
|
||||
u32 dst = 106u, u32 exec = 1u) {
|
||||
AppendSMovLiteral(&code, 106, 0x12345678u);
|
||||
AppendSMovLiteral(&code, 107, guard);
|
||||
AppendSMovLiteral(&code, dst + 1u, guard);
|
||||
code.push_back(EncodeSopc(0x06, InlineU32(expected), InlineU32(0)));
|
||||
code.insert(code.end(), words);
|
||||
const u32 sources[] = {dst, dst + 1u, 126, 127, 253};
|
||||
for (u32 i = 0; i < std::size(sources); ++i) {
|
||||
code.push_back(EncodeSMovB32(30u + i, sources[i]));
|
||||
}
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(1)));
|
||||
const u32 results[] = {expected, wave_size == 32 ? guard : 0u, exec, 0u, 1u - expected};
|
||||
for (u32 i = 0; i < std::size(results); ++i) {
|
||||
AppendStoreSgpr(&code, 30u + i, static_cast<u32>(test.expected.size()));
|
||||
test.expected.push_back(results[i]);
|
||||
}
|
||||
if (dst != 106u) {
|
||||
AppendStoreSgpr(&code, 106, static_cast<u32>(test.expected.size()));
|
||||
AppendStoreSgpr(&code, 107, static_cast<u32>(test.expected.size()) + 1u);
|
||||
test.expected.insert(test.expected.end(), {0x12345678u, guard});
|
||||
}
|
||||
};
|
||||
for (u32 index = 0; index < values.size(); ++index) {
|
||||
AppendVMovU32(&code, 30, index * 8u);
|
||||
AppendBufferLoadDword(&code, 0, 30);
|
||||
AppendVMovU32(&code, 30, index * 8u + 4u);
|
||||
AppendBufferLoadDword(&code, 2, 30);
|
||||
for (u32 bit = 0; bit < 12; ++bit) {
|
||||
AppendVMovU32(&code, 1, bit == 11 ? 0 : 1u << bit);
|
||||
const u32 expected = bit == index ? 1u : 0u;
|
||||
compare({EncodeVopc(0x8f, Vgpr(0), 1)}, expected);
|
||||
compare({EncodeVop3Word0(0x8f, 20), EncodeVop3Word1(Vgpr(0), Vgpr(1))},
|
||||
expected, 20);
|
||||
}
|
||||
// SDWA selects the high half, applies -abs, and writes an explicit SGPR pair.
|
||||
compare({EncodeVopc(0x8f, 249, InlineU32(56)),
|
||||
EncodeVopcSdwa(2, 20, 1, 5, 6, 0, 0, 1, 1, 0, 0, 0, 1)},
|
||||
index >= 3 && index <= 8 ? 1u : 0u, 20);
|
||||
compare({EncodeVop3Word0(0x8f, 20, 1),
|
||||
EncodeVop3Word1(Vgpr(0), InlineU32(56), 0, 0, 1)},
|
||||
index >= 3 && index <= 8 ? 1u : 0u, 20);
|
||||
}
|
||||
AppendVMovU32(&code, 1, 1u << 8u);
|
||||
compare({EncodeVopc(0x8f, 242, 1)}, 1); // Inline 1.0 becomes half 0x3c00.
|
||||
compare({EncodeVopc(0x8f, 255, 1), 0xdead3c00u}, 1); // Literal low half.
|
||||
compare({EncodeVop3Word0(0x8f, 20), EncodeVop3Word1(242, 248)}, 1, 20);
|
||||
// Inline INV_2PI supplies half bits 0x3118, including the positive-normal class.
|
||||
code.push_back(EncodeSMovB32(126, InlineU32(0)));
|
||||
compare({EncodeVopc(0x8f, 242, 1)}, 0, 106, 0); // Inactive lanes clear the result.
|
||||
AppendEnd(&code);
|
||||
test.initial.resize(test.expected.size());
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::S_CMP_EQ_U32, O::BUFFER_LOAD_DWORD,
|
||||
O::V_CMP_CLASS_F16, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.decoded_counts = {{"V_CMP_CLASS_F16", 264u}};
|
||||
test.compute_info.wave_size = wave_size;
|
||||
test.has_compute_info = true;
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorCmpxClassF16(u32 wave_size) {
|
||||
using O = ShaderOpcode;
|
||||
// One raw half value for each architectural class bit, in bit order.
|
||||
@@ -35978,6 +36052,8 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
||||
AddCase(VectorCompareClassF32);
|
||||
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
|
||||
cases.push_back(VectorCmpClassF16(32));
|
||||
cases.push_back(VectorCmpClassF16(64));
|
||||
cases.push_back(VectorCmpxClassF16(32));
|
||||
cases.push_back(VectorCmpxClassF16(64));
|
||||
AddCase(VectorCompareF16Ops);
|
||||
@@ -41474,6 +41550,14 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, VectorVopcSdwaCmpxClassF32CapturedExecMask());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--class-f16-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, VectorCmpClassF16(32));
|
||||
RunCase(&vulkan, VectorCmpClassF16(64));
|
||||
RunCase(&vulkan, VectorCmpxClassF16(32));
|
||||
RunCase(&vulkan, VectorCmpxClassF16(64));
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--cmpx-class-f16-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
RunCase(&vulkan, VectorCmpxClassF16(32));
|
||||
|
||||
Reference in New Issue
Block a user