Sergio0694 / ComputeSharp

A .NET library to run C# code in parallel on the GPU through DX12, D2D1, and dynamically generated HLSL compute and pixel shaders, with the goal of making GPU computing easy to use for all .NET developers! 🚀
MIT License
2.65k stars 122 forks source link

Precision issue with generated HLSL and float literal #779

Closed rickbrew closed 1 month ago

rickbrew commented 4 months ago

This shader:

[D2DInputCount(0)]
[D2DGeneratedPixelShaderDescriptor]
internal readonly partial struct BadShader
    : ID2D1PixelShader
{
    public float4 Execute()
    {
        return new float4(256, 60000, 131072.65f, 1.0f);
    }
}

generates this HLSL:

        /// <inheritdoc/>
        [global::System.CodeDom.Compiler.GeneratedCode("ComputeSharp.D2D1.D2DPixelShaderDescriptorGenerator", "3.0.0.0")]
        [global::System.Diagnostics.DebuggerNonUserCode]
        [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
        static string global::ComputeSharp.D2D1.Descriptors.ID2D1PixelShaderDescriptor<BadShader>.HlslSource =>
            """
            #define D2D_INPUT_COUNT 0

            #include "d2d1effecthelpers.hlsli"

            D2D_PS_ENTRY(Execute)
            {
                return float4(256, 60000, 131072.66, 1.0);
            }
            """;

Notice how the float4 in the C# has 131072.65f but the HLSL says 131072.66.

If I change to 131072.64f then it correctly emits 131072.64.

rickbrew commented 4 months ago

Now, to be fair, these two numbers do end up rounding to the same value, as evidenced by running this in the immediate window in VS:

131072.65f.ToString("N16")
"131,072.6562500000000000"
131072.66f.ToString("N16")
"131,072.6562500000000000"

But, I would still expect the generated HLSL to faithfully represent the C# code for something like this.

OR, I would expect it to emit 131072.65625 for both values

rickbrew commented 4 months ago

This came about while I was investigating #780 .

I don't think this issue (#779) is a high priority bug. HLSL is emitted that does not match the C# source, but it does produce the correct float value at runtime.

Instead, I consider this to be a debugging hazard: the HLSL will not match the C#, and it will be confusing.