Search Unity

ComputeBuffer.CopyCount(), how to clear buffer?

Discussion in 'Scripting' started by smuseus, Jul 23, 2015.

  1. smuseus

    smuseus

    Joined:
    Jun 8, 2014
    Posts:
    1
    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.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class BufferExample : MonoBehaviour
    5. {
    6.     public Material material;
    7.     public ComputeShader appendBufferShader;
    8.    
    9.     const int width = 32;
    10.     const float size = 5.0f;
    11.    
    12.     ComputeBuffer buffer;
    13.     ComputeBuffer argBuffer;
    14.    
    15.     void Start()
    16.     {
    17.        
    18.         buffer = new ComputeBuffer(width * width, sizeof(float) * 3, ComputeBufferType.Append);
    19.        
    20.         appendBufferShader.SetBuffer(0, "appendBuffer", buffer);
    21.         appendBufferShader.SetFloat("size", size);
    22.         appendBufferShader.SetFloat("width", width);
    23.        
    24.         appendBufferShader.Dispatch(0, width/8, width/8, 1);
    25.        
    26.         argBuffer = new ComputeBuffer(4, sizeof(int), ComputeBufferType.DrawIndirect);
    27.        
    28.         int[] args = new int[]{ 0, 1, 0, 0 };
    29.         argBuffer.SetData(args);
    30.        
    31.         ComputeBuffer.CopyCount(buffer, argBuffer, 0);
    32.         argBuffer.GetData(args);
    33.        
    34.         Debug.Log("vertex count " + args[0]);
    35.         Debug.Log("instance count " + args[1]);
    36.         Debug.Log("start vertex " + args[2]);
    37.         Debug.Log("start instance " + args[3]);
    38.     }
    39.  
    40.     void OnPostRender ()
    41.     {
    42.         material.SetPass(0);
    43.         material.SetBuffer ("buffer", buffer);
    44.         material.SetColor("col", Color.red);
    45.         Graphics.DrawProceduralIndirect(MeshTopology.Points, argBuffer, 0);
    46.     }
    47.    
    48.     void OnDestroy ()
    49.     {
    50.         buffer.Release();
    51.         argBuffer.Release();
    52.     }
    53. }
     
  2. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    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.
     
  3. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    Going to bump this here.
     
  4. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    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.
     
  5. mat_muze

    mat_muze

    Joined:
    Mar 17, 2015
    Posts:
    31
    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.

    Code (CSharp):
    1. public static class MyExtensions
    2. {
    3.     public static void ClearAppendBuffer(this ComputeBuffer appendBuffer)
    4.     {
    5.         // This resets the append buffer buffer to 0
    6.         var dummy1 = RenderTexture.GetTemporary(8, 8, 24, RenderTextureFormat.ARGB32);
    7.         var dummy2 = RenderTexture.GetTemporary(8, 8, 24, RenderTextureFormat.ARGB32);
    8.         var active = RenderTexture.active;
    9.  
    10.         Graphics.SetRandomWriteTarget(1, appendBuffer);
    11.         Graphics.Blit(dummy1, dummy2);
    12.         Graphics.ClearRandomWriteTargets();
    13.  
    14.         RenderTexture.active = active;
    15.  
    16.         dummy1.Release();
    17.         dummy2.Release();
    18.     }
    19. }
    Then do something like this:

    Code (CSharp):
    1. var appendBuffer = new ComputeBuffer(1000, sizeof(float) * 3, ComputeBufferType.Append);
    2. 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.
     
    Last edited: Nov 26, 2015
  6. mat_muze

    mat_muze

    Joined:
    Mar 17, 2015
    Posts:
    31
    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
     
  7. bzor

    bzor

    Joined:
    May 28, 2013
    Posts:
    35
    sorry to necro this thread but if anyone else runs across this like I did, the answer now is:
    Code (CSharp):
    1. buffer.SetCounterValue(0);
    after the buffer init