Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Casting uint2 to float2 results in negative values for large uints... under some circumstances

Discussion in 'Burst' started by EmmaEwert, Jul 29, 2021.

  1. EmmaEwert

    EmmaEwert

    Joined:
    Mar 13, 2014
    Posts:
    30
    While toying around with floats in Burst-compiled jobs, I ran into an issue trying to cast a uint2 to a float2 - indeed, casting any uint vector to a float vector has this issue, it seems.

    The issue is that uints seem to be interpreted as ints when cast to float vectors.

    Below is a small snippet for reproducing the issue in a pathological case. Specifically, it implicitly casts uint.MaxValue and uint.MaxValue / 2 + 1 to two floats and one float2.

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Jobs;
    4. using Unity.Mathematics;
    5. using UnityEngine;
    6.  
    7. public class BurstFloatCast : MonoBehaviour {
    8.     private void Start() {
    9.         using var output = new NativeArray<float4>(1, Allocator.TempJob);
    10.         new CastJob { output = output }.Schedule().Complete();
    11.         Debug.Log($"Without Burst:\t{output[0]}");
    12.         new BurstCastJob { output = output }.Schedule().Complete();
    13.         Debug.Log($"With Burst:\t{output[0]}");
    14.     }
    15.  
    16.     private struct CastJob : IJob {
    17.         public NativeArray<float4> output;
    18.         public void Execute() {
    19.             var input = new uint2(uint.MaxValue, uint.MaxValue / 2 + 1);
    20.             output[0] = new float4(input.x, input.y, input.xy);
    21.         }
    22.     }
    23.  
    24.     [BurstCompile]
    25.     private struct BurstCastJob : IJob {
    26.         public NativeArray<float4> output;
    27.         public void Execute() {
    28.             var input = new uint2(uint.MaxValue, uint.MaxValue / 2 + 1);
    29.             output[0] = new float4(input.x, input.y, input.xy);
    30.         }
    31.     }
    32. }
    The output of this snippet is:
    Code (csharp):
    1.  
    2. Without Burst: float4(4.294967E+09f, 2.147484E+09f, 4.294967E+09f, 2.147484E+09f)
    3. With Burst:    float4(4.294967E+09f, 2.147484E+09f, -1f, -2.147484E+09f)
    4.  
    The two first values are the individual uints' values implicitly cast to floats.

    The two last values are the uint2's values implicitly cast to a float2.

    I can work around the issue by either explicitly or implicitly making sure to cast every uint individually to float, but that seems tedious and less than optimal.

    I presume new float2(input.x, input.y) should not give a different result to (float2)input.xy, for uint2 input?

    I am aware that floating point arithmetic yields different result in different environments, but surely casting any uint to a float should not result in negative values? Especially not exclusively in some casts but not all?
     
    SamOld likes this.
  2. tim_jones

    tim_jones

    Unity Technologies

    Joined:
    May 2, 2019
    Posts:
    287
    Thank you for reporting this, and apologies for the delayed reply. This does indeed look like a bug - we'll investigate.