Hi All,
I’ve encountered a peculiar behavior when using SetComputeVectorParam
to update a global parameter in a compute shader. The issue manifests as the parameter value being one frame behind when accessed in the compute shader.
Steps:
- In the CPU code, I set a
Vector4
parameter usingSetComputeVectorParam
: - At the same time, I write the same data into a
ComputeBuffer
and use it in the shader.
Vector2 cachedPositionOffset = m_positionOffset;
var debugComputeBuffer = new ComputeBuffer(2, sizeof(float));
debugComputeBuffer.SetData(new []{cachedPositionOffset.x, cachedPositionOffset.y});
using var commandBuffer = CommandBufferPool.Get();
commandBuffer.SetComputeVectorParam(computeShader, "_PositionOffset", new Vector4(cachedPositionOffset.x, cachedPositionOffset.y, 0, 0));
commandBuffer.SetComputeBufferParam(computeShader, 0, "_debugBuffer", debugComputeBuffer);
commandBuffer.DispatchCompute(computeShader, 0, m_numThreads, 1, 1);
Graphics.ExecuteCommandBuffer(commandBuffer);
- I use the compute shader to write the
_PositionOffset
value to an output texture for debugging.
float4 _PositionOffset;
StructuredBuffer<float> _debugBuffer;
RWTexture2D<float4> _Result;
void Compute(uint3 id : SV_DispatchThreadID)
{
float4 debugColor = float4(_PositionOffset.x, _PositionOffset.y, _debugBuffer[0], _debugBuffer[1]);
_Result[int2(0, 0)] = debugColor;
}
Expectations:
The _PositionOffset
parameter and the ComputeBuffer
value should be identical within the same dispatch. Observed: The value from SetComputeVectorParam
lags one frame behind, while the value from the ComputeBuffer
is correct and up-to-date.
Findings:
- Switching to a
ComputeBuffer
for_PositionOffset
completely resolved the issue. - It seems that
SetComputeVectorParam
updates may not always propagate in time for the compute shader dispatch within the same frame. - The input values visible in Unity FrameDebugger appear to be up-to-date, however, upon also supplying a RenderCount id Integer, I realized it would just re-draw the whole thing when looked at in the Debugger, so its not the actual original drawcall.
- With RenderDoc I managed to capture the output Texture, where the values of the debugColor pixel would indeed not always be the exact same.
Environment:
- Unity Version: 2020.3.20f1
- Target Platform: Windows
- Rendering Pipeline: URP
Suggestions/Questions:
- Is this expected behavior due to Unity’s internal GPU queuing, or is it a bug in the parameter propagation pipeline?
- If this is expected, should
SetComputeVectorParam
include a note in the documentation warning about potential frame-lagging behavior? - Is there a best practice to ensure real-time updates when using
SetComputeXXXParam
, can it be trusted to be up-to-date or should I avoid it entirely in favor of ComputeBuffers?