mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
shader: decode v_cmp_class_f16
This commit is contained in:
@@ -401,6 +401,7 @@ enum class Opcode {
|
|||||||
V_CMP_T_I32,
|
V_CMP_T_I32,
|
||||||
V_CMP_CLASS_F32,
|
V_CMP_CLASS_F32,
|
||||||
V_CMPX_CLASS_F32,
|
V_CMPX_CLASS_F32,
|
||||||
|
V_CMP_CLASS_F16,
|
||||||
V_CMPX_CLASS_F16,
|
V_CMPX_CLASS_F16,
|
||||||
V_CMP_LT_I16,
|
V_CMP_LT_I16,
|
||||||
V_CMP_EQ_I16,
|
V_CMP_EQ_I16,
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
|||||||
{0x88u, Opcode::V_CMP_CLASS_F32}, {0x89u, Opcode::V_CMP_LT_I16},
|
{0x88u, Opcode::V_CMP_CLASS_F32}, {0x89u, Opcode::V_CMP_LT_I16},
|
||||||
{0x8au, Opcode::V_CMP_EQ_I16}, {0x8bu, Opcode::V_CMP_LE_I16},
|
{0x8au, Opcode::V_CMP_EQ_I16}, {0x8bu, Opcode::V_CMP_LE_I16},
|
||||||
{0x8cu, Opcode::V_CMP_GT_I16}, {0x8du, Opcode::V_CMP_NE_I16},
|
{0x8cu, Opcode::V_CMP_GT_I16}, {0x8du, Opcode::V_CMP_NE_I16},
|
||||||
{0x8eu, Opcode::V_CMP_GE_I16}, {0x91u, Opcode::V_CMPX_LT_I32},
|
{0x8eu, Opcode::V_CMP_GE_I16}, {0x8fu, Opcode::V_CMP_CLASS_F16, false},
|
||||||
|
{0x91u, Opcode::V_CMPX_LT_I32},
|
||||||
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
||||||
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
||||||
{0x96u, Opcode::V_CMPX_GE_I32}, {0x98u, Opcode::V_CMPX_CLASS_F32},
|
{0x96u, Opcode::V_CMPX_GE_I32}, {0x98u, Opcode::V_CMPX_CLASS_F32},
|
||||||
@@ -929,6 +930,7 @@ bool IsVopcFloatCompareOpcode(Opcode opcode) {
|
|||||||
case Opcode::V_CMPX_NEQ_F16:
|
case Opcode::V_CMPX_NEQ_F16:
|
||||||
case Opcode::V_CMPX_NLT_F16:
|
case Opcode::V_CMPX_NLT_F16:
|
||||||
case Opcode::V_CMP_CLASS_F32:
|
case Opcode::V_CMP_CLASS_F32:
|
||||||
|
case Opcode::V_CMP_CLASS_F16:
|
||||||
case Opcode::V_CMPX_CLASS_F16:
|
case Opcode::V_CMPX_CLASS_F16:
|
||||||
case Opcode::V_CMPX_CLASS_F32: return true;
|
case Opcode::V_CMPX_CLASS_F32: return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
|||||||
case O::V_CMPX_U_F32: EmitFloatOrderedCompare(inst, false, true); return;
|
case O::V_CMPX_U_F32: EmitFloatOrderedCompare(inst, false, true); return;
|
||||||
case O::V_CMP_CLASS_F32: EmitFloatClassCompare(inst, false); return;
|
case O::V_CMP_CLASS_F32: EmitFloatClassCompare(inst, false); return;
|
||||||
case O::V_CMPX_CLASS_F32: EmitFloatClassCompare(inst, true); return;
|
case O::V_CMPX_CLASS_F32: EmitFloatClassCompare(inst, true); return;
|
||||||
|
case O::V_CMP_CLASS_F16: EmitFloatClassCompare(inst, false, true); return;
|
||||||
case O::V_CMPX_CLASS_F16: EmitFloatClassCompare(inst, true, true); return;
|
case O::V_CMPX_CLASS_F16: EmitFloatClassCompare(inst, true, true); return;
|
||||||
|
|
||||||
case O::V_CVT_F32_UBYTE0: V_CVT_F32_UBYTE(inst, 0); return;
|
case O::V_CVT_F32_UBYTE0: V_CVT_F32_UBYTE(inst, 0); return;
|
||||||
|
|||||||
@@ -19073,6 +19073,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
|||||||
case Opcode::V_CMPX_NLT_F32:
|
case Opcode::V_CMPX_NLT_F32:
|
||||||
case Opcode::V_CMP_CLASS_F32:
|
case Opcode::V_CMP_CLASS_F32:
|
||||||
case Opcode::V_CMPX_CLASS_F32:
|
case Opcode::V_CMPX_CLASS_F32:
|
||||||
|
case Opcode::V_CMP_CLASS_F16:
|
||||||
case Opcode::V_CMPX_CLASS_F16:
|
case Opcode::V_CMPX_CLASS_F16:
|
||||||
case Opcode::V_CMP_LT_F16:
|
case Opcode::V_CMP_LT_F16:
|
||||||
case Opcode::V_CMP_EQ_F16:
|
case Opcode::V_CMP_EQ_F16:
|
||||||
@@ -26468,6 +26469,79 @@ TestCase VectorVopcSdwaCmpxClassF32CapturedExecMask() {
|
|||||||
return test;
|
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) {
|
TestCase VectorCmpxClassF16(u32 wave_size) {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
// One raw half value for each architectural class bit, in bit order.
|
// One raw half value for each architectural class bit, in bit order.
|
||||||
@@ -35978,6 +36052,8 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
||||||
AddCase(VectorCompareClassF32);
|
AddCase(VectorCompareClassF32);
|
||||||
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
|
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
|
||||||
|
cases.push_back(VectorCmpClassF16(32));
|
||||||
|
cases.push_back(VectorCmpClassF16(64));
|
||||||
cases.push_back(VectorCmpxClassF16(32));
|
cases.push_back(VectorCmpxClassF16(32));
|
||||||
cases.push_back(VectorCmpxClassF16(64));
|
cases.push_back(VectorCmpxClassF16(64));
|
||||||
AddCase(VectorCompareF16Ops);
|
AddCase(VectorCompareF16Ops);
|
||||||
@@ -41474,6 +41550,14 @@ int main(int argc, char **argv) {
|
|||||||
RunCase(&vulkan, VectorVopcSdwaCmpxClassF32CapturedExecMask());
|
RunCase(&vulkan, VectorVopcSdwaCmpxClassF32CapturedExecMask());
|
||||||
return 0;
|
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) {
|
if (argc == 2 && std::strcmp(argv[1], "--cmpx-class-f16-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, VectorCmpxClassF16(32));
|
RunCase(&vulkan, VectorCmpxClassF16(32));
|
||||||
|
|||||||
Reference in New Issue
Block a user