Hi all, I’ve been reading a lot of the posts on here having to do with OpenGL contexts. To make it short, my question is this: Is there a nice Juce-y way to create an OpenGL context when my app starts up, and have the context be guaranteed to persist (and not be destroyed) through the entire running of my app, so that my OpenGLComponent(s) will always have access to textures I’ve loaded, etc.? I really want to only have to load my textures (and shaders, fbo’s, etc.) once!!
p.s. I’m fairly experienced in native Windows OpenGL programming, so I know this is possible. I just want to know how to do it in Juce, primarily so I can have it work in cross-platform code.
Well, if you create an OpenGLComponent and don’t mess with it, then the context will mostly persist. You always need to be aware that the context can be deleted and re-created at any time though, so you must have code in place that can re-initialise it.
I understand, but that is exactly what I’m trying to avoid. In my application, users can toggle fullscreen for the OpenGLComponent (using component->addToDesktop), and they may be doing so quite often. I don’t want to have to re-initialize everything every time they go to fullscreen, and every time they go back to a window. There are a lot of textures, shaders, fbo’s, etc., in my program, and it takes a lot of time to initialize everything. It would also take more memory if I had to keep images around to re-upload them to the GPU. Is there no way to have one context guaranteed to persist? I would think that a lot of users would want this feature, based on the posts I’ve read.
I’m pretty sure there’s no way to provide a 100% guarantee that a context will never be changed, but if you want to do some investigation into behind-the-scenes tricks that could be used to keep the switches to a minimum, that’d be interesting to discuss (it’d all be very platform-specific hackery though).
Depends on what you want. I create an offscreen only context for each GPU, and keep it around for the whole app run. Each new context shares with it. This has worked well for years. I suspect there’s some problems with Linux right now, and I may have time to delve soon.
Although not the ‘same’ context, you can create some basic textures, lists, buffers in the GPU context, and they will be available to all sharers, plus you can create textures, buffers etc. in a new context, and they will persist after the context that created them is destroyed (don’t delete them on context close, obviously).
Does that give the same functionality as you need? I’m happy to share.
PS - I realize that I’ve changed how/when I create textures recently. I do need to check that things still work the way I think - I used to have a few extra offscreen only contexts that also stuck around, and now I don’t. OpenGL and multi-threading aren’t good friends, I found.
I have a GPUContext class that inherits from juce::OpenGLContext. I try to make 4 (four potential graphics cards), and each one starts up and tries to create a context on it’s designated GPU. There’s platform specific code, that can be lifted mainly from the Juce codebase, to create each context.
Since it’s an OpenGLContext subclass, just keep it around - say in your application object - and pass a pointer to it to each new OpenGLComponent.
I see. So you don’t even create an OpenGLComponent for it… interesting. That makes sense. I guess it would be nice then if the existing Juce codebase could support creating a cross-plaform OpenGLContext without an OpenGLComponent as its owner. Which I guess is what you programmed yourself, right?
Yes. A more sensible request - since this is a bit niche - is:
Please could we have an offscreen only OpenGLComponent like class? This would be capable of offscreen GPU accelerated drawing, typically to an FBO or similar (some platforms may need a hidden PBO or even hidden window (windows :? ).
The offscreen component should have a starter size, defaulting to something small, like 64x64, so it can be used as a low memory sharable context holder.
It should be able to provide textures to other components (that it has drawn), or pass images back to the CPU.
Since Jules is way into OpenGL at the moment, this could be a quite reasonable request that he may see the need for - the ability to do GPU drawing to an offscreen destination, and/or persist OpenGL resources.
I’ve got a slightly different problem from the same cause:
I have a main window with several tabs, and each tab has different OGL components. As their tab becomes focused, the ogl components will be added while all the rest are removed from the main window.
The problem is the time it takes to initialise the Opengl contexts, which is really slowing down the switching between tabs.
I believed if all of the contexts were persisted through the lifetime of the app, this time to switch would be minimal. Unfortunately since this has nothing to do with sharing of resources, Bruce’s suggestions aren’t entirely applicable here, the problem is back to context lifetime.