New OpenGL Scheme prevents sharing

Well, the NativeContext class is a Pimpl, so I certainly don’t want to expose it in any way… it’s really just there for handling native OS stuff behind the scenes.

Well, next one down is a void* to the actual platform context. Do the subclasses need to know anything other than that?

Bruce

I’ll need to have a think about this one…

1 Like

How about this -

NativeContext takes a raw context pointer to share with instead of a NativeContext*, and getRawContext() in OpenGLContext is virtual.

That way, there’s no exposure.

I wonder if over-protecting NativeContext is worthwhile, btw. Any other context that is intended to be shared with it would have involved complex OpenGL and platform work.

Bruce

Hang on, I’m confused here… What’s wrong with OpenGLContext::setContextToShareWith? Does it not work?

setContextToShareWith takes an OpenGLContext. The problems then are:

  • There isn’t an offscreen OpenGLContext in Juce, and OpenGLContext won’t make an actual context unless assigned a component.

  • OpenGLContext is not set up to be a base class, so can’t be replaced by a custom, offscreen capable version.
    Amongst other problems, it actually looks for a NativeContext when sharing, and that’s even harder to subclass.

  • A share from another non-Juce OpenGLContext can’t be wrapped and used - it can’t provide the hidden NativeContext.

So, it’s impossible to have a consistent share context, that survives the comings and goings of Juce contexts, and/or to share something that doesn’t rely on juce.

Being able to get the raw context from an OpenGLContext is helpful, but the other way around would be better - a GUI element would tend to be more transient than a global share context that ‘holds’ resources in shareable way for a certain GPU (on Mac, should be able to share between all GPUs these days).

Bruce

I’m agree with Bruce, setContextToShareWith is not enough to share from raw native GL contexts (HGLRC…) created without Juce.
For this, I had to made ugly Juce code modifications. (http://www.rawmaterialsoftware.com/viewtopic.php?f=2&t=9108)
Bruce’s modifications seem to be the cleanest way to do this.

I have a feeling Jules will object to OpenGLContext being subclassed. It does so much, using it as a base class to get one feature seems wrong.

So I have a proposal that better fits the way I want to use sharing, hopefully it fits with o=your cases?

class OpenGLShareGroup

Each new OpenGLContext can share with it or not. Resources can be registered with it, much like with an OpenGLContext, but they will now be shut down when the last context in the group shuts down, or the group itself shuts down.

At some point we could add a ‘persistent’ flag that would allow an offscreen context to be created.

A key advantage would be that no other contexts are needed. Currently, AFAICT, CachedComponentImages use their own context - Jules, context switching in the middle of a rendering pass is a big non-no. Now any work that needs to be done on a context can be done on any context in the group. So, for instance, if I want to make an Image available as a texture, I add it to the share group. Now, the first context that wants to render with it will create the texture (will involve some locking, but no context switching). It’s then available to any members of the group, and it’s still available even if one or all classes disappear.

class OpenGLShareGroupMember

a fairly lightweight ABC class that links to and from the share group. It should be lightweight enough that external, non-juce contexts can be wrapped and join the group, or the group can start with a non-juce context.

Any comments? I’d love to be able to not roll my own offscreen contexts, and it should improve the current Juce GL system.

It should also be relatively simple to implement with a minimum feature set: just the OpenGLShareGroupMember class as an ABC for sharing, thereby no misuse of the heavyweight OpenGLContext class.

setContextToShareWith (OpenGLShareGroupMember* share)

or

setContextShareGroup (OpenGLShareGroup::Ptr shareGroup)

Bruce

Nice interface Bruce!

Also, sharing is caring!!!

My initial thoughts on this were that I could just change the setContextToShareWith method to make it take a raw context handle instead of an OpenGLContext pointer, so you could either create that native context object yourself, or just get it from an existing OpenGLContext… What would be the advantages of using your OpenGLShareGroup idea instead?

That solution is fine too, but:

It addresses what people are trying to do, adding it as a juce capability.

In terms of stuff you may be concentrating on, it would allow resources (display lists, textures etc.) to be resident on the GPU even if a context is created and has to be recreated. That obviously has a positive effect on frame rates and responsiveness.

It also makes a stable well defined place for non-juce or juce OpenGL stuff to share with, without lifecycle issues.

Meanwhile, I had noticed that the CachedComponentImage creates a context. That may well be fine, but I do see some potential issues - the whole thing would probably have to be recreated if the main context has to be, and it doesn’t seem to have hooks to move, so the whole thing would have to be retransferred to GL (that’s the sort of thing you end up obsessing about when working on frame rates - times that GPU and CPU have to work together), but mostly importantly - if you’re actually using that context, switching to it has a big cost. It’s far better to have a context around to share with, but actually do the drawing on the thread and context that is making your visible results.

It also keeps some void pointers (more) out of the mix, so could avoid some pointer/deleted object related crashes.

Bruce

Edit/PS - it’s really whether you believe sharing is a useful feature for the majority. I was hoping some other OpenGL focussed users would jump in… it moves it from an ‘as well/not impossible’ to a feature. If did decide to do it, and has to go on the list for down the road, please do make the void* changes so it’s usable as is.

Ok, I’m probably being a bit thick, but I’m struggling a bit to see exactly what you mean with this… I’m going to do the void* change for now, because that’s a 5-minute job, and maybe you could sketch out your thoughts about this other idea - perhaps if I saw some code I’d understand the point!

The latest version doesn’t build on Windows.

Damn, could have sworn that I checked that… Thanks, it’s fixed now!

I have it in my head, but I’m a bit jammed. Will do.

Bruce

So actually, C++ is now your mother tongue, as English doesn’t fit anymore ?

I’d tend to follow Bruce idea, as I’ve hard time optimizing my code to reach the 60fps target, and context switching was an issue. I had to change the visibility of the method “isContextActive()” and perform a “if (!isContextActive()) makeCurrentContextActive()” because calling makeCurrentContextActive() unconditionnaly took milliseconds! (even if already active).

Some days, after a long programming session, I do feel a bit like that…

i.e like this?

Time stopProg = Time::now();
if ((stopProg - startProg).hours() > 6)
     throw EnglishAsLanguage();

Hi All,

I’m a new comer to JUCE and the forum, but I am very interested in the OpenGL development. Looking at this thread, I’m wondering if there has been any progress on allowing offscreen rendering using gl? Maybe it is currently possible and I misread this thread/the docs? Thanks in advance!

-Nick

Well, it’s always been possible to render off-screen, by drawing into a frame buffer - there’s even an OpenGLFrameBuffer class, and I do lots of off-screen rendering internally in the graphics code… Obviously like with all GL code everywhere, you can only draw while your thread has an active GL context, so you have to do it in the rendering callbacks, but it does work!