ComputeBuffer.CopyCount(), how to clear buffer?

I’m following Scrawks tutorial on AppendBuffers.

Each time ComputeBuffer.CopyCount() is called, the vertex count in the debugger increments.

How can I clear the memory? I’ve tried to release the buffers, yet this has no effect.

The odd thing is, if I comment out the ComputeBuffer.CopyCount(), the vertex count gets reset.

using UnityEngine;
using System.Collections;

public class BufferExample : MonoBehaviour
{
    public Material material;
    public ComputeShader appendBufferShader;
   
    const int width = 32;
    const float size = 5.0f;
   
    ComputeBuffer buffer;
    ComputeBuffer argBuffer;
   
    void Start()
    {
       
        buffer = new ComputeBuffer(width * width, sizeof(float) * 3, ComputeBufferType.Append);
       
        appendBufferShader.SetBuffer(0, "appendBuffer", buffer);
        appendBufferShader.SetFloat("size", size);
        appendBufferShader.SetFloat("width", width);
       
        appendBufferShader.Dispatch(0, width/8, width/8, 1);
       
        argBuffer = new ComputeBuffer(4, sizeof(int), ComputeBufferType.DrawIndirect);
       
        int[] args = new int[]{ 0, 1, 0, 0 };
        argBuffer.SetData(args);
       
        ComputeBuffer.CopyCount(buffer, argBuffer, 0);
        argBuffer.GetData(args);
       
        Debug.Log("vertex count " + args[0]);
        Debug.Log("instance count " + args[1]);
        Debug.Log("start vertex " + args[2]);
        Debug.Log("start instance " + args[3]);
    }

    void OnPostRender ()
    {
        material.SetPass(0);
        material.SetBuffer ("buffer", buffer);
        material.SetColor("col", Color.red);
        Graphics.DrawProceduralIndirect(MeshTopology.Points, argBuffer, 0);
    }
   
    void OnDestroy ()
    {
        buffer.Release();
        argBuffer.Release();
    }
}

Don’t think the count is getting reset, but rather, it’s not getting filled so it’s just set to the initial args parameter.

I’ve been trying to figure this out, but no luck, so I’m going to bump this up and see if anyone has any thoughts or ideas.

Going to bump this here.

I’ll try again… anyone have any thoughts? I’ve explored this chain quite thoroughly, but googling hasn’t given me much information, besides some vague thoughts on C code that would reset it through methods I’m not quite clear on.

I noticed that append buffer work as expected when using Graphics.Blit(), but not when using DrawProcedural(). The counter would simply not reset for some reason. Therefore I had the idea to perform a “dummy” blit in order to force the append buffer to reset the counter, and it worked.

I made an extension so that the buffer can be cleared easily.

public static class MyExtensions
{
    public static void ClearAppendBuffer(this ComputeBuffer appendBuffer)
    {
        // This resets the append buffer buffer to 0
        var dummy1 = RenderTexture.GetTemporary(8, 8, 24, RenderTextureFormat.ARGB32);
        var dummy2 = RenderTexture.GetTemporary(8, 8, 24, RenderTextureFormat.ARGB32);
        var active = RenderTexture.active;

        Graphics.SetRandomWriteTarget(1, appendBuffer);
        Graphics.Blit(dummy1, dummy2);
        Graphics.ClearRandomWriteTargets();

        RenderTexture.active = active;

        dummy1.Release();
        dummy2.Release();
    }
}

Then do something like this:

var appendBuffer = new ComputeBuffer(1000, sizeof(float) * 3, ComputeBufferType.Append);
appendBuffer.ClearAppendBuffer();

Strangely the dummy blit also solves other issues. I managed to make a texture work with Graphics.SetRandomWriteTarget() by doing a dummy blit afterwards, and it made my stuffs work all smoothly.

Any success with that snippet I just gave you ?

Keep in mind that the buffer must also be cleared before its first use in the application, because the count may sometimes be initialized to a random value which can crash the GPU driver

sorry to necro this thread but if anyone else runs across this like I did, the answer now is: buffer.SetCounterValue(0);

after the buffer init

5 Likes