I am currently writing a compute shader that requires a simple float multiplication of a float and a uint3, and I am getting really inaccurate results.
for example, uint3(1, 2, 3) * 0.25
expected result: uint3(0.25, 0.5, 0.75)
actual result: uint3(0.3, 0.5, 0.8)
Any idea how to increase the precision somehow?
The compute shader:
[numthreads(X_THREADS, Y_THREADS, Z_THREADS)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    // Fill the array
    uint tid = id.x;
    while (tid < octree_length)
    {
        // Normalize tid
        uint depth = OctreeDepth(tid);
        uint mid = tid - depth_offsets[depth];
        // Compute node data
        float node_size = bounds_size / pow(2, depth);
        float3 node_min = MortonToXYZ(mid) * node_size; 
        // Build node
        octree[tid].anchor = node_min;
        octree[tid].size = node_size;
        // Move tid
        tid += total_num_threads;
    }
}
The inaccurate multiplication:
float3 node_min = MortonToXYZ(mid) * node_size; 
The code that launches the shader and reads the data back:
ComputeBuffer BuildOctree(Vector3 boundsMin, float boundsSize, int octreeDepth, Vector3Int numThreadGroups) 
{
    // Compute constants
    int totalNumThreads = numThreadGroups.x * numThreadGroups.y * numThreadGroups.z * THREADS_PER_GROUPS;
    // Compute depth offsets and octree length
    int[] depthOffsets = new int[octreeDepth];
    int length = 0;
    for (int i = 0; i < octreeDepth; i++)
    {
        depthOffsets[i] = length;
        length += (int) Mathf.Pow(8, i);
    }
    // Prepare buffers
    ComputeBuffer octree = new ComputeBuffer(length, 4 * sizeof(float), ComputeBufferType.Structured);
    ComputeBuffer depthOffsetsGPU = new ComputeBuffer(octreeDepth, sizeof(int), ComputeBufferType.Structured);
    depthOffsetsGPU.SetData(depthOffsets);
    octree.SetData(new OctreeNode[length]);
    // Load data into shader
    OCTREE_BUILDER.SetBuffer(0, "octree", octree);
    OCTREE_BUILDER.SetBuffer(0, "depth_offsets", depthOffsetsGPU);
    OCTREE_BUILDER.SetInt("total_num_threads", totalNumThreads);
    OCTREE_BUILDER.SetInt("octree_length", length);
    OCTREE_BUILDER.SetFloat("bounds_size", boundsSize);
    // Launch kernal
    OCTREE_BUILDER.Dispatch(0, numThreadGroups.x, numThreadGroups.y, numThreadGroups.z);
    OctreeNode[] output = new OctreeNode[length];
    octree.GetData(output);
    for (int i = 0; i < output.Length; i++)
        Debug.Log("cell[" + i + "]: " + output[i].anchor + ", " + output[i].size);
    // Return octree buffer
    return octree;
}
Note:\
As user @bart pointed out, the issue was in the print, unity prints a 2 digit format which rounded my values down, by using ToString("F5") in my print it shows the correct values
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With