ComputeShader: StructuredBuffer sometimes empty in Metal
Hi all,
I'm trying to access a StructuredBuffer from a Compute Shader targeting Metal on a MacBook Pro, and finding that it is sometimes full of zeros the first time the shader runs...
My shader is really simple and just returns green if the first item in the StructuredBuffer has a non-zero value and red otherwise...
I only ever set the value for an item to 1 so I know it should always be non-zero (green) however it seems to sometimes be zero (red).
Is this a bug?
Unity Version: 2020.1.3f1
Shader Code:
#pragma kernel CSMain
RWTexture2D<float4> Result;
struct SomeObject
{
float value;
};
StructuredBuffer<SomeObject> _Objects;
uint _ObjectsCount;
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
if (_ObjectsCount > 0 && !any(_Objects[0].value)) {
SomeObject s = _Objects[0];
// Red
Result[id.xy] = float4(1, 0, 0, 1);
} else {
// Green
Result[id.xy] = float4(0, 1, 0, 1);
}
}
Script Code (Attached to the Camera):
using System.Collections.Generic;
using UnityEngine;
struct SomeObject
{
public float value;
}
public class MyComputeShaderTest : MonoBehaviour
{
public ComputeShader RayTracingShader;
private RenderTexture _target;
private ComputeBuffer _objectBuffer;
private int _renderCount = 0;
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (_renderCount > 0)
{
return;
}
RayTracingShader.SetBuffer(0, "_Objects", _objectBuffer);
RayTracingShader.SetInt("_ObjectsCount", _objectBuffer.count);
// Make sure we have a current render target
InitRenderTexture();
// Set the target and dispatch the compute shader
RayTracingShader.SetTexture(0, "Result", _target);
int threadGroupsX = Mathf.CeilToInt(Screen.width / 8.0f);
int threadGroupsY = Mathf.CeilToInt(Screen.height / 8.0f);
RayTracingShader.Dispatch(0, threadGroupsX, threadGroupsY, 1);
// Blit the result texture to the screen
Graphics.Blit(_target, destination);
_renderCount++;
}
private void InitRenderTexture()
{
if (_target == null || _target.width != Screen.width || _target.height != Screen.height)
{
// Release render texture if we already have one
if (_target != null)
_target.Release();
// Get a render target for Ray Tracing
_target = new RenderTexture(Screen.width, Screen.height, 0,
RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
_target.enableRandomWrite = true;
_target.Create();
}
}
private void OnEnable()
{
List<SomeObject> objects = new List<SomeObject>();
// Add a number of random objects
for (int i = 0; i < 100; i++)
{
SomeObject o = new SomeObject();
o.value = 1;
objects.Add(o);
}
// Assign to compute buffer
_objectBuffer = new ComputeBuffer(objects.Count, 4);
_objectBuffer.SetData(objects);
}
private void OnDisable()
{
if (_objectBuffer != null)
_objectBuffer.Release();
}
}
Answer by Nightbringr · Aug 26, 2020 at 09:09 AM
Seems possible to work around this by "warming up" the shader
private void OnEnable()
{
...
RayTracingShader.Dispatch(0, 1, 1, 1);
}
This is probably not a fix and just masking an underlying timing issue
Your answer
Follow this Question
Related Questions
AsyncGPUReadback.GetData with computeBufferType.Append 0 Answers
Still Unity3D Editor 2017.2 , Freezing in Mac OS High Sierra 3 Answers
_WorldSpacePosLight0 suddenly changes when change camera position or direction 0 Answers
How can I read in the actual elements from an Append Compute Buffer? 2 Answers