On Fri Feb 23 19:36:48 2024 +0000, Francisco Casas wrote:
Interesting experiments! This is making me having two separate hypothesis for SM1: A) Constant propagation skips casts from int to uint and vice-versa, which explains the result of the second test. B) Native must be doing something similar to my pass from !671 2/3 but before constant propagation. This means that constant folding casts the constants to float before performing the operation, and then casts the result back to the expected type. So in this test:
[pixel shader fail(sm<4) todo(sm<4)] float4 main() : SV_TARGET { uint x = 3000000000 + 3000000000; return float4(x, 0.0, 0.0, 0.0); } [test] draw quad todo probe all rgba (2.14748365e+009, 0.0, 0.0, 0.0)
- Each `3000000000` is stored as `int`, so each overflows to `-1294967296`.
- In the presence of arithmetic operators, constant folding turns them
to float.
- The `+` is performed with floating-point arithmetic resulting in
`-1294967296.0f - 1294967296.0f = -2589934592.0f`.
- The result is turned back to int which in C results in `2147483648`
(INT_MAX) because it cannot be represented as int (yep, it is UB).
I am approving the merge request, check my minor comment nitpicks if you got the chance before it gets merged.
Please disregard my hypothesis B. I tried that and it didn't work. In fact you even mentioned: ``` % Constant folding is done with uint semantics before converting to float; % so constant folding seems to happen before converting integer operations to floats ``` but maybe there is a lot more going on, for instance, notice this shader: https://shader-playground.timjones.io/df675e96acb6d16bb77dc0ebdf69dfb2
Constant folding is even preempting catastrophic cancellation.