How to set my constant buffer to compute shader

Hello

I have a buffer which i want to declare as constant since i only need to read from it, but i get an error when i attempt to set it.

In the compute shader i have:

#pragma kernel CSMain

RWBuffer<float2> Result;
const Buffer<float2> Twiddles;

Then in C# i have:

_twiddleBuffer = new ComputeBuffer(_size,sizeof(float)*2,ComputeBufferType.Constant);
_twiddleBuffer.SetData(_twiddleData);

int tID = Shader.PropertyToID("Twiddles");
_computeShader.SetConstantBuffer(tID, _twiddleBuffer, 0, sizeof(float) * _size);

But when i run my code i get this error every time:

Compute shader (CSMain): Property (Twiddles) at kernel index (7) is not set

What am i doing wrong here ?

The reason it doesn’t work is that you haven’t defined a constant buffer in the shader.
In HLSL syntax you define constant buffers with cbuffer. (ie. not const Buffer<>).
How ever, that would not work correctly on all API:s.

So instead you should use macros to do define it.

CBUFFER_START(MyRarelyUpdatedVariables)
float4 _SomeGlobalValue;
CBUFFER_END

Alternatively, if you decide you want to keep using Buffer, the syntax for read-only vs writeable is:

Buffer mybuffer; // read-only buffer
RWBuffer mybuffer; // writeable buffer

For both these cases, use _computeShader.SetBuffer() from script.

So what is the difference to a cbuffer and a Buffer which is read only…aren’t they technically both constant since you cannot write to them?

I think the Unity docs could do with some clarification here because it only really mentions Structured Buffers in 2 lines, so i am kinda guessing a lot here.

Most tutorials out there seem to all use Structured Buffer - unaware that you can just use Buffer for built in types.

The first answer to this post looks to give a decent summary:
https://www.gamedev.net/forums/topic/624529-structured-buffers-vs-constant-buffers/

Although I think some of that post is only relevant to NVidia GPUs, whereas AMD GPUs don’t consider them as different at all, from a performance perspective.

The very short version is that a “ConstantBuffer” is a special term for a small table of assorted values, whereas Buffer and StructuredBuffer are for arrays of the same type.

Eg you might use a ConstantBuffer for camera params, like the FOV, Aspect Ratio, View Matrix, Near Plane, etc.
Whereas a StructureBuffer is more likely used for “1,000 float3’s to define the positions of my asteroids.” Even though my second example might be constant data too.

I agree the terminology is not ideal - it comes from the graphics vendors or microsoft or both, i think. :slight_smile:

ComputeShader.SetConstantBuffer is giving stackoverflow on 2021.1

StackOverflowException: The requested operation caused a stack overflow.
UnityEngine.ComputeShader.SetConstantBuffer (System.Int32 nameID, UnityEngine.ComputeBuffer buffer, System.Int32 offset, System.Int32 size) (at <21b5136302b44b7c950da7557d38186f>:0)
UnityEngine.ComputeShader.SetConstantBuffer (System.Int32 nameID, UnityEngine.ComputeBuffer buffer, System.Int32 offset, System.Int32 size) (at <21b5136302b44b7c950da7557d38186f>:0)
UnityEngine.ComputeShader.SetConstantBuffer (System.Int32 nameID, UnityEngine.ComputeBuffer buffer, System.Int32 offset, System.Int32 size) (at <21b5136302b44b7c950da7557d38186f>:0)

I never managed to make it work in any version anyway.

please report it as a bug and we will fix :slight_smile:

1 Like

Stack overflow fixed in 2021.1.0b5 (db3e938e6c56).

1 Like

i was just playing around ComputeShader in 2019.4.20, where a constant buffer was declared like :
CBUFFER_START(GlobalDispatchSize)
uint _DispatchSize[4]; // actually intend to use this
uint _DispatchSize_x, _DispatchSize_y, _DispatchSize_z; // not intended to use this, that need padding
CBUFFER_END

then in the csharp awake/start, i computeShader.SetInts(_DispatchSize, intArry[4]), where intArry[4] was filled with values. then i output the data from the ComputeShader side, confirm that “_DispatchSize” only got x comp has data, all other comp is 0.
if i use computeShader.SetInt(_DispatchSize_x, intX) respectively,
_DispatchSize_x, _DispatchSize_y, _DispatchSize_z all got correct value.

was wondering if the api is bugged in 2019.4.20 ?

1 Like

Assuming “inArry” is an array of integers, you are passing intArray[4] which is a single int. As a result, only the first int in _DispatchSize will get any value. You should do computeShader.SetInts(_DispatchSize, intArry[0], intArry[1], intArry[2], intArry[3]) instead.

Sorry for the mild necropost!