-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add support for invalidation on OpenGL renderer #20073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
d7af8ef
to
e386258
Compare
Things to do:
|
I ran into a bug as well:
|
Thanks, updated my comment, noticed this before but forgot to put it there. |
0ee7f57
to
134e413
Compare
This comment was marked as duplicate.
This comment was marked as duplicate.
The issue with the options window is unrelated: #20312 |
fd3944a
to
8557de1
Compare
I think I've got all working now, even software will gain quite a major improvement here. On develop I get about 170 FPS on bpb.sv6 at the default zoom and on this PR it is 350 and without the rain it nearly hits 400. |
This comment was marked as outdated.
This comment was marked as outdated.
There are still some oddities that needs fixing, IntelOrca and others found some issues. |
This pull request has been marked as stale and will be closed in 14 days if no action is taken. To keep it open, leave a comment or remove the |
Did you manage to fix the remaining issues @ZehMatt ? |
Sort of, there is however a regression in performance with OpenGL which is odd considering it has to draw less 🤷♂️ I will get back to this eventually. There needs to be some general cleanup around the rendering code tbh. |
The title screen positioning has been fixed now. I think that this invalidation is now working correctly. I do have a couple of things I wanted to mention though: I hope that a fix for the clipped sprites will go in soon after this, otherwise the game is considerably more glitchy (depending on the park) now with no workaround. Performance is worse now in large complicated parks which are probably invalidating the majority of the screen on every frame. This was the case for software too when I tested it a while ago. I believe that invalidation can sometimes cause many more column draws than just redrawing the entire screen. A park like The Screameasy is a good example of both. All the signs and many other parts trigger the clipping bug, and perf is down too. |
The minor performance regression is a bit odd but I also get the same here, turns out that OpenGL is faster sometimes when it has to redraw everything which feels a bit illogical but the goal here first is to have parity with Software, also the abstraction how this currently works is quite bad, most of it is duplicate code and way to OOP oriented. Also the performance regression is very small the more complex the park. I will do some more PRs after this one now that it is at least fully functional I can focus on making it better. As for the clipping I will have to also experiment around with it, I think the way it culls is too primitive and should best consider the entire hierarchy as in all attached child nodes, the reason it flickers is probably that when the root node is out of bounds it picks one of the next children as the new root so it will potentially draw in a different order. |
I'm still a bit confused about what you mean with the hierarchy and the nodes. The culling is happening at the point where a sprite is painted, if it gets culled, it doesn't get added in the first place. Am I missing something? |
This is not quite correct, it is culled when it creates the graph before its sorted and is then rendered. Anyway I've improved the InvalidationGrid quite a bit and now OpenGL outperforms develop in majority of cases on my end. I will look into the clipping of sprites afterwards but ideally not in this PR. What I mean by the nodes, have a look at the following code: PaintStruct* PaintAddImageAsChild(
PaintSession& session, const ImageId image_id, const CoordsXYZ& offset, const BoundBoxXYZ& boundBox)
{
PaintStruct* parentPS = session.LastPS;
if (parentPS == nullptr)
{
return PaintAddImageAsParent(session, image_id, offset, boundBox);
}
...
} LastPS is perhaps a bit of a bad name, this should be LastRootPS/LastParentPS as that is always the last node (PaintStruct) created by PaintAddImageAsParent and in case PaintAddImageAsParent is culling it away it will be set to null making the next child the parent instead. The way it partially chips away things isn't good. It is probably best to move the culling stage after the entire graph is built, right now it only orders it but it doesn't remove anything, there are probably cases where it would still draw something even when it would be fully covered by lets say a wall. |
Ah okay I get you, I knew about the child sprite issue but in my head I had separated the two things even though I know it's part of the same thing. And yeah I wasn't meaning for you to do this in this PR, I just wanted to check if it was intended at all. |
At maximum zoom out this seems to cause a lot of things to stop rendering for multiple frames at a time. It's the same as on the software renderer. 2025-04-25.20-28-35.mp4Apologises for the low quality, but you should still be able to see the issue here. |
Does this also happen on the develop branch? Edit: Just tested and that is indeed an issue already in develop, rides probably don't invalidate at this zoom level but the game sometimes refreshes the entire screen which renders everything again for that frame. This is a separate issue, we could check for some rides that are larger like ferris wheels and also invalidate for that zoom, but this should be all done in a separate PR. |
This has made the (known) issues with invisible supports over water way worse in OpenRCT2-v0.4.21-151-g0d96235f32-linux-x86_64.AppImage: flickering_paths.mp4I did some bisecting with older dev builds, and this is the first with this issue. |
waterglitch.mp4It looks like it is not drawing the same sprites when the paint area gets clipped. Similar to the previous glitching i've been going on about. Will try and fix this later. |
- Feature: [#24206] [Plugin] Add APIs for breaking down rides, reading the current breakdown, and for fixing broken down rides. - Improved: [#20073] The OpenGL drawing engine now supports screen invalidation which avoids the redrawing of unchanged regions. - Improved: [#21767] RCT Classic for macOS can now be used as the source game. - Improved: [#23590] Title bars are now drawn bigger when “Enlarged UI” is enabled. - Improved: [#23626] Add small, medium and large flat and sloped turns, S-bends and diagonal track to the Go-Karts. - Improved: [#23982] The scenario objective window has been merged into the scenario options window. - Improved: [#24233] RCT Classic+ from Apple Arcade can now be used as the source game, and is detected automatically. - Improved: [#24260] Better performance on parks that have a lot of Guests and Entertainers. - Improved: [#24319] RCT Classic installs via Steam are now detected automatically on Windows. - Change: [#23803] Lightning strikes and thunder now happen at the same frequency independently of the game speed. - Change: [#23857] Replace display options tab with custom sprites. - Change: [#24069] [Plugin] Plugins are now available in the scenario editor and track designer. - Change: [#24135] Compress Emscripten js/wasm files. - Change: [#24194] The advanced options tab has been reworked to make it easier to find the RCT1 path setting. - Change: [#24235] Small changes to RCT1 theme. - Change: [#24236] Controls and Interface options now both have their own tabs in the Options window. - Change: [#24308] “Software” and “Software (hardware display)” renderers have been merged into a single “Software” renderer. - Change: [#24317] The scenery window now shows at least one row of scenery objects, even if there are multiple rows of tabs. - Fix: [#18479] Tile elements ordered beneath water do not draw correctly. - Fix: [#19782] Game stops counting inversions and golf holes after 31 (original bug). - Fix: [#21207] Track List window gets positioned incorrectly. - Fix: [#21919] Non-recolourable cars still show colour picker (original bug). - Fix: [#22182] [Plugin] Crash when using map.getAllEntities("car"). - Fix: [#22634] Asset packs with sound effect overrides are not loaded correctly at startup. - Fix: [#23108] Missing pieces on Hypercoaster and Hyper-Twister, even with the ‘all drawable track pieces’ cheat enabled. - Fix: [#24013] Failure to load a scenario preview image (minimap) could lead to an uncaught exception error message. - Fix: [#24045] [Plugin] Data storage is not cleared when converting save game to scenario. - Fix: [#24121] Checkbox labels run beyond the edge of the window if they’re too long to fit. - Fix: [#24142] [Plugin] Track origin is miscalculated on downward slopes. - Fix: [#24220] Narrow station platforms have missing sides on certain rotations. - Fix: [#24286] Steam installs of RCT1 and RCT2 are not autodetected on macOS. - Fix: [#24310] [Plugin] Missing invalidation on various plugin api setters for entities.
I'm catching up on some of the changes made when I wasn't active on the project, and came across this PR (after discussing it with @ZehMatt on Discord). Honestly, I'm of the opinion that this was probably a mistake. GPU rendering is based heavily on parallelism, and adding any sort of data dependency (where one operation relies on the result of another) reduces that parallelism. This change causes an inter-frame data dependency, where the GPU can't start rendering the next frame until the previous frame has completely finished rendering. Considering that this already has some pretty heavy intra-frame data dependencies for transparency drawing, I'm concerned by how much this affects throughput. I was testing a fairly busy park across v0.4.21 (the last release before this change) and v0.4.22 (the first release with this change), and found that the framerate using OpenGL seemed to drop from around 30-36 fps to more like 24-30 fps. Yes, invalidation can make more static scenes render faster, but at the cost of making the more involved scenes, which needs the framerate more, have notably worse performance. |
There are some minor quirks remaining, the rain is currently not drawing correctly and sometimes when panning a few stray pixels will appear from the toolbar somehow. Other than that its mostly fine for testing, this dramatically increases the performance on large parks where nothing is really going on.


Here is an example:
develop:
PR:
I'll have it in draft until I fix the remaining things, there might be other broken things so this is a good opportunity to start testing early.