From a9fc59d0df27c59a038af6307753d5e92273af96 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Fri, 19 Jul 2024 18:56:39 +0900 Subject: [PATCH] Rebase cleanup --- .../ImGuiBackend/Dx11Win32Backend.cs | 29 +++- .../Interface/Internal/InterfaceManager.cs | 5 +- Dalamud/Interface/Internal/SwapChainHelper.cs | 142 ------------------ 3 files changed, 29 insertions(+), 147 deletions(-) diff --git a/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs b/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs index a8a84b20d2..1346de439c 100644 --- a/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs +++ b/Dalamud/Interface/ImGuiBackend/Dx11Win32Backend.cs @@ -193,8 +193,8 @@ public void OnPostResize(int newWidth, int newHeight) /// public bool IsAttachedToPresentationTarget(nint targetHandle) => - this.swapChain.Get() == (void*)targetHandle - || this.swapChainPossiblyWrapped.Get() == (void*)targetHandle; + AreIUnknownEqual(this.swapChain.Get(), (IUnknown*)targetHandle) + || AreIUnknownEqual(this.swapChainPossiblyWrapped.Get(), (IUnknown*)targetHandle); /// public bool IsMainViewportFullScreen() @@ -204,6 +204,31 @@ public bool IsMainViewportFullScreen() return fullscreen; } + private static bool AreIUnknownEqual(T1* punk1, T2* punk2) + where T1 : unmanaged, IUnknown.Interface + where T2 : unmanaged, IUnknown.Interface + { + // https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void) + // For any given COM object (also known as a COM component), a specific query for the IUnknown interface on any + // of the object's interfaces must always return the same pointer value. + + if (punk1 is null || punk2 is null) + return false; + + fixed (Guid* iid = &IID.IID_IUnknown) + { + using var u1 = default(ComPtr); + if (punk1->QueryInterface(iid, (void**)u1.GetAddressOf()).FAILED) + return false; + + using var u2 = default(ComPtr); + if (punk2->QueryInterface(iid, (void**)u2.GetAddressOf()).FAILED) + return false; + + return u1.Get() == u2.Get(); + } + } + private void ReleaseUnmanagedResources() { if (this.device.IsEmpty()) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index a4f61c00ee..f7087d3ac5 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -780,6 +780,8 @@ private unsafe void ContinueConstruction( // This will wait for scene on its own. We just wait for this.dalamudAtlas.BuildTask in this.InitScene. _ = this.dalamudAtlas.BuildFontsAsync(); + SwapChainHelper.BusyWaitForGameDeviceSwapChain(); + try { if (Service.Get().WindowIsImmersive) @@ -797,9 +799,6 @@ private unsafe void ContinueConstruction( 0, this.SetCursorDetour); - SwapChainHelper.BusyWaitForGameDeviceSwapChain(); - SwapChainHelper.DetectReShade(); - Log.Verbose("===== S W A P C H A I N ====="); this.resizeBuffersHook = Hook.FromAddress( (nint)SwapChainHelper.GameDeviceSwapChainVtbl->ResizeBuffers, diff --git a/Dalamud/Interface/Internal/SwapChainHelper.cs b/Dalamud/Interface/Internal/SwapChainHelper.cs index 09c1f52fd4..e304839835 100644 --- a/Dalamud/Interface/Internal/SwapChainHelper.cs +++ b/Dalamud/Interface/Internal/SwapChainHelper.cs @@ -1,27 +1,14 @@ -using System.Diagnostics; using System.Threading; -using Dalamud.Game; -using Dalamud.Utility; - using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel; -using Serilog; - using TerraFX.Interop.DirectX; -using TerraFX.Interop.Windows; namespace Dalamud.Interface.Internal; /// Helper for dealing with swap chains. internal static unsafe class SwapChainHelper { - /// - /// Gets the function pointer for ReShade's DXGISwapChain::on_present. - /// Source. - /// - public static delegate* unmanaged ReshadeOnPresent { get; private set; } - /// Gets the game's active instance of IDXGISwapChain that is initialized. /// Address of the game's instance of IDXGISwapChain, or null if not available (yet.) public static IDXGISwapChain* GameDeviceSwapChain @@ -55,139 +42,10 @@ public static IDXGISwapChain.Vtbl* GameDeviceSwapChainVtbl } } - /// - public static bool IsGameDeviceSwapChain(nint punk) => IsGameDeviceSwapChain((IUnknown*)punk); - - /// Determines if the given instance of IUnknown is the game device's swap chain. - /// Object to check. - /// Type of the object to check. - /// true if the object is the game's swap chain. - public static bool IsGameDeviceSwapChain(T* punk) where T : unmanaged, IUnknown.Interface - { - // https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void) - // For any given COM object (also known as a COM component), a specific query for the IUnknown interface on any - // of the object's interfaces must always return the same pointer value. - - var gdsc = GameDeviceSwapChain; - if (gdsc is null || punk is null) - return false; - - fixed (Guid* iid = &IID.IID_IUnknown) - { - using var u1 = default(ComPtr); - if (gdsc->QueryInterface(iid, (void**)u1.GetAddressOf()).FAILED) - return false; - - using var u2 = default(ComPtr); - if (punk->QueryInterface(iid, (void**)u2.GetAddressOf()).FAILED) - return false; - - return u1.Get() == u2.Get(); - } - } - /// Wait for the game to have finished initializing the IDXGISwapChain. public static void BusyWaitForGameDeviceSwapChain() { while (GameDeviceSwapChain is null) Thread.Yield(); } - - /// Detects ReShade and populate . - public static void DetectReShade() - { - var modules = Process.GetCurrentProcess().Modules; - foreach (ProcessModule processModule in modules) - { - if (!processModule.FileName.EndsWith("game\\dxgi.dll", StringComparison.InvariantCultureIgnoreCase)) - continue; - - try - { - var fileInfo = FileVersionInfo.GetVersionInfo(processModule.FileName); - - if (fileInfo.FileDescription == null) - break; - - if (!fileInfo.FileDescription.Contains("GShade") && !fileInfo.FileDescription.Contains("ReShade")) - break; - - // warning: these comments may no longer be accurate. - // reshade master@4232872 RVA - // var p = processModule.BaseAddress + 0x82C7E0; // DXGISwapChain::Present - // var p = processModule.BaseAddress + 0x82FAC0; // DXGISwapChain::runtime_present - // DXGISwapChain::handle_device_loss =>df DXGISwapChain::Present => DXGISwapChain::runtime_present - // 5.2+ - F6 C2 01 0F 85 - // 6.0+ - F6 C2 01 0F 85 88 - - var scanner = new SigScanner(processModule); - var reShadeDxgiPresent = nint.Zero; - - if (fileInfo.FileVersion?.StartsWith("6.") == true) - { - // No Addon - if (scanner.TryScanText("F6 C2 01 0F 85 A8", out reShadeDxgiPresent)) - { - Log.Information("Hooking present for ReShade 6 No-Addon"); - } - - // Addon - else if (scanner.TryScanText("F6 C2 01 0F 85 88", out reShadeDxgiPresent)) - { - Log.Information("Hooking present for ReShade 6 Addon"); - } - - // Fallback - else - { - Log.Error("Failed to get ReShade 6 DXGISwapChain::on_present offset!"); - } - } - - // Looks like this sig only works for GShade 4 - if (reShadeDxgiPresent == nint.Zero && fileInfo.FileDescription?.Contains("GShade 4.") == true) - { - if (scanner.TryScanText("E8 ?? ?? ?? ?? 45 0F B6 5E ??", out reShadeDxgiPresent)) - { - Log.Information("Hooking present for GShade 4"); - } - else - { - Log.Error("Failed to find GShade 4 DXGISwapChain::on_present offset!"); - } - } - - if (reShadeDxgiPresent == nint.Zero) - { - if (scanner.TryScanText("F6 C2 01 0F 85", out reShadeDxgiPresent)) - { - Log.Information("Hooking present for ReShade with fallback 5.X sig"); - } - else - { - Log.Error("Failed to find ReShade DXGISwapChain::on_present offset with fallback sig!"); - } - } - - Log.Information( - "ReShade DLL: {FileName} ({Info} - {Version}) with DXGISwapChain::on_present at {Address}", - processModule.FileName, - fileInfo.FileDescription ?? "Unknown", - fileInfo.FileVersion ?? "Unknown", - Util.DescribeAddress(reShadeDxgiPresent)); - - if (reShadeDxgiPresent != nint.Zero) - { - ReshadeOnPresent = (delegate* unmanaged)reShadeDxgiPresent; - } - - break; - } - catch (Exception e) - { - Log.Error(e, "Failed to get ReShade version info"); - break; - } - } - } }