Port to Modern OpenGL#1296
Conversation
|
Please don't sacrifice support for old OpenGL. I have no objections if you move the current OpenGL 1.x/2.x rendering code into your abstracted interface and add OpenGL 3.x rendering as a second implementation. |
|
@s09bQ5 Thanks a lot for the review. I removed scaling the textures to power-of-two dimensions, under the assumption that all GPUs will have NPOT support (it's required in OpenGL 2.0 and later). Now that it's required to still support OpenGL 1.x, should I add support back for GPUs that don't support NPOT? Or can we make the extension mandatory for 1.x contexts? |
|
I personally am very much in favor of getting rid of the old fixed function based rendering. No need to keep that legacy code. All the other platforms will benefit from getting rid of it and switching to more current OGL. For example RaspberryPi will have much better performance even without us specifically adding GLES support. We got rid of 32-bit builds, that is much more of an issue for older setups than OpenGL 3 requirement. |
|
First off, sorry for merge-conflicting your branch, I only saw it was there at all after I already merged a bunch of things. With that out of the way, I did scroll through the branch diff a bit and I liked what I saw a lot. I remember messing around with the info bar (the one with all the rectangles when you're singing) and oscilloscopes some time ago and I also remember how often something was suddenly taking up half the screen, or invisible, etc. Bottom line: I am heavily interested in eventually merging this. As to what versions you should (or shouldn't) target, I'll defer to s09bQ5. Though personally, OpenGL 2.0 (or 1.x but requiring the NPOT extension) is perfectly valid. I can't comment on 2 vs 3 as a minimum, though I'm assuming NPOT is the biggest nightmare here anyway (but again I don't know much about this graphics internal stuff) Regarding merge conflicts, if you want to get some of the trivial renames done already (like the text one, but there's probably more) so that you don't have to constantly keep rebasing, I am okay with that. |
|
As a compromise, I could add support for OpenGL 2.0. 2.0 is at least somewhat modern in that it supports shaders and NPOT textures. I would have to adapt the code slightly, but way less than adding back the ancient 1.x fixed function stuff. Setting 2.0 as a minimum would give us at least 20 years of hardware compatibility for PCs. |
|
I'd like to again put emphasis on that we just recently dropped 32-bit support, requiring 64bit OS installs, and we just in the last release required that change. Adding the switch to OGL 3 would now fit perfectly. I checked again and from what I could find, all the typical hardware that typically comes with 64 bit OS also already supports OpenGL 3. So there would be no benefit in keeping 2.0 support around - it would just harm performance on some platforms. |
We didn't drop 32 bit support. We just stopped providing binaries for 32 bit OSes. And if I remember correctly, in the PR for that it was argued that users of 32 bit machines can still compile USDX for their systems.
Proof? Why do people think that the fixed function OpenGL API is bad? Just because Khronos renamed it to "legacy"? Why do we need shaders? Nobody has plans for visual changes that requires them. Machines that have support for OpenGL 3+ are fast enough to cope with any performance drawback of OpenGL 1.x/2.x. |
Here's an idea I have for how USDX could benefit from shader support. You've probably noticed that video decoding performance in USDX is not great. It often struggles with high resolution files. One of the reasons for this is the use of RGB textures for the video frames. Almost all video files use YUV colorspace, because it provides superior compression. But YUV data can't be displayed by the GPU. So we convert them to RGB format via the FFmpeg swresample library and then upload them to the GPU. With support for shaders, we could instead upload frames to the GPU in YUV format, and have the GPU do the YUV->RGB conversion. This would cut the memory bandwidth in half (1.5 bytes per pixel vs 3 bytes per pixel), and reduce the load on the CPU. This is one example of an optimization that can be made with shaders that isn't possible with the fixed function pipeline. |
|
The beauty of the legacy OpenGL API is that you don't have to use shaders. If they are supported, you can use them to speed things up. If not, you can continue to render the old way. |
|
This branch has reached feature parity with How to approach ProjectM will depend strongly on the versions of OpenGL that need to supported. The latest ProjectM 3.x/4.x releases require modern OpenGL (3.x). So this will be on hold until we can reach an agreement on the compatibility question. I remain in favor of dropping support for the OpenGL 1.x fixed function pipeline API in favor of the shader-based APIs. |
|
I still think that getting rid of glBegin / glEnd / fixed function pipeline would be worth it and switching to requiring OpenGL 3.3 or newer would be the best way to go forward. Any hardware released within the past 13+ years supports it. No need to maintain two rendering code paths (fixed function and shader based) concurrently. People with machines that are too old can still continue playing using previously released USDX versions. How much legacy code we decide to maintain has an impact on how fast new features and improvements of UltraStar Deluxe can be developed and tested+released. I'd like to force getting an agreement within the next few weeks, so that development on this very helpful PR can continue, and thus suggest we just vote on it. 🚀 Option 1: Maintain OpenGL 1.4+ and 2 and 3/4 compatibility for now Please vote via emoticon reaction within the next 7 days. |
|
I am on an ancient 2015 Intel Macbook Pro with an Intel Iris Graphics 6100 which fully supports OpenGL 3.3 and 4.1 Core Profile. In general, I am mostly in favor of supporting old hardware (because I am likely to be affected), but considering that even my ancient computer supports OpenGL 3, dropping support for 1.4+ and 2 is not exactly making a switch that requires brand-new hardware. |
|
You call that ancient? May I remind you of #1156, which was reported this year? That chipset is from 2008 and its GPU barely supports OpenGL 3.3. |
|
A bit of GPU history:
|
|
GPU History Continuation (2012–2026)
|
|
Thanks @s09bQ5 and @bohning for the history. That tracks closely with my estimate of ~15 years of hardware compatibility for this branch as it currently stands. As I previously mentioned, I could drop the minimum version down to OpenGL 2.0 with a little bit of added complexity to the code, but not too bad. That would get us another 5 years of hardware compatibility, to about 20 years total. Adding back the 1.X API would require a major restructuring of the code, and increase the maintenance burden in the long term. I would like to avoid that if possible. |
|
re: #1296 (comment) to add some explanation to why I picked "drop 1, keep 2.1 and above": Would a compromise be acceptable? That is:
My tertiary backup system (I hope I won't ever need it) has an X4500 HD. More pressing, until less than a year ago my main day-to-day system was a 3rd gen i3 with iGPU (~14 years old apparently), and only recently did I "upgrade" to ~9-year old hardware. But that upgrade was mostly because there's so much Personally, I'm actually fine with whatever comes out of the poll, because I have enough systems on GL3 and higher (and I really don't care about projectm at all) that it's not an issue for me. Dropping 1 seems like a sane idea to me, dropping 2 as well won't affect me personally but the "15 years of hardware compatability" is eerily close to my previous daily. |
|
@barbeque-squared Good points. I just switched my vote to Option 2. I think it's a fair compromise, and we should now have a final answer on this question. Last question I have is in regard to ProjectM. As I mentioned, we currently use very outdated ProjectM 2.x, which doesn't support OpenGL 3.x/4.x. The latest 4.x versions of ProjectM have dropped support for OpenGL 1.x/2.x. So they are mutually incompatible. I would really like to upgrade ProjectM to 4.x as there have been a lot of really good improvements to that library since 2.x, and it would greatly simplify our codebase. So users with 20 year old PCs running OpenGL 2.x would still be able to play the core game, but ProjectM would not be available. IMO this is fine since it's just an optional feature anyway. |
|
@complexlogic feel free to go ahead and switch it to ProjectM 4.x. |
|
This is now ready for review. Not going to be an easy review because of the huge diff, however, I think this is a major step forward for the game. I tested this thoroughly on Windows, Linux, and Raspberry Pi 4. Didn't test at all on Mac because I have no hardware access, but perhaps @bohning could help with that. |
|
Tested on my 2015 Intel Macbook Pro with Intel Iris Graphics 6100 and seems to work as before, couldn't notice anything of concern. Should I be looking at something in particular? As a side note: I now have |
|
From the user's perspective, there should be no noticeable changes from A difficult aspect of graphics programming is that some drivers may not be optimized in the same way as others. This branch could perform well on my PC but struggle on another PC. That's why I wanted a Mac tester, especially because Apple's OpenGL implementation is not actually a hardware driver but a compatibility layer running on top of Metal. But glad to hear it's working well. |
This incorporates the intent of 98784c8 which was lost while rebasing
|
Would it be possible to restructure the series of commits to something that is easier to review and also look at in hindsight? At the minimum having consistent meaningful commit messages, but I more and more moved to restructuring the entire commit chain and drawing the lines between commits by structure and not timeline, which makes it easier to look at one commit and understand what it does. That would be helpful here as well, considering that this is changing more than a hundred files with a 13000 line diff? |
I've been working on porting the game to modern OpenGL, which uses shaders instead of the fixed function pipeline. The port currently targets OpenGL 2.0 and OpenGL ES 2.0. It should be compatible with most PCs made in the last ~20 years.
This branch establishes a new abstract base class
TRendererfor doing drawing, with sub classes implemented by each rendering backend (currently only OpenGL and OpenGL ES). This is similar to how other systems work in USDX, such as the audio system.I have two motivations for doing this. The first is that it significantly improves the code quality of USDX. All of the OpenGL code is now contained within a single unit. No more having 100+ different pieces of code to draw a texture or quad scattered throughout various places in the codebase.
Now, this becomes
Renderer.DrawTexture,Renderer.DrawQuad,Renderer.DrawLine, etc. This is a nice abstraction, so you don't have be an OpenGL expert to work on the graphics anymore. The low level graphics code is hidden and contained.The second reason for doing this is that it improves the portability of the program. The pluggable rendering interface provides the ability to add other rendering backends in the future if we need to. OpenGL is a legacy API, and is officially deprecated on Apple platforms. For example, if Apple eventually drops OpenGL, we could keep macOS support by adding a Metal backend.
This would also allow us to upgrade ProjectM to the latest 4.x release, instead of being stuck on unmaintained 2.x. With 4.x, the ProjectM library now provides a C API, so we wouldn't need the C Wrapper library anymore. That would greatly simplify the build system.
Summary of Code Changes
Here's a high level summary of the code changes:
TRendererclass introduced for drawing, with subclasses for each rendering backendTTextureUnitclass functionality (LoadTexture,GetTexture, etc.) are now part ofTRenderer-Rendererto request a specific rendering backend (-Renderer glor-Renderer gles).TTextureis now a class instead of a record. This was needed for polymorphism (ability to support multiple rendering backends)TTextureclass, instead of being implemented separately in each of the graphics classes (TMenuButton,TStatic, text, etc).TextGLunit is nowUTextglPrintfunction is nowPrintTextglTextWidthfunction is nowTextWidth--with-local-projectM-presetswas removed. The ProjectM library no longer ships presets, so we always use the provided presets ingame/visuals/projectM. Theconfig.inpstill allows users to point to a custom preset directory if they wishUsdx.Glis nowUsdx.Renderer, andUsdx.TextGLis nowUsdx.Text. All of provided party mode plugins in this repo have been ported to use the new modules and will continue to work as they did before, but any out-of-tree party mode plugins that useUsdx.GlandUsdx.TextGLwill be broken.UMenuStaticListunitTMenu.SetAnimationProgressfunction and its overrides in subclassesTo Do