Skip to content

Create shim over GuiApi so it can only be used via WithSurface - #4799

Draft
YoshiRulz wants to merge 6 commits into
masterfrom
guiapi-depr-cycle
Draft

Create shim over GuiApi so it can only be used via WithSurface#4799
YoshiRulz wants to merge 6 commits into
masterfrom
guiapi-depr-cycle

Conversation

@YoshiRulz

@YoshiRulz YoshiRulz commented Jul 22, 2026

Copy link
Copy Markdown
Member

This PR finishes some way-too-long deprecation cycles, and finishes the implementation of scoped/batched drawing for ApiHawk from 7749d02.
Remaining points to address before merge:

We could also split the interface so the Draw* methods aren't discoverable on APIs.Gui..

Did I separate out the "global" methods correctly? (edit: I had an OSD function marked as a draw function, fixed.)
And should they be available on the lambda param gui, or only APIs.Gui? Currently I'm supporting both, by forwarding calls through the shim to the real impl.

Do the changes to GuiLuaLibrary have a noticeable impact on performance for scripts which draw a lot?

@YoshiRulz YoshiRulz added the re: APIHawk Relating to EmuHawk's public .NET API or to the creation of external tools label Jul 22, 2026
@YoshiRulz
YoshiRulz requested a review from SuuperW July 22, 2026 16:07
@SuuperW

SuuperW commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Why?

Also this looks incomplete, so I cannot tell what API you expect to end up with.

@YoshiRulz

YoshiRulz commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

This was always the intent: to add a way to batch draw calls, and remove the old system.

It is complete in the sense that I have nothing left to add (except docs). The questions in OP need answering, which do relate to the shape of the APIs.

@SuuperW

SuuperW commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

to add a way to batch draw calls, and remove the old system.

Again, why? I do not see any benefit to doing it this way. (Tbh, I'm not entirely sure what "this way" is, since I don't know how to draw anything via Lua right now.)

It is complete in the sense that I have nothing left to add (except docs).

Explain how it's supposed to be used, because old Lua scripts currently don't work and it is not obvious how to migrate. An explanation of how things are set up would also be helpful, because I can't answer your questions without understanding the code you wrote and the intention behind this change.

@YoshiRulz
YoshiRulz force-pushed the guiapi-depr-cycle branch from 892ed6c to 827055b Compare July 22, 2026 21:36
@YoshiRulz

Copy link
Copy Markdown
Member Author

I forgot the Lua library impl. needed WithSurface everywhere. This PR isn't about Lua, it's about ext. tools, but that change may impact Lua drawing performance.

@SuuperW

SuuperW commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

My FPS drops from ~138 to ~130 when unthrottled with a Lua script drawing over most of the screen. For a change that seemingly has zero benefits, this is unacceptable. If you believe this change does have benefits, I ask you again to please explicitly state them.

@YoshiRulz

Copy link
Copy Markdown
Member Author

That's not too big a hit, but it should definitely be addressed before merge. The Lua libraries already get their own copy of the API impl classes, so maybe they could get the "real" GuiApi instead of the shim. Or maybe we could lift the WithSurface scope to outside where we pass execution to Lua.

I see one immediate benefit and one opportunity from forcing a batching pattern onto ext. tools:

  1. It encourages separation-of-concerns designs over entangled designs; and
  2. It enables us to apply more aggressive optimisations on our end, including the most powerful: skipping work.

@SuuperW

SuuperW commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

It encourages separation-of-concerns designs over entangled designs

That could be beneficial, but why would it be something we force only on power users? ("power users" being people who make external tools rather than just write Lua scripts, as that's a much more advanced feature; such people are likely already much more knowledgeable and less likely to need us to enforce our ideas of what makes for good code)

And besides, this PR does not even do that. As evidenced by the fact you were able to pretty easily modify the Lua api so that each individual call is a "batch" of one operation. External tool authors could also create a similar shim around your GuiApiShim that wraps each individual operation in a batch; or manually put WithSurface around each draw call. The code flow for external tools can still mix drawing with other concerns just as easily as it can before your change.

It enables us to apply more aggressive optimisations on our end, including the most powerful: skipping work.

This should apply just as much, if not more so, to Lua.

I am not entirely opposed to taking my PR and forcing all draw calls to happen inside the drawing callback. (The main problem with doing that would be that all old Lua scripts that draw will no longer work.) This would address both of your points. We could also give the drawing callback two parameters, one for the emu surface and one for the client surface. This way there's no more need to specify the surface as a parameter to each call or to use_surface or WithSurface, and makes the fact we have two surfaces more visible. (Perhaps there'd be a a third parameter for an object that just does what gui.text does ... or some other consideration for the fact that it only works on the client surface - ish.)

Also, you forgot to wrap clearGraphics here. A Lua script that calls clearGraphics() will encounter an exception.

public void AddMessage(string message, [LiteralExpected] int? duration = null)
=> _dialogController.AddOnScreenMessage(message, duration);

public void ClearGraphics(DisplaySurfaceID? surfaceID = null) => Get2DRenderer(surfaceID).Clear();

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void ClearGraphics(DisplaySurfaceID? surfaceID = null) => _displayManager.GetApiHawk2DRenderer(surfaceID ?? SurfaceID ?? throw...).Clear();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

re: APIHawk Relating to EmuHawk's public .NET API or to the creation of external tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants