mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
Shader: execute RDNA2 FP64 shadow arithmetic and log denorm limits
Shader: disable FP64 denorm preservation controls for now
This commit is contained in:
@@ -15837,6 +15837,7 @@ private:
|
||||
device_features.shaderImageGatherExtended = true;
|
||||
device_features.sampleRateShading = true;
|
||||
device_features.shaderInt64 = true;
|
||||
device_features.shaderFloat64 = available_features.shaderFloat64;
|
||||
device_features.fillModeNonSolid = true;
|
||||
device_features.tessellationShader = true;
|
||||
device_info.pEnabledFeatures = &device_features;
|
||||
@@ -16400,6 +16401,11 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
||||
case Opcode::V_MAX3_F32:
|
||||
case Opcode::V_MED3_F32:
|
||||
case Opcode::V_DOT2C_F32_F16:
|
||||
case Opcode::V_CVT_F64_I32:
|
||||
case Opcode::V_CVT_F32_F64:
|
||||
case Opcode::V_RCP_F64:
|
||||
case Opcode::V_MUL_F64:
|
||||
case Opcode::V_FMA_F64:
|
||||
case Opcode::V_CVT_F32_I32:
|
||||
case Opcode::V_CVT_F32_U32:
|
||||
case Opcode::V_CVT_U32_F32:
|
||||
@@ -21689,6 +21695,157 @@ TestCase VectorSpecialF32FlushesDenormalInputs() {
|
||||
O::V_SQRT_F32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase VectorF64CapturedScreenSpaceShadows() {
|
||||
using O = ShaderOpcode;
|
||||
TestCase test;
|
||||
test.name = "VectorF64CapturedScreenSpaceShadows";
|
||||
const auto store_pair = [&](u32 reg, double value) {
|
||||
const auto bits = std::bit_cast<uint64_t>(value);
|
||||
AppendStoreVgpr(&test.code, reg, static_cast<u32>(test.expected.size()));
|
||||
AppendStoreVgpr(&test.code, reg + 1,
|
||||
static_cast<u32>(test.expected.size() + 1));
|
||||
test.expected.insert(test.expected.end(), {static_cast<u32>(bits),
|
||||
static_cast<u32>(bits >> 32)});
|
||||
};
|
||||
for (const auto values :
|
||||
{std::array<int32_t, 3>{63, 127, 101},
|
||||
std::array<int32_t, 3>{16777217, -16777217, 123456789},
|
||||
std::array<int32_t, 3>{INT32_MIN, INT32_MAX, -31}}) {
|
||||
AppendVMovLiteral(&test.code, 7, static_cast<u32>(values[0]));
|
||||
AppendVMovLiteral(&test.code, 1, static_cast<u32>(values[1]));
|
||||
AppendVMovLiteral(&test.code, 9, static_cast<u32>(values[2]));
|
||||
// Exact FP64 instruction words from b90e2024732c6111, PCs 0xc8 through
|
||||
// 0x130.
|
||||
test.code.insert(test.code.end(), {0x7e060907u, 0x7e0a0901u, 0x7e020909u});
|
||||
store_pair(3, double(values[0]));
|
||||
store_pair(5, double(values[1]));
|
||||
store_pair(1, double(values[2]));
|
||||
test.code.push_back(0x7e065f03u);
|
||||
const double reciprocal = 1.0 / double(values[0]);
|
||||
store_pair(3, reciprocal);
|
||||
test.code.insert(test.code.end(), {0xd5650005u, 0x00020305u});
|
||||
const double product = double(values[1]) * double(values[2]);
|
||||
store_pair(5, product);
|
||||
test.code.insert(test.code.end(), {0xd54c0001u, 0x84060705u});
|
||||
const double result = std::fma(product, reciprocal, -double(values[2]));
|
||||
store_pair(1, result);
|
||||
test.code.push_back(0x7e041f01u);
|
||||
AppendStoreVgpr(&test.code, 2, static_cast<u32>(test.expected.size()));
|
||||
test.expected.push_back(std::bit_cast<u32>(static_cast<float>(result)));
|
||||
}
|
||||
AppendEnd(&test.code);
|
||||
test.opcodes = {O::V_MOV_B32, O::V_CVT_F64_I32, O::V_RCP_F64,
|
||||
O::V_MUL_F64, O::V_FMA_F64, O::V_CVT_F32_F64,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
test.required_spirv = {"OpCapability Float64",
|
||||
"OpTypeFloat 64",
|
||||
"OpFDiv",
|
||||
"Fma",
|
||||
"SignedZeroInfNanPreserve 64",
|
||||
"RoundingModeRTE 32"};
|
||||
test.ir_counts = {{"ConvertF64S32", 9},
|
||||
{"FPRecip64", 3},
|
||||
{"FPMul64", 3},
|
||||
{"FPFma64", 3},
|
||||
{"ConvertF32F64", 3}};
|
||||
|
||||
ShaderComputeInputInfo info{};
|
||||
std::vector<u32> normal_key, other_key;
|
||||
BuildStageStaticKey(info, normal_key);
|
||||
info.float_mode = 0xc4;
|
||||
BuildStageStaticKey(info, other_key);
|
||||
Require(test.name, "pipeline identity",
|
||||
normal_key != other_key && normal_key.size() == other_key.size(),
|
||||
"FP64 rounding modes must not share a compiled shader key");
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorF64ModesModifiersAndExec() {
|
||||
using O = ShaderOpcode;
|
||||
TestCase test;
|
||||
test.name = "VectorF64ModesModifiersAndExec";
|
||||
const auto load_pair = [&](u32 reg, uint64_t bits) {
|
||||
AppendVMovLiteral(&test.code, reg, static_cast<u32>(bits));
|
||||
AppendVMovLiteral(&test.code, reg + 1, static_cast<u32>(bits >> 32));
|
||||
};
|
||||
const auto store_pair = [&](u32 reg, uint64_t bits) {
|
||||
AppendStoreVgpr(&test.code, reg, static_cast<u32>(test.expected.size()));
|
||||
AppendStoreVgpr(&test.code, reg + 1,
|
||||
static_cast<u32>(test.expected.size() + 1));
|
||||
test.expected.insert(test.expected.end(), {static_cast<u32>(bits),
|
||||
static_cast<u32>(bits >> 32)});
|
||||
};
|
||||
const auto store_word = [&](u32 reg, u32 bits) {
|
||||
AppendStoreVgpr(&test.code, reg, static_cast<u32>(test.expected.size()));
|
||||
test.expected.push_back(bits);
|
||||
};
|
||||
for (const auto [source, expected] :
|
||||
{std::pair<uint64_t, uint64_t>{0, 0x7ff0000000000000ull},
|
||||
{0x8000000000000000ull, 0xfff0000000000000ull},
|
||||
{0x7ff0000000000000ull, 0},
|
||||
{0xfff0000000000000ull, 0x8000000000000000ull},
|
||||
{0x0008000000000000ull, 0x7fe0000000000000ull},
|
||||
{0x7fe0000000000000ull, 0x0008000000000000ull}}) {
|
||||
load_pair(1, source);
|
||||
test.code.push_back(EncodeVop1(0x2f, 1, Vgpr(1)));
|
||||
store_pair(1, expected);
|
||||
}
|
||||
// A fused result retains the residual that separate multiply/add would round
|
||||
// to zero.
|
||||
load_pair(1, std::bit_cast<uint64_t>(1.0 + 0x1p-27));
|
||||
load_pair(3, std::bit_cast<uint64_t>(1.0 - 0x1p-27));
|
||||
AppendVop3(&test.code, 0x14c, 1, Vgpr(1), Vgpr(3), 243u);
|
||||
store_pair(1, std::bit_cast<uint64_t>(-0x1p-54));
|
||||
// Unaligned pairs, SGPR pairs, inline floats, literal highword expansion, ABS
|
||||
// then NEG.
|
||||
test.code.push_back(EncodeSop1(0x03, 8, 255));
|
||||
test.code.push_back(0u);
|
||||
test.code.push_back(EncodeSop1(0x03, 9, 255));
|
||||
test.code.push_back(0xbff00000u);
|
||||
AppendVop3(&test.code, 0x165, 1, 8u, 244u, 0, 1, 0, false, 0, 1);
|
||||
store_pair(1, std::bit_cast<uint64_t>(-2.0));
|
||||
AppendVop3(&test.code, 0x165, 1, 255u, 242u);
|
||||
test.code.push_back(0x40080000u);
|
||||
store_pair(1, std::bit_cast<uint64_t>(3.0));
|
||||
AppendVop3(&test.code, 0x165, 1, 248u, 242u);
|
||||
store_pair(1, 0x3fc45f306dc9c882ull);
|
||||
AppendVop3(&test.code, 0x184, 1, InlineU32(3), 0);
|
||||
store_pair(1, std::bit_cast<uint64_t>(3.0));
|
||||
AppendVop3(&test.code, 0x1af, 1, 244u, 0);
|
||||
store_pair(1, std::bit_cast<uint64_t>(0.5));
|
||||
// Preserve both destination words when EXEC is clear, restoring the original
|
||||
// live lanes.
|
||||
test.code.push_back(EncodeSop1(0x04, 12, 126));
|
||||
test.code.push_back(EncodeSop1(0x04, 126, InlineU32(0)));
|
||||
test.code.push_back(EncodeVop1(0x04, 1, InlineU32(9)));
|
||||
test.code.push_back(EncodeSop1(0x04, 126, 12));
|
||||
store_pair(1, std::bit_cast<uint64_t>(0.5));
|
||||
for (const auto [source, expected] :
|
||||
{std::pair<uint64_t, u32>{0x47f0000000000000ull, 0x7f7fffffu},
|
||||
{0xc7f0000000000000ull, 0xff7fffffu},
|
||||
{0x7ff0000000000000ull, 0x7f800000u},
|
||||
{0xfff0000000000000ull, 0xff800000u},
|
||||
{0x3800000000000000ull, 0},
|
||||
{0xb800000000000000ull, 0x80000000u},
|
||||
{0x3810000000000000ull, 0x00800000u},
|
||||
{0x3ff0000010000000ull, 0x3f800000u}}) {
|
||||
load_pair(1, source);
|
||||
AppendVop3(&test.code, 0x18f, 1, Vgpr(1), 0);
|
||||
store_word(1, expected);
|
||||
}
|
||||
load_pair(1, 0x7ff8123456789abcull);
|
||||
test.code.push_back(EncodeVop1(0x2f, 1, Vgpr(1)));
|
||||
AppendVMovLiteral(&test.code, 3, 0x7ff80000u);
|
||||
test.code.push_back(EncodeVop2(0x1b, 2, Vgpr(3), 2));
|
||||
store_word(2, 0x7ff80000u);
|
||||
AppendEnd(&test.code);
|
||||
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::S_MOV_B64,
|
||||
O::V_CVT_F64_I32, O::V_RCP_F64, O::V_MUL_F64,
|
||||
O::V_FMA_F64, O::V_CVT_F32_F64, O::V_AND_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorRcpIflagF32IntegerReciprocal() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -28874,6 +29031,8 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(CvtF32ToIntSaturatesNaNAndOutOfRange);
|
||||
AddCase(VectorSpecialF32FlushesDenormalInputs);
|
||||
AddCase(VectorRcpIflagF32IntegerReciprocal);
|
||||
AddCase(VectorF64CapturedScreenSpaceShadows);
|
||||
AddCase(VectorF64ModesModifiersAndExec);
|
||||
AddCase(VectorSinCosMaxFiniteSpecialCases);
|
||||
AddCase(VectorCompareOps);
|
||||
AddCase(VectorVop3CompareEqI64OnGpu);
|
||||
|
||||
Reference in New Issue
Block a user