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.

This still happens with latest Juce

I get some crash report that looks like this as soon as some users are using Roseta, Logic and JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 AGXMetalG13X 0x7ffa234f9e44 0x7ffa232b5000 + 2379332
1 SparkVerb 0x161f2defd juce::RectangleList juce::CoreGraphicsMetalLayerRenderer::drawRectangleListjuce::NSViewComponentPeer::displayLayer(CALayer*):‘lambda’(auto&&...)(CAMetalLayer*, float, juce::NSViewComponentPeer::displayLayer(CALayer*)::‘lambda’(auto&&…)&&, juce::RectangleList, bool) + 1517
2 SparkVerb 0x161f297d9 juce::NSViewComponentPeer::displayLayer(CALayer*) + 217
3 SparkVerb 0x161f2c2b3 juce::JuceCALayerDelegate::JuceCALayerDelegate()::‘lambda’(objc_object*, objc_selector*, CALayer*)::__invoke(objc_object*, objc_selector*, CALayer*) + 51
4 QuartzCore 0x7ff81aec8a07 CA::Layer::display_if_needed(CA::Transaction*) + 873
5 QuartzCore 0x7ff81b0202aa CA::Context::commit_transaction(CA::Transaction*, double, double*) + 640
6 QuartzCore 0x7ff81aea9e6d CA::Transaction::commit() + 777
7 AppKit 0x7ff816467191 __62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke + 285
8 AppKit 0x7ff816baef1c ___NSRunLoopObserverCreateWithHandler_block_invoke + 41
9 CoreFoundation 0x7ff81398a6d5 CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 23
10 CoreFoundation 0x7ff81398a56a __CFRunLoopDoObservers + 543
11 CoreFoundation 0x7ff8139899ec __CFRunLoopRun + 840
12 CoreFoundation 0x7ff813988fe4 CFRunLoopRunSpecific + 562
13 HIToolbox 0x7ff81caa75e6 RunCurrentEventLoopInMode + 292
14 HIToolbox 0x7ff81caa734a ReceiveNextEventCommon + 594
15 HIToolbox 0x7ff81caa70e5 _BlockUntilNextEventMatchingListInModeWithFilter + 70
16 AppKit 0x7ff8162faf6d _DPSNextEvent + 927
17 AppKit 0x7ff8162f962a -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1394
18 Logic Pro X 0x10456885d 0x102d45000 + 25311325
19 AppKit 0x7ff8162ebcd9 -[NSApplication run] + 586
20 AppKit 0x7ff8162bfc57 NSApplicationMain + 817
21 Logic Pro X 0x10383565d 0x102d45000 + 11470429
22 dyld 0x2056b752e start + 462

Looks like to be related to M1 Max as well
Model: Mac13,1, BootROM 8422.121.1, proc 10:8:2 processors, 64 GB, SMC
Graphics: Apple M1 Max, Apple M1 Max, Built-In

Unfortunately I cannot reproduce it as I don’t have such hardware.