Bad access in CoreGraphicsMetalLayerRenderer::drawRectangleList

We just started testing our application with JUCE 7.
I turned on JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS but i get a bad acces
in CoreGraphicsMetalLayerRenderer::drawRectangleList.

I don’t know why this happens yet for us but this is what happens:

        if (! CGSizeEqualToSize (layer.drawableSize, transformedFrameSize))
        {
            layer.drawableSize = transformedFrameSize;
            resources = std::make_unique<Resources> (device.get(), layer, componentHeight);
        }

        auto gpuTexture = resources->getGpuTexture();

Resources is created conditionally, but on line 89 it assumes it is there.
I added a line that checks if resources is null and returns false when it is.
When i add the check our application does seem to run fine.

might be related to:

This will be addressed in the upcoming fix.

Ok, thanks!

Hi @t0m , we finally got around to trying to enable this macro again.
However we have an issue when a component’s size is 0x0, which occasionally seems to happen in our codebase en most likely will happen for other as well, we are testing this with JUCE 7.0.2.
When size is 0x0 we get an assert from Metal, so ideally JUCE should catch this behaviour.

This is the backtrace we got:

2022-11-18 12:54:05.637408+0100 Arena[49017:171155] CAMetalLayer ignoring invalid setDrawableSize width=0.000000 height=0.000000
2022-11-18 12:54:06.075758+0100 Arena[49017:171155] [com.resolume.arena] CGContextTranslateCTM: invalid context 0x0. Backtrace:
  <_ZN4juce30CoreGraphicsMetalLayerRendererI6NSViewE9ResourcesC2EPU19objcproto9MTLDevice11objc_objectP12CAMetalLayer+1662>
   <_ZN4juce30CoreGraphicsMetalLayerRendererI6NSViewE9ResourcesC1EPU19objcproto9MTLDevice11objc_objectP12CAMetalLayer+37>
    <_ZNSt3__1L11make_uniqueIN4juce30CoreGraphicsMetalLayerRendererI6NSViewE9ResourcesEJPU19objcproto9MTLDevice11objc_objectRP1
     <_ZN4juce30CoreGraphicsMetalLayerRendererI6NSViewE17drawRectangleListIZZNS_19NSViewComponentPeer25setNeedsDisplayRectangle
      <_ZZN4juce19NSViewComponentPeer25setNeedsDisplayRectanglesEvENKUlvE0_clEv+213>
       <_ZN4juce19NSViewComponentPeer25setNeedsDisplayRectanglesEv+773>
        <_ZN4juce19NSViewComponentPeer23onDisplaySourceCallbackEv+21>
         <___ZN4juce19NSViewComponentPeer19createCVDisplayLinkEv_block_invoke+28>
          <_dispatch_client_callout+8>
           <_dispatch_continuation_pop+453>
            <_dispatch_source_invoke+2179>
             <_dispatch_main_queue_drain+744>
              <_dispatch_main_queue_callback_4CF+31>
               <__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__+9>
                <__CFRunLoopRun+2771>
                 <CFRunLoopRunSpecific+562>
                  <RunCurrentEventLoopInMode+292>
                   <ReceiveNextEventCommon+594>
                    <_BlockUntilNextEventMatchingListInModeWithFilter+70>
                     <_DPSNextEvent+927>
                      <-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]+1394>
                       <-[NSApplication run]+586>
                        <_ZN4juce14MessageManager15runDispatchLoopEv+153>
                         <_ZN4juce19JUCEApplicationBase4mainEv+389>
                          <_ZN4juce19JUCEApplicationBase4mainEiPPKc+60>
                           <main+51>                            12b91d52e
2022-11-18 12:54:06.480133+0100 Arena[49017:171155] [com.resolume.arena] CGContextScaleCTM: invalid context 0x0. Backtrace:
  <_ZN4juce30CoreGraphicsMetalLayerRendererI6NSViewE9ResourcesC2EPU19objcproto9MTLDevice11objc_objectP12CAMetalLayer+1795>
   <_ZN4juce30CoreGraphicsMetalLayerRendererI6NSViewE9ResourcesC1EPU19objcproto9MTLDevice11objc_objectP12CAMetalLayer+37>
    <_ZNSt3__1L11make_uniqueIN4juce30CoreGraphicsMetalLayerRendererI6NSViewE9ResourcesEJPU19objcproto9MTLDevice11objc_objectRP1
     <_ZN4juce30CoreGraphicsMetalLayerRendererI6NSViewE17drawRectangleListIZZNS_19NSViewComponentPeer25setNeedsDisplayRectangle
      <_ZZN4juce19NSViewComponentPeer25setNeedsDisplayRectanglesEvENKUlvE0_clEv+213>
       <_ZN4juce19NSViewComponentPeer25setNeedsDisplayRectanglesEv+773>
        <_ZN4juce19NSViewComponentPeer23onDisplaySourceCallbackEv+21>
         <___ZN4juce19NSViewComponentPeer19createCVDisplayLinkEv_block_invoke+28>
          <_dispatch_client_callout+8>
           <_dispatch_continuation_pop+453>
            <_dispatch_source_invoke+2179>
             <_dispatch_main_queue_drain+744>
              <_dispatch_main_queue_callback_4CF+31>
               <__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__+9>
                <__CFRunLoopRun+2771>
                 <CFRunLoopRunSpecific+562>
                  <RunCurrentEventLoopInMode+292>
                   <ReceiveNextEventCommon+594>
                    <_BlockUntilNextEventMatchingListInModeWithFilter+70>
                     <_DPSNextEvent+927>
                      <-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]+1394>
                       <-[NSApplication run]+586>
                        <_ZN4juce14MessageManager15runDispatchLoopEv+153>
                         <_ZN4juce19JUCEApplicationBase4mainEv+389>
                          <_ZN4juce19JUCEApplicationBase4mainEiPPKc+60>
                           <main+51>                            12b91d52e
2022-11-18 12:54:06.484599+0100 Arena[49017:171155] -[MTLTextureDescriptorInternal validateWithDevice:], line 1325: error 'Texture Descriptor Validation
MTLTextureDescriptor has width of zero.
MTLTextureDescriptor has height of zero.
'
-[MTLTextureDescriptorInternal validateWithDevice:]:1325: failed assertion `Texture Descriptor Validation
MTLTextureDescriptor has width of zero.
MTLTextureDescriptor has height of zero.
'
Process 49017 stopped
* thread #1, name = 'JUCE Message Thread', queue = 'com.apple.main-thread', stop reason = hit program assert
    frame #4: 0x00007ff81ea0d8a4 Metal`MTLReportFailure.cold.1 + 43
Metal`bool MTLGetEnvCase<MTLErrorModeType>(char const*, MTLErrorModeType&, std::__1::vector<std::__1::pair<char const*, MTLErrorModeType>, std::__1::allocator<std::__1::pair<char const*, MTLErrorModeType> > > const&) (.cold.1):
->  0x7ff81ea0d8a4 <+0>: pushq  %rbp
    0x7ff81ea0d8a5 <+1>: movq   %rsp, %rbp
    0x7ff81ea0d8a8 <+4>: pushq  %r15
    0x7ff81ea0d8aa <+6>: pushq  %r14
Target 0: (Arena) stopped.
(lldb) bt
* thread #1, name = 'JUCE Message Thread', queue = 'com.apple.main-thread', stop reason = hit program assert
    frame #0: 0x00007ff815f5200e libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007ff815f881ff libsystem_pthread.dylib`pthread_kill + 263
    frame #2: 0x00007ff815ed3d24 libsystem_c.dylib`abort + 123
    frame #3: 0x00007ff815ed30cb libsystem_c.dylib`__assert_rtn + 314
  * frame #4: 0x00007ff81ea0d8a4 Metal`MTLReportFailure.cold.1 + 43
    frame #5: 0x00007ff81e9f7c05 Metal`MTLReportFailure + 529
    frame #6: 0x00007ff81e9f0378 Metal`_MTLMessageContextEnd + 1278
    frame #7: 0x00007ff81e941bdf Metal`-[MTLTextureDescriptorInternal validateWithDevice:] + 3296
    frame #8: 0x00007ffa32fdac27 AMDRadeonX6000MTLDriver`-[GFXAAMD_MtlTexture initInternalWithDevice:descriptor:] + 59
    frame #9: 0x000000010112a60a Arena`juce::CoreGraphicsMetalLayerRenderer<NSView>::GpuTexturePool::GpuTexturePool(this=0x0000000164e27990, metalDevice=0x0000000148008000, descriptor=0x00006000039a0000) at juce_mac_CGMetalLayerRenderer.h:239:26
    frame #10: 0x000000010112a545 Arena`juce::CoreGraphicsMetalLayerRenderer<NSView>::GpuTexturePool::GpuTexturePool(this=0x0000000164e27990, metalDevice=0x0000000148008000, descriptor=0x00006000039a0000) at juce_mac_CGMetalLayerRenderer.h:237:9
    frame #11: 0x0000000101129161 Arena`std::__1::__unique_if<juce::CoreGraphicsMetalLayerRenderer<NSView>::GpuTexturePool>::__unique_single std::__1::make_unique<juce::CoreGraphicsMetalLayerRenderer<NSView>::GpuTexturePool, id<MTLDevice>&, MTLTextureDescriptor*&>(__args=0x00007ff7bfefdb90, __args=0x00007ff7bfefdb40) at unique_ptr.h:728:32
    frame #12: 0x0000000101128caa Arena`juce::CoreGraphicsMetalLayerRenderer<NSView>::Resources::Resources(this=0x0000000160a1f600, metalDevice=0x0000000148008000, layer=0x0000600000c06d00) at juce_mac_CGMetalLayerRenderer.h:304:30
    frame #13: 0x0000000101128535 Arena`juce::CoreGraphicsMetalLayerRenderer<NSView>::Resources::Resources(this=0x0000000160a1f600, metalDevice=0x0000000148008000, layer=0x0000600000c06d00) at juce_mac_CGMetalLayerRenderer.h:261:9
    frame #14: 0x0000000101127d21 Arena`std::__1::__unique_if<juce::CoreGraphicsMetalLayerRenderer<NSView>::Resources>::__unique_single std::__1::make_unique<juce::CoreGraphicsMetalLayerRenderer<NSView>::Resources, id<MTLDevice>, CAMetalLayer*&>(__args=0x00007ff7bfefddd8, __args=0x00007ff7bfefdec8) at unique_ptr.h:728:32
    frame #15: 0x0000000101127615 Arena`bool juce::CoreGraphicsMetalLayerRenderer<NSView>::drawRectangleList<juce::NSViewComponentPeer::setNeedsDisplayRectangles(this=0x000000012dc4f450, view=0x000000033fb5b030, scaleFactor=0, drawRectWithContext=0x00007ff7bfefdf98, dirtyRegions=0x000000033fb38da0)::'lambda0'()::operator()() const::'lambda'(CGContext*, CGRect)>(NSView*, float, juce::NSViewComponentPeer::setNeedsDisplayRectangles()::'lambda0'()::operator()() const::'lambda'(CGContext*, CGRect)&&, juce::RectangleList<float> const&) at juce_mac_CGMetalLayerRenderer.h:123:25
    frame #16: 0x0000000101126da5 Arena`juce::NSViewComponentPeer::setNeedsDisplayRectangles(this=0x00007ff7bfefdff8)::'lambda0'()::operator()() const at juce_mac_NSViewComponentPeer.mm:1092:38
    frame #17: 0x00000001011269b5 Arena`juce::NSViewComponentPeer::setNeedsDisplayRectangles(this=0x000000033fb38ce0) at juce_mac_NSViewComponentPeer.mm:1103:13
    frame #18: 0x0000000101145815 Arena`juce::NSViewComponentPeer::onDisplaySourceCallback(this=0x000000033fb38ce0) at juce_mac_NSViewComponentPeer.mm:1800:9
    frame #19: 0x00000001011457ec Arena`invocation function for block in juce::NSViewComponentPeer::createCVDisplayLink(.block_descriptor=0x0000600000c07ed0) at juce_mac_NSViewComponentPeer.mm:1825:64
    frame #20: 0x00007ff815dd1317 libdispatch.dylib`_dispatch_client_callout + 8
    frame #21: 0x00007ff815dd3d7c libdispatch.dylib`_dispatch_continuation_pop + 453
    frame #22: 0x00007ff815de5208 libdispatch.dylib`_dispatch_source_invoke + 2179
    frame #23: 0x00007ff815dddbb1 libdispatch.dylib`_dispatch_main_queue_drain + 744
    frame #24: 0x00007ff815ddd8bb libdispatch.dylib`_dispatch_main_queue_callback_4CF + 31
    frame #25: 0x00007ff81608cf37 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    frame #26: 0x00007ff81604dfcf CoreFoundation`__CFRunLoopRun + 2771
    frame #27: 0x00007ff81604ce3c CoreFoundation`CFRunLoopRunSpecific + 562
    frame #28: 0x00007ff81ecfc5e6 HIToolbox`RunCurrentEventLoopInMode + 292
    frame #29: 0x00007ff81ecfc34a HIToolbox`ReceiveNextEventCommon + 594
    frame #30: 0x00007ff81ecfc0e5 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 70
    frame #31: 0x00007ff818a86fad AppKit`_DPSNextEvent + 927
    frame #32: 0x00007ff818a8566a AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1394
    frame #33: 0x00007ff818a77d19 AppKit`-[NSApplication run] + 586
    frame #34: 0x0000000100e4ff29 Arena`juce::MessageManager::runDispatchLoop(this=0x0000000130c04250) at juce_mac_MessageManager.mm:365:13
    frame #35: 0x0000000100e4fe15 Arena`juce::JUCEApplicationBase::main() at juce_ApplicationBase.cpp:262:40
    frame #36: 0x0000000100e4fc2c Arena`juce::JUCEApplicationBase::main(argc=1, argv=0x00007ff7bfeffa58) at juce_ApplicationBase.cpp:240:16
    frame #37: 0x00000001000b2293 Arena`main(argc=1, argv=0x00007ff7bfeffa58) at Main.cpp:1685:1
    frame #38: 0x000000012b91d52e dyld`start + 462

Could you please provide a description of how you can get into this situation? I can see that a layer size of zero is problematic, but I’d like to understand what else is going on. The fix might be required somewhere else.