OpenGL renderer Graphics object re-use?

I’m working on performance optimization and by far the largest consumer of CPU is the creation of a Graphics object for each OpenGL frame. I’ve tried various ways to cache this Graphics object, but it always leads to crashes. For example, I’ve tried recreating this object each time the OpenGL renderer is recreated.

Is there any fundamental reason why this object can’t be cached? Does it really need to be recreated 60x per second when that is your target framerate?

This problem only occurs because I need a Graphics object in order to render text. Everything else is done using the OpenGL API and when I remove the text rendering and Graphics object creation, performance is profoundly better.

Without understanding what the crash is, it is hard to speculate. Is it a crash or are you hitting an assert?

It actually works for drawing rectangles but crashes in drawText, deep into the graphics driver. I’m assuming this is because I have other code which calls OpenGL functions and this conflicts with the state in some way. However, I don’t see the way to properly handle that, if it exists currently.

This is all occurring inside renderOpenGL, and the only difference in the code is whether or not I created a new Graphics object every time renderOpenGL is called. It seems like there ought to be some way to reset the context or something, but I’m bumping up against the limits of my knowledge of OpenGL and JUCE’s implementation of OpenGL backed Graphics contexts.

I’ve tried saveState/restoreState in various locations, but again not really sure even theoretically what I’m missing here.

nvoglv64.dll!00007ffaa46ca912() (Unknown Source:0)
nvoglv64.dll!00007ffaa4327c76() (Unknown Source:0)
opengl32.dll!00007ffab5297504() (Unknown Source:0)
APU Loudness Compressor.exe!juce::OpenGLRendering::StateHelpers::ShaderQuadQueue::draw() Line 1298 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_opengl\opengl\juce_OpenGLGraphicsContext.cpp:1298)
APU Loudness Compressor.exe!juce::OpenGLRendering::StateHelpers::ShaderQuadQueue::add(int x, int y, int w, int h, juce::PixelARGB colour) Line 1228 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_opengl\opengl\juce_OpenGLGraphicsContext.cpp:1228)
APU Loudness Compressor.exe!juce::OpenGLRendering::StateHelpers::EdgeTableRenderer<juce::OpenGLRendering::StateHelpers::ShaderQuadQueue>::handleEdgeTablePixel(int x, int alphaLevel) Line 901 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_opengl\opengl\juce_OpenGLGraphicsContext.cpp:901)
APU Loudness Compressor.exe!juce::EdgeTable::iterate<juce::OpenGLRendering::StateHelpers::EdgeTableRenderer<juce::OpenGLRendering::StateHelpers::ShaderQuadQueue>>(juce::OpenGLRendering::StateHelpers::EdgeTableRenderer<juce::OpenGLRendering::StateHelpers::ShaderQuadQueue> & iterationCallback) Line 190 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\geometry\juce_EdgeTable.h:190)
APU Loudness Compressor.exe!juce::OpenGLRendering::StateHelpers::ShaderQuadQueue::add<juce::EdgeTable>(const juce::EdgeTable & et, juce::PixelARGB colour) Line 1263 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_opengl\opengl\juce_OpenGLGraphicsContext.cpp:1263)
APU Loudness Compressor.exe!juce::OpenGLRendering::SavedState::fillWithSolidColour<juce::EdgeTable const>(const juce::EdgeTable & iter, juce::PixelARGB colour, bool replaceContents) Line 1723 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_opengl\opengl\juce_OpenGLGraphicsContext.cpp:1723)
APU Loudness Compressor.exe!juce::RenderingHelpers::ClipRegions<juce::OpenGLRendering::SavedState>::EdgeTableRegion::fillAllWithColour(juce::OpenGLRendering::SavedState & state, juce::PixelARGB colour, bool replaceContents) Line 1765 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\native\juce_RenderingHelpers.h:1765)
APU Loudness Compressor.exe!juce::RenderingHelpers::SavedStateBase<juce::OpenGLRendering::SavedState>::fillShape(juce::ReferenceCountedObjectPtr<juce::RenderingHelpers::ClipRegions<juce::OpenGLRendering::SavedState>::Base> shapeToFill, bool replaceContents) Line 2461 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\native\juce_RenderingHelpers.h:2461)
APU Loudness Compressor.exe!juce::OpenGLRendering::SavedState::drawGlyph(int glyphNumber, const juce::AffineTransform & trans) Line 1678 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_opengl\opengl\juce_OpenGLGraphicsContext.cpp:1678)
APU Loudness Compressor.exe!juce::RenderingHelpers::StackBasedLowLevelGraphicsContext<juce::OpenGLRendering::SavedState>::drawGlyph(int glyphNumber, const juce::AffineTransform & t) Line 2725 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\native\juce_RenderingHelpers.h:2725)
APU Loudness Compressor.exe!juce::GlyphArrangement::draw(const juce::Graphics & g, juce::AffineTransform transform) Line 742 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\fonts\juce_GlyphArrangement.cpp:742)
APU Loudness Compressor.exe!juce::`anonymous namespace'::ConfiguredArrangement::draw(const juce::Graphics & g) Line 56 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\contexts\juce_GraphicsContext.cpp:56)
APU Loudness Compressor.exe!juce::`anonymous namespace'::GlyphArrangementCache<`juce::Graphics::drawText'::`2'::ArrangementArgs>::draw<juce::`anonymous-namespace'::ConfiguredArrangement <lambda>(const juce::Graphics::drawText::__l2::ArrangementArgs &)>(const juce::Graphics & g, juce::Graphics::drawText::__l2::ArrangementArgs && args, juce::Graphics::drawText::__l2::juce::`anonymous-namespace'::ConfiguredArrangement <lambda>(const juce::Graphics::drawText::__l2::ArrangementArgs &) && configureArrangement) Line 104 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\contexts\juce_GraphicsContext.cpp:104)
APU Loudness Compressor.exe!juce::Graphics::drawText(const juce::String & text, juce::Rectangle<float> area, juce::Justification justificationType, bool useEllipsesIfTooBig) Line 445 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\contexts\juce_GraphicsContext.cpp:445)
APU Loudness Compressor.exe!juce::Graphics::drawText(const juce::String & text, juce::Rectangle<int> area, juce::Justification justificationType, bool useEllipsesIfTooBig) Line 454 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\contexts\juce_GraphicsContext.cpp:454)
APU Loudness Compressor.exe!juce::Graphics::drawText(const juce::String & text, int x, int y, int width, int height, juce::Justification justificationType, bool useEllipsesIfTooBig) Line 460 (c:\Aaron\3rd-party\JUCE-7.0.5\modules\juce_graphics\contexts\juce_GraphicsContext.cpp:460)
APU Loudness Compressor.exe!LoudnessVisualizationComponent::drawTextBubble(juce::Graphics & graphics, const char * text, float posX, float posY, LoudnessVisualizationComponent::TextBubblePosition position, bool background, bool constrain) Line 1247 (c:\Aaron\Projects\GitHub\APU\modules\apu_loudness\LoudnessVisualizationComponent.cpp:1247)

Search the for Graphics object thread, and I believe you will find posts that relate to your issue. But not ones with any solutions.

1 Like