Possible crash in OpenGL renderer on OSX


#1

Hello,

 

I'm currently trying to switch from the software renderer to the OpenGL one.

I'm having a strange crash, not related to drawing in a currently cached Image outside of the OpenGL Render Thread:

 At the end of OpenGLContext::CachedImage::renderFrame(), I have "isUpdating" true and the crash occurs somewhere in "drawComponentBuffers" (it crashes on a call to glDrawArrays(), in OpenGLContext::copyTexture() ).

Since "isUpdating" is true, the Message Thread isn't locked at this point.

Meanwhile, the Message Thread is currently executing the timerCallback of ImageCache::Pimpl.

I am suspecting the ImageCache::Pimpl to be deleting an Image used in drawComponentBuffers.


#2

If you're confident that this is a juce bug rather than a mistake in your own code, could you give us a short piece of test code we could use to reproduce it?


#3

I can't reproduce it easily, it only happened in 2 debug sessions today. It might be something else. I'll update here if I can manage to reproduce/isolate it and create a prototype.

What I don't understand is why drawComponentBuffers() can be called with the Message Thread unlocked, or if it needs to be unlocked.


#4

drawComponentBuffers is ok to be called unlocked, because it should only be using internal images, so should be safe. There's nothing in there that uses images from the ImageCache, so I don't think that can be related (?)


#5

Just had another very similar crash, in the MessageThread this time:

#10 0x0000000103a9cc97 in juce::OpenGLTexture::release (this=0x1eedb2bf0) at juce_OpenGLTexture.cpp:168
#11 0x0000000103a9cb98 in juce::OpenGLTexture::~OpenGLTexture (this=0x1eedb2bf0) at juce_OpenGLTexture.cpp:41
#12 0x0000000103a9a945 in juce::OpenGLTexture::~OpenGLTexture (this=0x1eedb2bf0) at juce_OpenGLTexture.cpp:40
#13 0x0000000103aaf1b0 in juce::OpenGLRendering::CachedImageList::CachedImage::~CachedImage (this=0x1eedb2be0) at juce_OpenGLGraphicsContext.cpp:102
#14 0x0000000103aaf0d5 in juce::OpenGLRendering::CachedImageList::CachedImage::~CachedImage (this=0x1eedb2be0) at juce_OpenGLGraphicsContext.cpp:99
#15 0x0000000103aaf08a in juce::ContainerDeletePolicy<juce::OpenGLRendering::CachedImageList::CachedImage>::destroy (object=0x1eedb2be0) at juce_ContainerDeletePolicy.h:48
#16 0x0000000103aaf058 in juce::ScopedPointer<juce::OpenGLRendering::CachedImageList::CachedImage>::~ScopedPointer (this=0x7fff5fbfd708) at juce_ScopedPointer.h:100
#17 0x0000000103aaf035 in juce::ScopedPointer<juce::OpenGLRendering::CachedImageList::CachedImage>::~ScopedPointer (this=0x7fff5fbfd708) at juce_ScopedPointer.h:100
#18 0x0000000103aaef0c in juce::OwnedArray<juce::OpenGLRendering::CachedImageList::CachedImage, juce::DummyCriticalSection>::remove (this=0x1911894b0, indexToRemove=895, deleteObject=true) at juce_OwnedArray.h:606
#19 0x0000000103abc3bf in juce::OpenGLRendering::CachedImageList::imageDataBeingDeleted (this=0x191189490, im=0x1eedb4100) at juce_OpenGLGraphicsContext.cpp:161
#20 0x0000000103abc4af in non-virtual thunk to juce::OpenGLRendering::CachedImageList::imageDataBeingDeleted(juce::ImagePixelData*) (this=0x1911894a0, im=0x1eedb4100) at juce_OpenGLGraphicsContext.cpp:171
#21 0x000000010385ee3e in juce::ListenerList<juce::ImagePixelData::Listener, juce::Array<juce::ImagePixelData::Listener*, juce::DummyCriticalSection, 0> >::call<juce::ImagePixelData*> (this=0x1eedb4138, callbackFunction=
) at juce_ListenerList.h:167
#22 0x00000001037e1eec in juce::ImagePixelData::~ImagePixelData (this=0x1eedb4100) at juce_Image.cpp:34
#23 0x00000001038c009f in juce::CoreGraphicsImage::~CoreGraphicsImage (this=0x1eedb4100) at juce_mac_CoreGraphicsContext.mm:52
#24 0x00000001038bfd15 in juce::CoreGraphicsImage::~CoreGraphicsImage (this=0x1eedb4100) at juce_mac_CoreGraphicsContext.mm:49
#25 0x00000001038bfd38 in juce::CoreGraphicsImage::~CoreGraphicsImage (this=0x1eedb4100) at juce_mac_CoreGraphicsContext.mm:49
#26 0x00000001038b8ade in juce::ContainerDeletePolicy<juce::ImagePixelData>::destroy (object=0x1eedb4100) at juce_ContainerDeletePolicy.h:48
#27 0x00000001038b8a8c in juce::ReferenceCountedObjectPtr<juce::ImagePixelData>::decIfNotNull (o=0x1eedb4100) at juce_ReferenceCountedObject.h:366
#28 0x00000001038b8e78 in juce::ReferenceCountedObjectPtr<juce::ImagePixelData>::~ReferenceCountedObjectPtr (this=0x1eedb0df0) at juce_ReferenceCountedObject.h:327
#29 0x000000010385ef75 in juce::ReferenceCountedObjectPtr<juce::ImagePixelData>::~ReferenceCountedObjectPtr (this=0x1eedb0df0) at juce_ReferenceCountedObject.h:326
#30 0x00000001037e2b9a in juce::Image::~Image (this=0x1eedb0df0) at juce_Image.cpp:254
#31 0x00000001037c9525 in juce::Image::~Image (this=0x1eedb0df0) at juce_Image.cpp:253
#32 0x00000001038c7ef5 in juce::ImageCache::Pimpl::Item::~Item (this=0x1eedb0df0) at juce_ImageCache.cpp:139
#33 0x00000001038c7ed5 in juce::ImageCache::Pimpl::Item::~Item (this=0x1eedb0df0) at juce_ImageCache.cpp:139
#34 0x00000001038c7e8a in juce::ContainerDeletePolicy<juce::ImageCache::Pimpl::Item>::destroy (object=0x1eedb0df0) at juce_ContainerDeletePolicy.h:48
#35 0x00000001038c7e58 in juce::ScopedPointer<juce::ImageCache::Pimpl::Item>::~ScopedPointer (this=0x7fff5fbfdae8) at juce_ScopedPointer.h:100
#36 0x00000001038c7e35 in juce::ScopedPointer<juce::ImageCache::Pimpl::Item>::~ScopedPointer (this=0x7fff5fbfdae8) at juce_ScopedPointer.h:100
#37 0x00000001038c7cec in juce::OwnedArray<juce::ImageCache::Pimpl::Item, juce::DummyCriticalSection>::remove (this=0x10c4466a0, indexToRemove=6344, deleteObject=true) at juce_OwnedArray.h:606
#38 0x00000001038c79f5 in juce::ImageCache::Pimpl::timerCallback (this=0x10c446670) at juce_ImageCache.cpp:118

With the OpenGL render thread being at the same point as last times:

#11 0x00007fff879c48e7 in glDrawArrays_ACC_Exec ()
#12 0x0000000103a99fe2 in juce::OpenGLContext::copyTexture (this=0x10c9fa110, targetClipArea=@0x1ad12ad18, anchorPosAndTextureSize=@0x1ad12ad18, contextWidth=1280, contextHeight=698, flippedVertically=false) at juce_OpenGLContext.cpp:933
#13 0x0000000103aa5c3a in juce::OpenGLContext::CachedImage::drawComponentBuffer (this=0x1a386d6e0) at juce_OpenGLContext.cpp:293
#14 0x0000000103aa5697 in juce::OpenGLContext::CachedImage::renderFrame (this=0x1a386d6e0) at juce_OpenGLContext.cpp:203
#15 0x0000000103aa6a71 in juce::OpenGLContext::CachedImage::run (this=0x1a386d6e0) at juce_OpenGLContext.cpp:375
#16 0x0000000103aa6b5c in non-virtual thunk to juce::OpenGLContext::CachedImage::run() (this=0x1a386d6e8) at juce_OpenGLContext.cpp:382

 


#6

Are you using your own GL images that you're keeping in the ImageCache?


#7

Not sure what you mean, but I would answer no: I only create software juce::Image, as it was when using the software renderer.

The only Images create/deleted (that I'm aware of) are buffered images of a waveform, created when needed, then scrolled, then released when obsolete.

They are created as such (from OpenGL render thread):

Image image(Image::ARGB, width, height, true);

Graphics g(image);

/* painting in g */

Painted (displayed) multiple times with successive calls to drawImageAt().

And image is released (deleted) when considered obsolete, in OpenGL render thread as well.


#8

All my assumptions were wrong. Locking the MessageThread for drawComponentBuffers doesn't help and neither does deactivating the mentioned waveform...

I found something horrible in the code: a png decoded from a BinaryBuilt resource in a paint callback, at each paint... Removing this helped a bit, but now it still crashes after about 35 minutes of run time, each time, but only on an Intel HD 3000 on OSX (Yosemite). The crash happens in glDeleteTexture(). I saw another thread talking about this exact same issue, I will post my feedback there.

Thanks.


#9

Yeah, I'll look into this soon, it may be something that needs to be fixed in the GL image caching code.