How to deallocate a MTLBuffer and MTLTexture
Asked Answered
B

2

9

I know how to create a MTLBuffer and or MTLTexture but how do I free the GPU memory for these resources when they are no longer needed?

Bonnett answered 26/8, 2016 at 4:27 Comment(0)
E
18

MTLBuffer and MTLTexture are Objective-C objects and thus reference counted. If you are using automatic reference counting in an Objective-C project or using Metal via Swift, simply ensuring you no longer hold references to the buffer or texture will release any associated hardware resources.

let texture: MTLTexture? = device.newTexture(with: descriptor)
texture = nil // <- resources will be released

One can confirm this by stepping through the associated assembly when assigning nil to texture, which first leads us to [MTLDebugTexture dealloc]

MetalTools`-[MTLDebugTexture dealloc]:
    ...
->  0x100af569e <+34>: call   0x100af87ee               ; symbol stub for: objc_msgSendSuper2
    0x100af56a3 <+39>: add    rsp, 0x10
    0x100af56a7 <+43>: pop    rbp
    0x100af56a8 <+44>: ret    

...and through [MTLToolsObject dealloc]

MetalTools`-[MTLToolsObject dealloc]:
    0x100ac6c7a <+0>:   push   rbp
    0x100ac6c7b <+1>:   mov    rbp, rsp
    0x100ac6c7e <+4>:   push   r14
    ...

...and through the GeForceMTLDriver

GeForceMTLDriver`___lldb_unnamed_symbol1095$$GeForceMTLDriver:
->  0x7fffd2e57b14 <+0>:  push   rbp
    0x7fffd2e57b15 <+1>:  mov    rbp, rsp

All the way, releasing any resources through the various dealloc methods.

Exile answered 26/8, 2016 at 6:57 Comment(0)
W
4

If you are using automatic reference counting, as the accepted answer said, just set nil.

But if you are using manual reference counting, Metal has two kinds of dynamically allocated resources(MTLBuffer && MTLTexture) and you can release them in below way.

id<MTLDevice> m_Device = MTLCreateSystemDefaultDevice();
// allocate Buffer
NSUInteger BufferLength = 100;
id<MTLBuffer> m_Buffer = [m_Device newBufferWithLength:BufferLength options:0]; 

// allocate Texture
MTLTextureDescriptor *shadowTextureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatDepth32Float width: 1024 height: 1024 mipmapped: NO];
id<MTLTexture> m_Texture = [m_Device newTextureWithDescriptor:shadowTextureDesc];

// release Buffer
[m_Buffer setPurgeableState:MTLPurgeableStateEmpty]; 
[m_Buffer release];

// release Texture
[m_Texture setPurgeableState:MTLPurgeableStateEmpty];
[m_Texture release];

About setPurgeableState, you can refer to the link(https://developer.apple.com/documentation/metal/mtlresource/1515898-setpurgeablestate)

Workingwoman answered 25/3, 2019 at 3:23 Comment(6)
Id like you to expand on this for other MTL types to make it a better answer.Oligosaccharide
@RayGarner In my opinion, Only MTLBuffer && MTLTexture need to be released(in manual reference counting mode) and the other MTL types are static. Then, they are automatically released when they are out of scope.Corrody
OK what about descriptors that are alloced with new or alloc init. Also is the call to release 100% necessary if you setPurgeableState:MTLPurgeableStateEmpty ?Oligosaccharide
Why is release not enough and you have to set the purgable state to empty? Wouldn't release do it when references get to 0?Victoriavictorian
Of course, you can try it. I only implement the brutal release way.Corrody
I just want to add, that setPurgeableState:MTLPurgeableStateEmpty causes Metal to ignore buffer dependencies. If you happen to have kernels still running or scheduled to run that use the purgeable buffer, you may experience all kinds of weird behaviour. However, if you just call release, the buffer will not be deallocated until all dependent kernels (well, command buffers to be precise) finish executing.Imperator

© 2022 - 2024 — McMap. All rights reserved.