Hello there,
I am working on an in-editor image editing extension and currently using Compute Shader to execute some heavy tasks.
I have three ComputeBuffers that I use to send pixels to the shader. I create these buffers in the class constructor and I dispose of them in the deconstructor.
Whenever I press and move a mouse around I execute every frame a function that sets data to these buffers and then dispatches the compute shader. Afterward, I get the output from one of the buffers and that’s it.
At the start, everything runs smoothly, however, after some seconds the unity memory usage goes up to the extreme. My total memory usage goes up to 98+%… Once I stop dragging the mouse and executing the shader the memory usage stays the same until I restart Unity.
I am still learning Compute Shaders and am not sure what could be causing this. Can someone give me some advice on what should I do to prevent such memory usage from happening?
Are you constructing this class each update? Or instancing once and using it for the lifetime of the editor/tool? As it’s ideal to just hold on to your ComputeBuffer until it’s actually not going to be needed for a long period of time.
Also, when you call GetData, are you making a new array each time or are you persisting an Array of adequate size to copy the data into?
Hello there, I am creating the class once when initializing the plugin on open. Should I dispose all buffers after the process is complete? Wouldn’t that be expensive to create new buffers every frame?
I have a color array variable that I create in the constructor and when I call GetData I specify that array variable as an argument. The size of the array is always the same. Also whenever I get the output result in the other class I use “Array.Copy” to store that received color data into another color array variable that will be used next time.
No no, I was asking just in case you weren’t just holding onto the same buffer. No worries, that’s good then.
That shouldn’t result in memory inflation either as that should be a GC free copy.
I would wager there must be something else going on that is causing it. Have you open up the Window>Analysis>Profiler and checked to see what function exactly is generating the GC? The profiler gives you a list of operations and you can sort by GC allocations. And you can also see total memory allocation that might help pinpoint the issue too.
What exact Unity version are you on as well? It may be a memory leak in Unity itself and worth a report depending on the version, or you may need to upgrade to a newer patch version of the major version you’re on if it’s not the latest.
I am using Unity 2021.1.15f1 version. I have run a deep profiler and this is the data that I’ve got:
Cpu Usage:
Memory:
In Cpu usage, it points to the ComputeBuffer.GetData method. I wait for the end of the frame before calling GetData, but maybe it takes longer for everything to process?
This is the current function, where I execute the compute shader:
Well, one main issue I see there is that you are actually creating a whole new array each time…
If data is already of appropriate length, then there is no reason to do new float4[canvasOutputPixels.Length];, just do canvasOutputPixels.CopyTo(data, 0);. Anywhere you might be doing similar, try to avoid it by using this or if it’s a buffer of varying size then an adequately sized List or NativeList. (or even just make a stackalloc (stack allocated) array if you only need the array for that frame and can utilize it within that call)
Also, is there a reason you’re converting your BlendMode enum to a string, instead of just using the enum as the key? var kernel = kernels[mode.ToString()];
You’ll generate garbage for the creation of a new string each time when you could just be doing var kernel = kernels[mode];.