mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-06 13:30:00 +00:00
Merge pull request #15161 from brumskysb/docs/fma-f64-tininess
docs(shader): record `v_fma_f64` and `v_div_fmas_f64` on RDNA2
This commit is contained in:
1 file changed
+1
-1
@@ -128,7 +128,7 @@
|
||||
- [v_fma_f64 and v_div_fmas_f64](../../../core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterFloat64.cpp) with a subnormal operand or result round once, as IEEE 754 fusedMultiplyAdd does with f64 denormals kept, measured on RDNA2 (gfx1035) at IEEE=0 and IEEE=1, `v_div_fmas_f64` with VCC clear and set. Shaders with f64 instructions declare `DenormPreserve` for 64-bit floats only when `shaderDenormPreserveFloat64` is true and Vulkan reports `denormBehaviorIndependence` as `ALL`; other independence modes are not handled by the current backend because they require coupled execution modes. See [VkShaderFloatControlsIndependence](https://docs.vulkan.org/refpages/latest/refpages/source/VkShaderFloatControlsIndependence.html). Elsewhere the driver may flush f64 subnormals, and `agc_driver_f64_fma_subnormals` skips if it does.
|
||||
- [v_floor_f64, v_ceil_f64, v_fract_f64, v_frexp_mant_f64 and v_frexp_exp_i32_f64](../../../core/shader/recompiler/Translation/src/Float64Instructions.cpp) follow the `FLOAT_MODE` f16/f64 denormal field: a denormal input is flushed to a zero of its sign when bit 0 is clear (0 and 2), and `v_fract_f64` flushes a denormal result, the fraction of a positive denormal input, to +0 when bit 1 is clear (0 and 1). `v_trunc_f64` and `v_rndne_f64` give the same results either way and are unchanged. Measured on RDNA2 (gfx1031, Radeon RX 6700 XT, AMD Windows driver 32.0.21045.5002 through HIP) at IEEE=0 and IEEE=1 with denorm16 0..3 over 23 f64 values (zeros, denormals, minimum normals, ±0.5, ±1, values next to 1, the largest finite value, infinities and quiet and signaling NaNs), and with neg and abs modifiers over 16 values (13 of those, -1.5, 2.75 and 1 - 2^-53). Shaders without a known float mode keep the previous lowering. The PS5's gfx1013 is not measured.
|
||||
- [v_add_f64 and v_mul_f64 denormals](../../../core/shader/recompiler/Translation/src/Float64Instructions.cpp) follow the `FLOAT_MODE` f16/f64 denormal field; the PS5's gfx1013 is not measured. Inputs flush to a zero of their sign when bit 0 is clear (0 and 2). When bit 1 is clear (0 and 1), a sum below 2^-1022, or a product whose exact value rounded to 53 significant bits with an unbounded exponent is below 2^-1022, flushes to a zero of its sign, so `0x2000000000000001 * 0x1ffffffffffffffe` (exactly 2^-1022 - 2^-1126) rounds to 2^-1022 and is kept. Measured on RDNA2 (gfx1031, RX 6700 XT, AMD Windows driver 32.0.21045.5002, HIP) at IEEE=0 and 1, denorm16 0..3, over 576 pairs of 24 f64 values (zeros, denormals, minimum normals, values next to 1 and to 2^-1022, products just below 2^-1022, the largest finite value, infinities), with neg, abs and clamp. Shaders without a known float mode keep the previous lowering.
|
||||
- [v_fma_f64 and v_div_fmas_f64 denormals](../../../core/shader/recompiler/Translation/src/Float64Instructions.cpp) follow the `FLOAT_MODE` f16/f64 denormal field as measured on RDNA3 (gfx1101, Radeon RX 7700 XT) with the hardware oracle; the PS5's gfx1013 is not measured. RDNA2 (gfx1035) matches this rule in denorm16 0 and 3 over 3,000 rows of each instruction at IEEE=0 and 1, including `0x3fefffffffffffff * 0x0010000000000000` (exactly 2^-1022 - 2^-1075), which flushes. Those rows do not tell tininess after rounding from before it, so `0x2000000000000001 * 0x1ffffffffffffffe` (exactly 2^-1022 - 2^-1126), which gfx1101 keeps as 2^-1022, and denorm16 1 and 2 are not measured on RDNA2. `v_fma_f64` flushes denormal operands to a zero of their sign when bit 0 is clear (0 and 2); `v_div_fmas_f64` keeps them. When bit 1 is clear (0 and 1), both flush a result whose value rounded to 53 significant bits with an unbounded exponent is below 2^-1022 to a zero of its sign, `v_div_fmas_f64` after its VCC scale by 2^±128. Measured at IEEE=0 and 1, denorm16 0..3, over 300 random triples biased to denormals. Shaders without a known float mode keep the previous lowering.
|
||||
- [v_fma_f64 and v_div_fmas_f64 denormals](../../../core/shader/recompiler/Translation/src/Float64Instructions.cpp) follow the `FLOAT_MODE` f16/f64 denormal field (gfx1101); the PS5's gfx1013 is not measured. `v_fma_f64` flushes denormal operands to a zero of their sign when bit 0 is clear (0 and 2); `v_div_fmas_f64` keeps them. When bit 1 is clear (0 and 1) both flush a result that rounds to 53 significant bits below 2^-1022 with an unbounded exponent, to a zero of its sign, `v_div_fmas_f64` after its VCC scale by 2^±128. On RDNA2 (gfx1036), IEEE=0/1, denorm16 0..3, a product that rounds up to 2^-1022 is kept in every mode (`0x2000000000000001 * 0x1ffffffffffffffe`, 2^-1022 - 2^-1126), while the exact tie `0x3fefffffffffffff * 0x0010000000000000` (2^-1022 - 2^-1075) flushes in modes 0 and 1 and is kept in 2 and 3; `v_div_fmas_f64` matches. RDNA2 (gfx1035) matches in 0 and 3 (3,000 rows each). Also 300 random biased triples. Without a known float mode, lower as before.
|
||||
- [v_add_f64, v_mul_f64, v_cvt_f64_f32 and v_cvt_f32_f64](../../../core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterFloat64.cpp) are computed with 64-bit integers, rounded to nearest even with denormals kept, on a device without the Float64 capability when they are the only f64 instructions of the shader; any other f64 instruction still needs Float64 and throws. NaN results use the same bits as the native path. Checked bit for bit against the host's IEEE results by `agc_driver_f64_integer_arithmetic` (on Apple M5 Max through MoltenVK and an RTX 4090 per the author); not measured on AMD hardware or the PS5's gfx1013.
|
||||
- [SINT storage images](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp) of 8- and 16-bit components saturate each stored 32-bit value to the component range, as adriadam10 measured for image stores on RDNA2 (gfx1035) in #944 (448 rows match); the PS5's gfx1013 is not measured. A D16 store sign-extends each 16-bit half before that saturation, as measured on RDNA2 (gfx1035) for `image_store d16` to all eight SINT formats with DMASK 0xf, 0x7, 0x5, 0x3, 0x2, 0xa and 0x1 (1792 rows match).
|
||||
- [D16 accesses of converted images](../../../core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp) (10_11_11 UNORM, and 11_11_10 or 10_11_11 FLOAT written through an R32_UINT storage view) are not measured on hardware. A D16 `image_store` widens each half to f32, which is exact, and encodes it as the 32-bit store does. A D16 `image_load` decodes the texel to f32 as the 32-bit load does and rounds each component to f16 to nearest even, so a UNORM component is rounded twice; the float formats fit f16 exactly, except for NaN payloads. `image_load` of the float formats reads the native B10G11R11 view and does not take this path.
|
||||
|
||||
Reference in new issue
Block a user