Search Unity

ComputeBuffer warning when component uses ExecuteInEditMode

Discussion in 'Shaders' started by thefonet, Mar 11, 2020.

  1. thefonet

    thefonet

    Joined:
    Apr 9, 2014
    Posts:
    10
    I'm using a ComputeShader which uses a ComputeBuffer that I want to see in the Editor when the game is not running, so I have made the component to ExecuteInEditMode.

    Unfortunately, every time I run the game I get the following warning.

    Code (csharp):
    1. GarbageCollector disposing of ComputeBuffer allocated in D:\SVN\G03-Crusoe\prototypes-world\Unity\Assets\Playtonic\Scripts\Game\Graphics\AreaPositionBufferGenerator.cs at line 112. Please use ComputeBuffer.Release() or .Dispose() to manually release the buffer.
    2. UnityEngine.ComputeBuffer:Finalize() (at C:/buildslave/unity/build/Runtime/Export/Shaders/ComputeShader.bindings.cs:28)
    Any ideas on what is the best way to allocate and release a ComputeBuffer when the game is not playing?

    Thanks!
     
  2. alexzzzz

    alexzzzz

    Joined:
    Nov 20, 2010
    Posts:
    1,447
    I hit the same problem. I allocate compute buffers in OnEnable and dispose them in OnDisable. Works fine without [ExecuteInEditMode], but with the attribute spams the console with tones of "GarbageCollector disposing of ComputeBuffer..." warnings.

    I have found a way to suppress the messages:
    Code (CSharp):
    1. buffer = new ComputeBuffer(4, Marshal.SizeOf<Matrix4x4>());
    2. GC.SuppressFinalize(buffer);
    - ComputeBuffer's finalizer doesn't do anything useful anyway, but I'm still not sure what's wrong exactly.
     
    Last edited: May 29, 2020
  3. bmarinariSparky

    bmarinariSparky

    Joined:
    Jan 5, 2018
    Posts:
    10
    To anyone who has this problem... make sure to heed the warning! It was leaking GPU memory in my case (where the buffer was set globally). My workaround was to add a
    SceneManager.sceneUnloaded
    delegate that released the buffers.
     
    DERKLORD, nacmac and a52 like this.
  4. Genghis42

    Genghis42

    Joined:
    Feb 14, 2018
    Posts:
    18
    My buffers were being prematurely disposed without me ever changing/unloading the scene, but this seemed to help:

    Code (CSharp):
    1. /// <summary>
    2. /// Prevent the C# garbage collector from disposing the buffers until this function is called.
    3. /// Call this wherever buffers *should* be disposed or released.
    4. /// </summary>
    5. public void KeepBuffersAlive()
    6. {
    7.     GC.KeepAlive(_accelReductionBuffer);
    8.     GC.KeepAlive(_maxPosReductionBuffer);
    9.     //etc for all your buffers
    10. }
    I think this still allows the GC to dispose the buffers after you call .Release(); it simply keeps them from being disposed *before* that.
     
    Last edited: Mar 31, 2022
    Invertex likes this.
  5. OccaSoftware

    OccaSoftware

    Joined:
    May 24, 2019
    Posts:
    29
    Using Compute Buffers in a Custom Render Pass in URP, these warnings go away in edit mode when subscribing to the UnityEditor delegate from the render pass constructor, which is also where I create the buffer.
    Code (CSharp):
    1. cBuffer = new ComputeBuffer(1, sizeof(float));
    2. #if UNITY_EDITOR
    3.      UnityEditor.AssemblyReloadEvents.beforeAssemblyReload += OnAssemblyReload;
    4. #endif
    And the OnAssemblyReload method:
    Code (CSharp):
    1. private void OnAssemblyReload()
    2. {
    3.      cBuffer.Release();
    4. }
    Try subscribing to the delegate from where you create the buffer and releasing it from the callback to see if that solves the issue for you.
     
    Propagant and wolfand13 like this.
  6. Propagant

    Propagant

    Joined:
    Nov 18, 2013
    Posts:
    38
    Fantastic. Thanks a bunch!
    If anyone is interested in the actual implementation, I needed to release all the buffers from a custom material buffer in OnEnable and OnDisable methods.
    Code (CSharp):
    1.  private void OnEnable()
    2.         {
    3. #if UNITY_EDITOR
    4.             AssemblyReloadEvents.beforeAssemblyReload += ReleaseComputeBuffers;
    5. #endif  
    6.         }
    7.        
    8.         private void OnDisable()
    9.         {
    10. #if UNITY_EDITOR
    11.             AssemblyReloadEvents.beforeAssemblyReload -= ReleaseComputeBuffers;
    12. #endif
    13.             ReleaseComputeBuffers();
    14.         }
    15.  
    16.         private void ReleaseComputeBuffers()
    17.         {
    18.             RenderMappingMaster.ReleaseComputeBuffer();
    19.             RenderMasterMaterials.ReleaseComputeBuffer();
    20.         }
     
    OccaSoftware likes this.