mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
shader: fold exact float class masks into native NaN predicates
This commit is contained in:
@@ -263,10 +263,6 @@ uint32_t EmitUMedTri32(EmitterState& state, uint32_t arg0, uint32_t arg1, uint32
|
|||||||
return EmitUMax32(state, EmitUMin32(state, arg0, arg1), high_min);
|
return EmitUMax32(state, EmitUMin32(state, arg0, arg1), high_min);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t EmitFPIsNan32(EmitterState& state, uint32_t arg0) {
|
|
||||||
return EmitNative<spv::OpFUnordNotEqual, IR::Type::U1>(state, arg0, arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t EmitFPMin32(EmitterState& state, uint32_t arg0, uint32_t arg1) {
|
uint32_t EmitFPMin32(EmitterState& state, uint32_t arg0, uint32_t arg1) {
|
||||||
return EmitMinMaxF32Value(state, arg0, arg1, false);
|
return EmitMinMaxF32Value(state, arg0, arg1, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ inline constexpr auto EmitFPOrdLessThanEqual32 = EmitFloatCompare32<spv::OpFOrdL
|
|||||||
inline constexpr auto EmitFPUnordLessThanEqual32 = EmitFloatCompare32<spv::OpFUnordLessThanEqual>;
|
inline constexpr auto EmitFPUnordLessThanEqual32 = EmitFloatCompare32<spv::OpFUnordLessThanEqual>;
|
||||||
inline constexpr auto EmitFPOrdGreaterThanEqual32 = EmitFloatCompare32<spv::OpFOrdGreaterThanEqual>;
|
inline constexpr auto EmitFPOrdGreaterThanEqual32 = EmitFloatCompare32<spv::OpFOrdGreaterThanEqual>;
|
||||||
inline constexpr auto EmitFPUnordGreaterThanEqual32 = EmitFloatCompare32<spv::OpFUnordGreaterThanEqual>;
|
inline constexpr auto EmitFPUnordGreaterThanEqual32 = EmitFloatCompare32<spv::OpFUnordGreaterThanEqual>;
|
||||||
uint32_t EmitFPIsNan32(EmitterState& state, uint32_t arg0);
|
EMIT_NATIVE(FPIsNan32, OpIsNan, U1, uint32_t)
|
||||||
inline constexpr auto EmitFPCmpClass32 = EmitClassMaskF32;
|
inline constexpr auto EmitFPCmpClass32 = EmitClassMaskF32;
|
||||||
inline constexpr auto EmitFPCmpClass16 = EmitClassMaskF16;
|
inline constexpr auto EmitFPCmpClass16 = EmitClassMaskF16;
|
||||||
EMIT_NATIVE(FPAdd32, OpFAdd, F32, uint32_t, uint32_t)
|
EMIT_NATIVE(FPAdd32, OpFAdd, F32, uint32_t, uint32_t)
|
||||||
|
|||||||
@@ -215,6 +215,24 @@ void FoldInstruction(Block& block, Block::iterator instruction,
|
|||||||
return;
|
return;
|
||||||
case ValueOpcode::SelectU32:
|
case ValueOpcode::SelectU32:
|
||||||
case ValueOpcode::SelectF32: FoldSelect(inst); return;
|
case ValueOpcode::SelectF32: FoldSelect(inst); return;
|
||||||
|
case ValueOpcode::FPCmpClass32: {
|
||||||
|
const auto mask = Arg(inst, 1);
|
||||||
|
if (!IsImmediate(mask, Type::U32)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (mask.U32() & 0x3ffu) {
|
||||||
|
case 0u: Replace(inst, Value(false)); break;
|
||||||
|
case 0x3ffu: Replace(inst, Value(true)); break;
|
||||||
|
case 3u: {
|
||||||
|
const auto result = block.PrependNewInst(
|
||||||
|
instruction, ValueOpcode::FPIsNan32, {Arg(inst, 0)});
|
||||||
|
Replace(inst, Value(&*result));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
case ValueOpcode::BitFieldInsert: {
|
case ValueOpcode::BitFieldInsert: {
|
||||||
const auto base = Arg(inst, 0);
|
const auto base = Arg(inst, 0);
|
||||||
const auto insert = Arg(inst, 1);
|
const auto insert = Arg(inst, 1);
|
||||||
|
|||||||
@@ -26812,6 +26812,48 @@ TestCase VectorCompareClassF32() {
|
|||||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase VectorCompareClassF32ImmediateAndDynamicMasks() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
// One input for each architectural class bit, in bit order.
|
||||||
|
constexpr std::array<u32, 10> values{
|
||||||
|
0x7f800001u, 0x7fc00001u, 0xff800000u, 0xbf800000u, 0x80000001u,
|
||||||
|
0x80000000u, 0x00000000u, 0x00000001u, 0x3f800000u, 0x7f800000u};
|
||||||
|
constexpr std::array<u32, 8> masks{
|
||||||
|
0u, 0x3ffu, 3u, 7u, 0xfffffc00u, 0xffffffffu, 0xfffffc03u, 0xfffffc07u};
|
||||||
|
TestCase test;
|
||||||
|
test.name = "VectorCompareClassF32ImmediateAndDynamicMasks";
|
||||||
|
test.initial.assign(values.begin(), values.end());
|
||||||
|
test.initial.insert(test.initial.end(), masks.begin(), masks.end());
|
||||||
|
test.expected = test.initial;
|
||||||
|
auto &code = test.code;
|
||||||
|
AppendVMovU32(&code, 1, 1);
|
||||||
|
for (u32 index = 0; index < values.size(); ++index) {
|
||||||
|
AppendVMovU32(&code, 30, index * 4u);
|
||||||
|
AppendBufferLoadDword(&code, 0, 30);
|
||||||
|
for (u32 mask_index = 0; mask_index < masks.size(); ++mask_index) {
|
||||||
|
for (const bool dynamic : {false, true}) {
|
||||||
|
if (dynamic) {
|
||||||
|
AppendVMovU32(&code, 30, (values.size() + mask_index) * 4u);
|
||||||
|
AppendBufferLoadDword(&code, 2, 30);
|
||||||
|
code.push_back(EncodeVopc(0x88, Vgpr(0), 2));
|
||||||
|
} else {
|
||||||
|
AppendVop3(&code, 0x88, 106, Vgpr(0), 255);
|
||||||
|
code.push_back(masks[mask_index]);
|
||||||
|
}
|
||||||
|
code.push_back(EncodeVop2(0x01, 3, InlineU32(0), 1));
|
||||||
|
AppendStoreVgpr(&code, 3, static_cast<u32>(test.expected.size()));
|
||||||
|
test.expected.push_back((masks[mask_index] & (1u << index)) != 0u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AppendEnd(&code);
|
||||||
|
test.initial.resize(test.expected.size());
|
||||||
|
test.opcodes = {O::V_MOV_B32, O::BUFFER_LOAD_DWORD, O::V_CMP_CLASS_F32,
|
||||||
|
O::V_CNDMASK_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||||
|
test.required_spirv = {"OpIsNan"};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase VectorVopcSdwaCmpxClassF32CapturedExecMask() {
|
TestCase VectorVopcSdwaCmpxClassF32CapturedExecMask() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -36518,6 +36560,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(VectorVopcCmpxNeU64CapturedExecMask);
|
AddCase(VectorVopcCmpxNeU64CapturedExecMask);
|
||||||
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
||||||
AddCase(VectorCompareClassF32);
|
AddCase(VectorCompareClassF32);
|
||||||
|
AddCase(VectorCompareClassF32ImmediateAndDynamicMasks);
|
||||||
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
|
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
|
||||||
cases.push_back(VectorCmpClassF16(32));
|
cases.push_back(VectorCmpClassF16(32));
|
||||||
cases.push_back(VectorCmpClassF16(64));
|
cases.push_back(VectorCmpClassF16(64));
|
||||||
@@ -42012,6 +42055,7 @@ int main(int argc, char **argv) {
|
|||||||
RunCase(&vulkan, VectorCompareF32DenormalModes(mode));
|
RunCase(&vulkan, VectorCompareF32DenormalModes(mode));
|
||||||
}
|
}
|
||||||
RunCase(&vulkan, VectorCompareClassF32());
|
RunCase(&vulkan, VectorCompareClassF32());
|
||||||
|
RunCase(&vulkan, VectorCompareClassF32ImmediateAndDynamicMasks());
|
||||||
RunCase(&vulkan, VectorCompareF16Ops());
|
RunCase(&vulkan, VectorCompareF16Ops());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user