Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[Solved] ComputeBuffer becomes null after hotswap, seems to cause a memory leak

Discussion in 'Shaders' started by Guedez, Sep 5, 2017.

  1. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    Edit - Solution: I simply release the buffers on
    Code (csharp):
    1. UnityEditor.AssemblyReloadEvents.beforeAssemblyReload

    Post before edit: -----------------------
    I have a compute buffer declared as such
    Code (csharp):
    1.         [SerializeField, HideInInspector]
    2.         public ComputeBuffer _append;
    However, it becomes null, even with SerializeField, after the code hotswaps.
    The issue is that during hotswap, the "OnDestroy" method is not called, and therefore I don't Dispose/Release() the buffers, causing a memory leak.

    I can't be 100% sure that this is the cause of a memory leak I have, but sure enough, quickly running and stopping the game does not permanently increase the memory usage of the editor (as measured by the Task Manager), meanwhile running, hotswapping and stopping does.

    I've tried using OnBeforeSerialize, but there is no way to know if this was called because I clicked the GameObject (and thus the inspector called OnBeforeSerialize), or if it was the unity serialization.
     
    Last edited: Sep 7, 2017
  2. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    322
    I don't believe you can serialize ComputeBuffers like this, as they are not UnityObjects. It wouldn't really make sense to. Hotswapping is a bit of a nightmare to detect and I avoid it like the plague personally, however you can poll EditorApplication.isCompiling to try and chuck in a sneaky Dispose(). Personally I just create and dispose them as close to use as possible to avoid this issue, but a ComputeBufferPool sort of thing would work as well.
     
  3. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    I was experimenting with checking
    Code (csharp):
    1. Event.current == null && isTheStackTraceJustThisMethod()
    inside the serialization callback, and while this does work, unfortunately, checking a combo box on a inspector window is detected as a false positive

    I am currently investigating using a wrapper that overrides Finalize, then I just release the buffer right before the wrapper gets GC'ed. Hopefully it will work, but I still did not have the time to test it.

    If I could just instantiate a compute buffer through it's native pointer, then all would work (at least it seems), I could just serialize the pointer and use it, since obviously the buffer still exists in the graphics card memory.
     
  4. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    I̶t̶ ̶d̶o̶e̶s̶ ̶n̶o̶t̶ ̶w̶o̶r̶k̶.̶ ̶I̶ ̶c̶a̶n̶n̶o̶t̶ ̶d̶e̶s̶t̶r̶o̶y̶ ̶t̶h̶e̶ ̶b̶u̶f̶f̶e̶r̶s̶ ̶o̶u̶t̶s̶i̶d̶e̶ ̶o̶f̶ ̶t̶h̶e̶ ̶m̶a̶i̶n̶ ̶t̶h̶r̶e̶a̶d̶ ̶f̶o̶r̶ ̶s̶o̶m̶e̶ ̶r̶e̶a̶s̶o̶n̶,̶ ̶c̶a̶n̶'̶t̶ ̶q̶u̶e̶u̶e̶ ̶a̶ ̶d̶e̶l̶e̶g̶a̶t̶e̶ ̶i̶n̶t̶o̶ ̶t̶h̶e̶ ̶n̶e̶x̶t̶ ̶m̶a̶i̶n̶ ̶t̶h̶r̶e̶a̶d̶ ̶e̶x̶e̶c̶u̶t̶i̶o̶n̶ ̶b̶e̶c̶a̶u̶s̶e̶ ̶b̶y̶ ̶t̶h̶e̶n̶,̶ ̶t̶h̶e̶ ̶a̶s̶s̶e̶m̶b̶l̶y̶ ̶i̶s̶ ̶a̶l̶r̶e̶a̶d̶y̶ ̶r̶e̶l̶o̶a̶d̶e̶d̶ ̶a̶n̶d̶ ̶t̶h̶u̶s̶ ̶t̶h̶e̶ ̶r̶e̶f̶e̶r̶e̶n̶c̶e̶ ̶l̶o̶s̶t̶

    I was about to throw a hissyfit about how impossible this is but then I've found out about UnityEditor.AssemblyReloadEvents.beforeAssemblyReload
     
    OccaSoftware likes this.
  5. OccaSoftware

    OccaSoftware

    Joined:
    May 24, 2019
    Posts:
    29
    UnityEditor.AssemblyReloadEvents.beforeAssemblyReload also solves Compute Buffers from URP Custom Render Passes throwing GC warnings. Thanks for sharing your solution here.