veeenu / hudhook

A videogame overlay framework written in Rust, supporting DirectX and OpenGL
MIT License
167 stars 27 forks source link

Per-engine compositors #156

Closed veeenu closed 4 months ago

veeenu commented 4 months ago

I come to you, dear community, with a PR that would infuse a merciless sense of dread even in the hearts of the greatest practitioners of Zen meditation alive.

immagine

This PR is close to a full rewrite of hudhook's core. The plan is to carefully review every single file and running extensive tests before smashing the green button, but the quality has in my opinion improved greatly.

2024-02-24_164233 2024-02-24_164331 2024-02-24_164442 2024-02-24_164050

Changes

Unified renderer

We stay the course with the single imgui renderer as of the previous PR #143.

The single renderer allows us to work on imgui specific circumstances from a single unified spot. This way, UI rendering issues and new features don't have to be spread over four different renderers, and we will be able in the future to leverage rendering concurrency if we so wish.

This is currently not so; the imgui frame is constructed and rendered right in the middle of the Present hooks, and blocking those calls. Luckily hudhook and imgui are pretty slick and can do all that in all four renderers without ever dipping below a solid 100fps on my machine (RTX 3080).

Per-engine compositors

I took a deep plunge in the dark seas of rendering engines and built four full-screen quad renderers from scratch, one per supported engine, which take the off-screen rendered resource and composite it on top of the appropriate backbuffer.

Asynchronous input processing

There is now a Pipeline object (its design is still a bit dirty, I want to work on it) that is responsible for managing the lifecycle of the rendering engine, the imgui context, and among those operations will also manage the window procedure. The window procedure proper is now dummy and only ships its parameters to a mpsc::channel.

This has the advantage that the window events are now processed asynchronously just before a frame gets rendered, which should be fine on our end, but the drawback that an event cannot be blocked immediately should the render loop wish to do that, as it won't be able to decide right away whether to consume the events without forwarding them. This should not be a big deal as these decisions sort of depend on the state before the rendering anyway, rather than on any single specific event, and the previous model is not more fine grained than that.

If you had issues with blocking input, please give this branch a go, it might just inadvertently fix that. Or make things worse. It did not make things worse for my use cases.

Wine support

I have tested on-and-off the library on Wine with Proton, and it seems like it's working pretty well. There's still work to be done to figure things out, but we're getting there.

Todo list

Affected issues

Conclusion

All in all, I am very happy about the results of this PR and have been working tirelessly towards it. There are some outstanding issues, but all manageable. I will keep making inconsequential changes while I wait for your feedback, but my plan is to wrap this up sooner rather than later and finally release 0.6.0.

cc @Jakobzs @vars1ty @vSylva @camas

vars1ty commented 4 months ago

Tested in Star Stable Online with the example OGL3 DLL, built with MSVC. All tested via Wine.

Average FPS without, and with UI displayed:

So does tank a bit, worse FPS than the legacy render engine, but does now work on Wine unlike the last refactor.

veeenu commented 4 months ago

This PR feels more like the development of a redemption arc rather than good, conscientious software engineering, but here goes.

The performance penalty incurred by @vars1ty is not acceptable, so I don't see this copy-buffers solution as viable.

Reviewing my own code, I realized that the full screen quad renderers which I wrote from scratch are literally 30-40 lines away each from being complete, fully-fledged dear imgui renderers. The difference is literally just uploading data to vertex/index buffers and adding render commands according to an enum match in a loop.

In the process, I have acquired enough knowledge about the various rendering engines and GPUs that I now feel confident maintaining all of these things by myself.

In fact, I went back and checked the renderers' code from 0.5.0 and I shuddered. What the heck was that garbage, @veeenu !

We will thus go back to the previous model, skipping the current PR: one rendering engine per hook type.

The way forward: considerations

Conclusions

More updates to come soon. I have a plan well laid out in my mind to make good out of this absolute mess that I have willingly put myself in the midst of. February is coming to an end, which means that if everything goes according to plan, I will have a solid solution by the time it will be both feasible and advisable for me to finally go out and touch grass. 🌱

veeenu commented 4 months ago

Superseded by #158.