Hi, I work on a app with Metal-cpp rendering. The app does not use an MTKView. Instead, it requests a drawable from the MetalLayer and renders to the drawable's texture.
When calling [CAMetalLayer nextDrawable]
i sometime get this error:
-[MTLDebugDevice notifyExternalReferencesNonZeroOnDealloc:]:2885: failed assertion `The following Metal object is being destroyed while still required to be alive by the command buffer 0x142944a00 (label: <no label set>):
<MTLToolsObject: 0x16e22b0a0> -> <AGXG13GFamilyTexture: 0x16e232a80>
label = CAMetalLayer Display Drawable
textureType = MTLTextureType2D
The call stack shows that nextDrawable tries to delete some textures.
1- I am confused by this message. Can someone confirm which object "is being destroyed"? The AGXG13GFamilyTexture or the MTLToolsObject?
2- I did a memory graph but i see no direct or indirect link between the texture and the command buffer. How can I find who is preventing the object from being destroyed?
My workstation: M1 Mac mini, MacOS Ventura 13.0.1, XCode 14.1
1- I am confused by this message. Can someone confirm which object "is being destroyed"? The AGXG13GFamilyTexture or the MTLToolsObject?
They are the same object. The MTLToolsObject is a class used when Metal API validation is enabled and it wrapping the actual driver object (AGXG13GFamilyTexture) which represents the object as used by the GPU.
2- I did a memory graph but i see no direct or indirect link between the texture and the command buffer. How can I find who is preventing the object from being destroyed?
A mengraph may not show you the relation between all objects. But it looks like CA is trying to destroy a drawable texture before a command buffer drawing to that texture has not completed.
A few things that would be useful to know. Are you creating command buffers with -[MTLCommandQueue commandBufferWithUnretainedReferences]
? Does this occur after/during a resize of the window? Are you double or triple buffered?
Something you can try is taking a strong reference to each drawable and only releasing it until the command buffer drawing to it has been presented. Something like the following:
id<MTLTexture> drawableTexture = [drawable.texture retain];
[myCmdBuf addCompletedHandler:^(...)
{
[drawableTexture release];
}];