<p>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?</p>
<p>With a simple Compute Shader:</p>
<pre><code>#pragma kernel CSMain

RWStructuredBuffer&lt;int&gt; buf1;
RWStructuredBuffer&lt;int&gt; buf2;
RWStructuredBuffer&lt;int&gt; buf3;

[numthreads(64,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    buf1[id.x] = buf3[id.x];
}
</code></pre>
<p>CSharp side code:</p>
<pre><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 &lt; initData.Length; i++)
        {
            initData[i] = 3;
        }
        buf1.SetData(initData);

        for(int i = 0; i &lt; initData.Length; i++)
        {
            initData[i] = 7;
        }
        buf2.SetData(initData);

        for(int i = 0; i &lt; initData.Length; i++)
        {
            initData[i] = 8;
        }
        buf3.SetData(initData);

        bufferOverrunShader.SetBuffer(0, &quot;buf1&quot;, buf1);
        bufferOverrunShader.SetBuffer(0, &quot;buf2&quot;, buf2);
        bufferOverrunShader.SetBuffer(0, &quot;buf3&quot;, 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);
    }
</code></pre>
<p>Doing a readback of the buffers from the GPU shows all buffers contain the initial expected data, with buf1 containing the values from buf3.</p>
<p>My question is, why does this work without some sort of buffer overrun error?</p>

CC BY-SA 4.0
2022-11-03T12:05:46.650Z
Using D3D11 you [should be safe](https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-intro): *Direct3D guarantees to return zero for any resource that is accessed out of bounds.* Similarly, out of bounds writes should be ignored. That said this guarantee does not exist for D3D12 (iirc), since its the clients responsibility to manage descriptors and resource there anyway.
Carsten
CC BY-SA 4.0
2022-11-03T17:26:21.603Z
Thank you. That really does explain it. With that prompt, I was able to find [the relevant D3D12 docs](https://learn.microsoft.com/en-us/windows/win32/direct3d12/advanced-use-of-descriptor-tables#out-of-bounds-indexing) and [this post re OpenGL](https://stackoverflow.com/questions/72373517/out-of-bounds-index-in-indices-opengl). Much appreciated.
infosizzle
<compute-shader><buffers>
Does RWStructuredBuffer have built-in overflow protection in hlsl?
infosizzle
# Does RWStructuredBuffer have built-in overflow protection in hlsl?

(Asked by: username_0 on 2022-11-02)

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?

**Tags:** compute-shader, buffers

> **Comments:**
> **username_1**: Using D3D11 you [should be safe](https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-intro): *Direct3D guarantees to return zero for any resource that is accessed out of bounds.* Similarly, out of bounds writes should be ignored. That said this guarantee does not exist for D3D12 (iirc), since its the clients responsibility to manage descriptors and resource there anyway.  
> **username_0**: Thank you. That really does explain it. With that prompt, I was able to find [the relevant D3D12 docs](https://learn.microsoft.com/en-us/windows/win32/direct3d12/advanced-use-of-descriptor-tables#out-of-bounds-indexing) and [this post re OpenGL](https://stackoverflow.com/questions/72373517/out-of-bounds-index-in-indices-opengl). Much appreciated.  

---

## 0 answers

