Skip to content

Instantly share code, notes, and snippets.

@swillits
Created May 15, 2016 07:00
Show Gist options
  • Save swillits/36919b9c06b941cb6e992959f37b67ff to your computer and use it in GitHub Desktop.
Save swillits/36919b9c06b941cb6e992959f37b67ff to your computer and use it in GitHub Desktop.
// ================================================================
// Example 1:
@implementation MTLRenderPassDescriptor
+ (MTLRenderPassDescriptor *)renderPassDescriptor
{
// We know this method returns an "autoreleased" object because it's not alloc or copy.
// This is basically what it could look like...
return [[[MTLRenderPassDescriptor alloc] init] autorelease];
}
@end
// Somewhere in your code ...
@implementation FooInYourCode
- (void)blah
{
// No need to call release. It's already in balance because
// renderPassDescriptor returns an autoreleased instance
MTLRenderPassDescriptor * renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
}
@end
// This demonstrates some code higher up in the stack which is creating
// the autorelease pool. Usuall this would be the NSRunLoop on the main thread, for example.
@implementation Something_UsuallyTheMainThreadNSRunLoop
- (void)tick
{
// Create a pool, which sets it as the current autorelease pool on the thread...
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
{
// Someway somehow your method gets called...
[foo blah];
// -blah calls +renderPassDescriptor, which calls -autorelease on the renderPassDesc instance.
// -autorelease gives "the current autorelease pool" (eg 'pool' above) a reference to the receiving
// object, eg 'renderPassDesc'. So 'renderPassDesc' is now in the pool.
}
// 'pool' itself will be deallocated here since its retain count drops to zero,
// so pool calls -release on 'renderPassDesc' balancing the +alloc inside +renderPassDescriptor,
// which then makes renderPassDesc's retain count fall to 0 and be deallocated. No leak.
[pool release];
}
@end
// ================================================================
// Example 2
@implementation RendererFactory // for illustration...
- (Renderer *)makeRenderer
{
// Create the render pass desc... it's autoreleased
MTLRenderPassDescriptor * renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor];
// Pass it to this renderer. If the renderer is going to keep the RPD around,
// then the renderer itself is responsible for retaining it.
Renderer * renderer = [[Renderer alloc] initWithPassDesc:renderPassDesc other:otherObject];
// RendererFactory isn't going to keep a reference to the renderer,
// so call -autorelease, so the retain count is effectively in balance,
// and the caller does *not* need to explicitly release the renderer,
// just to balance an allocation.
return [renderer autorelease];
}
@end
@implementation Renderer
{
MTLRenderPassDescriptor * _renderPassDesc;
}
- (instancetype)initWithPassDesc:(MTLRenderPassDescriptor *)rpd other:(id)obj
{
if (!(self = [super init])) {
return nil;
}
// Retaining because this 'Renderer' instance will use the rpd obj later,
// after init returns.
_renderPassDesc = [rpd retain];
// ...
return self;
}
- (void)dealloc
{
// Simply balancing the -retain in our -init.
// Doesn't necessarily dealloc. Other renderers could reference / "own" this same RPD instance too.
[_renderPassDesc release];
[super dealloc];
}
- (void)renderFrame
{
// Reusing _renderPassDesc each frame
id<MTLCommandBuffer> commandBuffer = ...;
id<MTLRenderCommandEncoder> renderCE = [commandBuffer renderCommandEncoderWithDescriptor:_renderPassDesc];
// ...
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment