I'm trying to convert an existing private property to an instance variable. This question is not about whether I should keep it a private property or not. I'm aware of the advantages of properties. However, in my case (at least I thought) that I don't need them.
So, the private property that I want to convert is declared as follows:
@interface Renderer ()
@property(nonatomic, strong) MTLRenderPassDescriptor* renderPassDescriptor;
@end
It is then initialized as follows:
- (void)createRenderPassDescriptor
{
self.renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
if(_scaledWidth > 0 && _scaledHeight > 0)
{
[self createDepthBufferTexture:self.renderPassDescriptor.depthAttachment];
[self createMultiSamplingTexture:self.renderPassDescriptor.colorAttachments[0]];
}
}
- (void)createMultiSamplingTexture:(MTLRenderPassColorAttachmentDescriptor*)colorAttachmentDescriptor
{
MTLTextureDescriptor* multisamplingTextureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:(NSUInteger)_scaledWidth
height:(NSUInteger)_scaledHeight
mipmapped:FALSE];
multisamplingTextureDescriptor.textureType = MTLTextureType2DMultisample;
multisamplingTextureDescriptor.usage = MTLTextureUsageRenderTarget;
multisamplingTextureDescriptor.storageMode = MTLStorageModePrivate;
multisamplingTextureDescriptor.resourceOptions = MTLResourceStorageModePrivate;
multisamplingTextureDescriptor.sampleCount = _multisampleAntiAliasingCount;
colorAttachmentDescriptor.texture = [self.device newTextureWithDescriptor:multisamplingTextureDescriptor];
colorAttachmentDescriptor.loadAction = MTLLoadActionClear;
colorAttachmentDescriptor.storeAction = MTLStoreActionMultisampleResolve;
colorAttachmentDescriptor.clearColor = MTLClearColorMake(1.0f, 1.0f, 1.0f, 1.0f);
}
I have omitted createDepthBufferTexture
because it does not seem relevant.
Finally, there is the renderFrame
method that gets continuously invoked by the rendering loop:
- (void)renderFrame
{
dispatch_semaphore_wait(_bufferAccessSemaphore, DISPATCH_TIME_FOREVER);
id<CAMetalDrawable> drawable = [self.layer nextDrawable];
id<MTLTexture> framebufferTexture = drawable.texture;
self.renderPassDescriptor.colorAttachments[0].resolveTexture = framebufferTexture;
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
// rest of the rendering code
}
I tried to convert the renderPassDescriptor
property to an instance variable as follows:
@implementation Renderer
{
MTLRenderPassDescriptor* _renderPassDescriptor;
// other instance variables
}
At the same time, I'm removing the expression @property(nonatomic, strong) MTLRenderPassDescriptor* renderPassDescriptor;
. So the property is no longer there.
After that I replace all calls of self.renderPassDescriptor
with just _renderPassDescriptor
. After doing so, the code compiles fine but it blows up at the following line in the renderFrame
method:
_renderPassDescriptor.colorAttachments[0].resolveTexture = framebufferTexture;
Apparently, colorAttachments[0] is not nil but invoking resolveTexture
crashes the app.
Unfortunately I cannot debug anymore due to Xcode not allowing me to deploy my app to physical iPhones (as described here). Running a metal app in the simulator is not supported (thanks, Apple!). So, please forgive me for not specifying what exactly is going on on that line.
Does anyone have a clue why it would make a difference whether I use a property or instance variable?
I know this might be a stupid question and comparable questions might be around already but I'm relatively new to Objective-C and just haven't figured it out myself yet.
EDIT:
My Xcode debugging issue is resolved which means I could take a closer look at what is going on.
The expression
_renderPassDescriptor.colorAttachments[0]
results in a EXC_BAD_ACCESS. So, the MTLRenderPassDescriptor*
variable _renderPassDescriptor
definitely behaves different than a private property of the same type. I just lack the insight why that would be the case.