OpenGL rework ready to try edge cases?


#1

Jules, I see a fairly big GL check-in. Should those of us with specific OpenGL needs and edge cases start testing it yet?

Do you have a moment to recap the design while it’s fresh in your mind?

Bruce


#2

You call that big? Hah!

Well, I looked at a few diffs…it seems just like some grooming and no real changes in functionality (the comment says “refactoring”)


#3

No, no, no! That’s just a gradual step along the way…

A quick summary of what I’m moving towards: I think I’ll get rid of the OpenGLComponent class altogether. Instead, you’ll create an OpenGLContext object, and attach it to any component, and it will use that component for rendering.

As well as using GL to do the component’s rendering, there’ll also be a pure virtual class called OpenGLRenderer which your component can implement, to add methods like renderOpenGL(), newContextCreated(), etc., so if you implement that, it’ll let you do your custom GL rendering.

By decoupling the context creation/deletion from the component, it makes it easy to do things like e.g. change the pixel format by deleting your GL context and attaching a new one, without the component needing to know anything about that sort of functionality.

I also think I’ll make all the GL rendering happen on a background thread - that already works pretty well, and I can’t really think of a reason to complicate things by having two different threading modes. But let me know if there’s a reason to keep the old UI-threaded rendering!


#4

Sounds fair. I’m not 100% certain that we couldn’t have a quick-ish thread and work it out that the built-in contexts covered 90% of the cases anyway, but it seems like a good way to go.

[quote=“jules”]By decoupling the context creation/deletion from the component, it makes it easy to do things like e.g. change the pixel format by deleting your GL context and attaching a new one, without the component needing to know anything about that sort of functionality.

I also think I’ll make all the GL rendering happen on a background thread - that already works pretty well, and I can’t really think of a reason to complicate things by having two different threading modes. But let me know if there’s a reason to keep the old UI-threaded rendering![/quote]

There may be some issues with inter-thread sync…

In my ideal world, the standard juce components would be 2d ARGB textures placed in a 3D world. The component animator would be able to animate them in the 3D space. But some components re-draw fairly frequently, and it seems fair that casual users can expect to just deal with main thread issues, so there’s an interlock that will appear between the two threads. I guess, if a redraw is triggered as usual, when GL comes around to drawing, it will see that it needs a ‘fresh copy’ of the component. That would require GL and main thread to synchronize = bad. A fairly common workaround is to have a one frame lag - the GL thread places an order for the fresh copy, and it happens on the main thread and marks that there is fresh data.

I hope you know what you’re getting into! You seem more likely to solve it than anyone I can think of!

If you get there, and want to know the results of my painful battles with cross-platform, cross-vendor, fast, low blockage data transfers onto GPUs, let me know.

Bruce

PS, well actually, here’s a reasonable method:

GL draw thread runs, notices that a sub-component (or itself) needs to be redrawn,

GL creates (or better, pulls from a pool) a PBO of the same size as the component plus decorations and ‘maps’ the buffer to CPU accessible memory,

On the main thread (if required: maybe the user could flag the component or something as multithread safe, in which case drawing would happen on a 3rd thread (NOT the GL thread)), the component gets redrawn into the buffer, and the buffer gets atomically tagged as ready,

Next frame (or a few frames later), the GL would notice the tag, and trigger a transfer into a texture, using the previously mapped PBO, and then draw with that texture until a replacement is ready.

Please - do not attempt multithreaded GL right now, except for the unavoidable case of multiple windows/contexts. The hardware and drivers just don’t support it well - all of a GPU’s parallelism happens long after the CPU has stepped back, and access from another thread just disrupts that.