mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: implement RDNA2 double-precision fractional part
This commit is contained in:
@@ -17774,6 +17774,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
||||
case Opcode::V_CVT_F64_F32:
|
||||
case Opcode::V_CVT_F64_U32:
|
||||
case Opcode::V_RCP_F64:
|
||||
case Opcode::V_FRACT_F64:
|
||||
case Opcode::V_MUL_F64:
|
||||
case Opcode::V_FMA_F64:
|
||||
case Opcode::V_CVT_F32_I32:
|
||||
@@ -23693,6 +23694,67 @@ TestCase VectorF64CapturedScreenSpaceShadows() {
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorFractF64CapturedAndEdges() {
|
||||
using O = ShaderOpcode;
|
||||
constexpr std::array<std::array<uint64_t, 2>, 17> cases{{
|
||||
{0x400a000000000000ull, 0x3fd0000000000000ull}, // 3.25 -> .25
|
||||
{0xbff4000000000000ull, 0x3fe8000000000000ull}, // -1.25 -> .75
|
||||
{0x3ff0000000000001ull, 0x3cb0000000000000ull}, // 1 + 2^-52
|
||||
{0xbff0000000000001ull, 0x3feffffffffffffeull},
|
||||
{0x4320000000000001ull, 0x3fe0000000000000ull}, // 2^51 + .5
|
||||
{0, 0}, {0x8000000000000000ull, 0},
|
||||
{0x401c000000000000ull, 0}, {0xc01c000000000000ull, 0},
|
||||
{1, 1}, {0x8000000000000001ull, 0x3ff0000000000000ull},
|
||||
{0x000fffffffffffffull, 0x000fffffffffffffull},
|
||||
{0x7fefffffffffffffull, 0},
|
||||
{0x7ff0000000000000ull, 0x7ff8000000000000ull},
|
||||
{0xfff0000000000000ull, 0x7ff8000000000000ull},
|
||||
{0x7ff8123456789abcull, 0x7ff8000000000000ull},
|
||||
{0x7ff0000000000001ull, 0x7ff8000000000000ull}}};
|
||||
TestCase test;
|
||||
test.name = "VectorFractF64CapturedAndEdges";
|
||||
const auto store_pair = [&](u32 reg, uint64_t expected) {
|
||||
const auto index = static_cast<u32>(test.expected.size());
|
||||
AppendStoreVgpr(&test.code, reg, index);
|
||||
AppendStoreVgpr(&test.code, reg + 1, index + 1);
|
||||
test.expected.insert(test.expected.end(), {u32(expected), u32(expected >> 32)});
|
||||
};
|
||||
for (u32 i = 0; i < cases.size(); i++) {
|
||||
const auto [source, expected] = cases[i];
|
||||
test.initial.insert(test.initial.end(), {u32(source), u32(source >> 32)});
|
||||
for (u32 word = 0; word < 2; word++) {
|
||||
AppendVMovU32(&test.code, 30, (i * 2 + word) * 4);
|
||||
AppendBufferLoadDword(&test.code, 4 + word, 30);
|
||||
}
|
||||
test.code.push_back(0x7e087d04u); // Captured v_fract_f64 v[4:5], v[4:5].
|
||||
if ((source & 0x7ff0000000000000ull) == 0x7ff0000000000000ull) {
|
||||
// Classify quiet NaNs without requiring a particular payload or sign.
|
||||
AppendVMovU32(&test.code, 4, 0);
|
||||
AppendVMovLiteral(&test.code, 6, 0x7ff80000u);
|
||||
test.code.push_back(EncodeVop2(0x1b, 5, Vgpr(6), 5));
|
||||
}
|
||||
store_pair(4, expected);
|
||||
}
|
||||
AppendVMovU32(&test.code, 1, 0);
|
||||
AppendVMovLiteral(&test.code, 2, 0xbff40000u);
|
||||
AppendVop3(&test.code, 0x1be, 1, Vgpr(1), 0, 0, 1, 0, false, 0, 1);
|
||||
store_pair(1, 0x3fe8000000000000ull); // Odd pair; ABS precedes NEG.
|
||||
AppendVMovU32(&test.code, 4, 1);
|
||||
AppendVMovLiteral(&test.code, 5, 0x3ff00000u);
|
||||
test.code.push_back(EncodeSop1(0x04, 12, 126));
|
||||
test.code.push_back(EncodeSop1(0x04, 126, InlineU32(0)));
|
||||
test.code.push_back(0x7e087d04u);
|
||||
test.code.push_back(EncodeSop1(0x04, 126, 12));
|
||||
store_pair(4, 0x3ff0000000000001ull); // Both words survive inactive EXEC.
|
||||
AppendEnd(&test.code);
|
||||
test.initial.resize(test.expected.size());
|
||||
test.opcodes = {O::V_MOV_B32, O::BUFFER_LOAD_DWORD, O::V_FRACT_F64,
|
||||
O::V_AND_B32, O::S_MOV_B64, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.decoded_counts = {{"V_FRACT_F64 v4, v4", cases.size() + 1}};
|
||||
test.required_spirv = {"OpCapability Float64", "OpTypeFloat 64", "Fract"};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorF64WideningConversions() {
|
||||
using O = ShaderOpcode;
|
||||
TestCase test;
|
||||
@@ -32493,6 +32555,7 @@ std::vector<TestCase> MakeCases() {
|
||||
cases.push_back(VectorCompareF64WaveMasks(32));
|
||||
cases.push_back(VectorCompareF64WaveMasks(64));
|
||||
AddCase(VectorF64CapturedScreenSpaceShadows);
|
||||
AddCase(VectorFractF64CapturedAndEdges);
|
||||
AddCase(VectorF64ModesModifiersAndExec);
|
||||
AddCase(VectorF64WideningConversions);
|
||||
AddCase(VectorSinCosMaxFiniteSpecialCases);
|
||||
@@ -37596,6 +37659,7 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, VectorCompareF64WaveMasks(32));
|
||||
RunCase(&vulkan, VectorCompareF64WaveMasks(64));
|
||||
RunCase(&vulkan, VectorF64CapturedScreenSpaceShadows());
|
||||
RunCase(&vulkan, VectorFractF64CapturedAndEdges());
|
||||
RunCase(&vulkan, VectorF64ModesModifiersAndExec());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3579,6 +3579,27 @@ void TestNewShaderRecompilerCapturedVop1SdwaByteConvert() {
|
||||
"V_CVT_F16_U16 accepted unimplemented SDWA byte sign extension");
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerCapturedFractF64() {
|
||||
using namespace ShaderRecompiler::Decoder;
|
||||
const uint32_t captured[] = {0x7e087d04u};
|
||||
Instruction decoded;
|
||||
DecodeInstruction(captured, 0, decoded);
|
||||
Check(decoded.family == Family::VOP1 && decoded.opcode == Opcode::V_FRACT_F64 &&
|
||||
decoded.opcode_id == 0x3e && decoded.word_count == 1 &&
|
||||
decoded.dst.kind == OperandKind::Vgpr && decoded.dst.reg == 4 &&
|
||||
decoded.src0.kind == OperandKind::Vgpr && decoded.src0.reg == 4,
|
||||
"captured V_FRACT_F64 did not decode its in-place register pair");
|
||||
for (const uint32_t opcode : {0x3eu, 0x2fu}) {
|
||||
for (const uint32_t source : {249u, 250u}) {
|
||||
const uint32_t invalid[] = {EncodeVop1(opcode, 4, source),
|
||||
source == 249u ? 0x00060604u : EncodeVop1Dpp(4, 0xe4)};
|
||||
DecodeInstruction(invalid, 0, decoded);
|
||||
Check(decoded.opcode == Opcode::UNSUPPORTED,
|
||||
"FP64 VOP1 accepted an unsupported SDWA or DPP encoding");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerVop1SdwaBfrev() {
|
||||
using namespace ShaderRecompiler::Decoder;
|
||||
const uint32_t captured[] = {0x7e0070f9u, 0x00040600u};
|
||||
@@ -14567,6 +14588,7 @@ int main() {
|
||||
TestNewShaderRecompilerDsReadWrite2Translation();
|
||||
TestNewShaderRecompilerDsWideAndAtomicTranslation();
|
||||
TestNewShaderRecompilerCapturedVop1SdwaByteConvert();
|
||||
TestNewShaderRecompilerCapturedFractF64();
|
||||
TestNewShaderRecompilerVop1SdwaBfrev();
|
||||
TestNewShaderRecompilerVop1SdwaNotDestination();
|
||||
TestNewShaderRecompilerScalarMemoryBindingDomains();
|
||||
|
||||
Reference in New Issue
Block a user