From 476ac94d801beecb284041b1b7c6d5518df0154b Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Fri, 24 May 2024 13:25:28 -0700 Subject: [PATCH] Add GPU acceleration for most of ApiHawk's GuiApi (gui.* lua APIs), refactor ApiHawk surfaces --- Assets/dll/SDL2.dll | Bin 1460736 -> 1653760 bytes Assets/dll/cimgui.dll | Bin 0 -> 1229824 bytes Assets/dll/cimgui.so | Bin 0 -> 2029200 bytes Assets/dll/libSDL2.so | Bin 1932304 -> 2140632 bytes Directory.Packages.props | 1 + ExternalProjects/SDL2/CMakeLists.txt | 3 +- .../Controls/OpenGLControl.cs | 2 +- .../BizHawk.Bizware.Graphics.csproj | 1 + .../D3D11/D3D11Pipeline.cs | 69 ++- .../D3D11/D3D11Resources.cs | 4 +- .../D3D11/IGL_D3D11.cs | 85 ++- .../Extensions/DrawingExtensions.cs | 4 + .../Extensions/IGLExtensions.cs | 5 + .../GDIPlus/IGL_GDIPlus.cs | 6 +- .../ImGuiResourceCache.cs | 182 +++++++ .../Interfaces/I2DRenderer.cs | 62 +++ .../Interfaces/IGL.cs | 13 +- .../{Renderers => Interfaces}/IGuiRenderer.cs | 0 .../Interfaces/IPipeline.cs | 10 + .../OpenGL/IGL_OpenGL.cs | 36 +- .../OpenGL/OpenGLPipeline.cs | 47 +- .../PipelineCompileArgs.cs | 16 +- .../Renderers/GuiRenderer.cs | 3 +- .../Renderers/ImGui2DRenderer.cs | 490 ++++++++++++++++++ .../Renderers/SDLImGui2DRenderer.cs | 190 +++++++ src/BizHawk.Bizware.Graphics/RetroShader.cs | 4 +- .../Api/Classes/GuiApi.cs | 293 ++++------- .../Api/Interfaces/IGuiApi.cs | 11 +- .../DisplayManager/DisplayManagerBase.cs | 127 +---- .../DisplayManager/DisplaySurface.cs | 63 --- .../DisplayManager/Filters/Gui.cs | 31 +- .../DisplayManager/IDisplaySurface.cs | 19 - .../SwappableDisplaySurfaceSet.cs | 87 ---- .../DisplayManager/TextureFrugalizer.cs | 8 +- .../lua/CommonLibs/GuiLuaLibrary.cs | 8 +- src/BizHawk.Client.EmuHawk/Api/ApiManager.cs | 1 - src/BizHawk.Client.EmuHawk/Program.cs | 2 +- .../tools/Lua/LuaLibraries.cs | 11 - 38 files changed, 1285 insertions(+), 609 deletions(-) create mode 100644 Assets/dll/cimgui.dll create mode 100644 Assets/dll/cimgui.so create mode 100644 src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs create mode 100644 src/BizHawk.Bizware.Graphics/Interfaces/I2DRenderer.cs rename src/BizHawk.Bizware.Graphics/{Renderers => Interfaces}/IGuiRenderer.cs (100%) create mode 100644 src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs create mode 100644 src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs delete mode 100644 src/BizHawk.Client.Common/DisplayManager/DisplaySurface.cs delete mode 100644 src/BizHawk.Client.Common/DisplayManager/IDisplaySurface.cs delete mode 100644 src/BizHawk.Client.Common/DisplayManager/SwappableDisplaySurfaceSet.cs diff --git a/Assets/dll/SDL2.dll b/Assets/dll/SDL2.dll index 7d92399f4ddf8d187eddcd422a7d894088b7d555..6b2458fe5ae2bd404d92ea4572475da0473eefff 100644 GIT binary patch delta 591004 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