It appears that reads to indices outside the range of a ComputeBuffer always return 0, and writes to out-of-range indices do not cause any exceptions or runtime errors. Is there built-in range-checking when reading and writing to a ComputeBuffer in hlsl that prevents buffer overflows?
With a simple Compute Shader:
#pragma kernel CSMain
RWStructuredBuffer<int> buf1;
RWStructuredBuffer<int> buf2;
RWStructuredBuffer<int> buf3;
[numthreads(64,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
buf1[id.x] = buf3[id.x];
}
CSharp side code:
void TestForBufferOverruns()
{
int bufferSize = 1024;
buf1 = new ComputeBuffer(bufferSize, sizeof(int));
buf2 = new ComputeBuffer(bufferSize, sizeof(int));
buf3 = new ComputeBuffer(bufferSize, sizeof(int));
// Init buffers to some arbitrary values
int[] initData = new int[bufferSize];
for(int i = 0; i < initData.Length; i++)
{
initData[i] = 3;
}
buf1.SetData(initData);
for(int i = 0; i < initData.Length; i++)
{
initData[i] = 7;
}
buf2.SetData(initData);
for(int i = 0; i < initData.Length; i++)
{
initData[i] = 8;
}
buf3.SetData(initData);
bufferOverrunShader.SetBuffer(0, "buf1", buf1);
bufferOverrunShader.SetBuffer(0, "buf2", buf2);
bufferOverrunShader.SetBuffer(0, "buf3", buf3);
// Max numThreadGroups should be 16.
// bufferSize/threadGroupSize = 1024/64 = 64.
// Dispatching more than 16 threadGroups should
// case a buffer overrun, correct?
int numThreadGroups = 17;
bufferOverrunShader.Dispatch(0, numThreadGroups, 1, 1);
}
Doing a readback of the buffers from the GPU shows all buffers contain the initial expected data, with buf1 containing the values from buf3.
My question is, why does this work without some sort of buffer overrun error?