From 803e69d1b7c3b874b0f0f4963a6c31c5dba063be Mon Sep 17 00:00:00 2001 From: meli <57847713+ff-meli@users.noreply.github.com> Date: Thu, 27 Feb 2020 23:01:43 -0800 Subject: [PATCH] Fix #38 - resizing the game window was causing swapchain ResizeBuffers() to fail, leading to corrupt render targets --- .../DXGI/ISwapChainAddressResolver.cs | 1 + .../Internal/DXGI/SwapChainSigResolver.cs | 6 ++-- .../Internal/DXGI/SwapChainVtableResolver.cs | 2 ++ Dalamud/Interface/InterfaceManager.cs | 30 +++++++++++++++++++ lib/ImGuiScene | 2 +- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs b/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs index ad2e003f6..d1fbe2bb8 100644 --- a/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs +++ b/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs @@ -3,5 +3,6 @@ using System; namespace Dalamud.Game.Internal.DXGI { public interface ISwapChainAddressResolver { IntPtr Present { get; set; } + IntPtr ResizeBuffers { get; set; } } } diff --git a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs index 37c28197e..0c6b12d61 100644 --- a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs +++ b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs @@ -11,7 +11,7 @@ namespace Dalamud.Game.Internal.DXGI public sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver { public IntPtr Present { get; set; } - //public IntPtr ResizeBuffers { get; private set; } + public IntPtr ResizeBuffers { get; set; } protected override void Setup64Bit(SigScanner sig) { @@ -24,9 +24,7 @@ namespace Dalamud.Game.Internal.DXGI // This(code after the function head - offset of it) was picked to avoid running into issues with other hooks being installed into this function. Present = scanner.ScanModule("41 8B F0 8B FA 89 54 24 ?? 48 8B D9 48 89 4D ?? C6 44 24 ?? 00") - 0x37; - - // seems unnecessary for now, but we may need to handle it - //ResizeBuffers = scanner.ScanModule("48 8B C4 55 41 54 41 55 41 56 41 57 48 8D 68 ?? 48 81 EC C0 00 00 00"); + ResizeBuffers = scanner.ScanModule("48 8B C4 55 41 54 41 55 41 56 41 57 48 8D 68 ?? 48 81 EC C0 00 00 00"); } } } diff --git a/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs index a9981b8ed..29729f7a8 100644 --- a/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs +++ b/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs @@ -59,6 +59,7 @@ namespace Dalamud.Game.Internal.DXGI #region Addresses public IntPtr Present { get; set; } + public IntPtr ResizeBuffers { get; set; } #endregion @@ -93,6 +94,7 @@ namespace Dalamud.Game.Internal.DXGI } Present = this.dxgiSwapChainVTblAddresses[8]; + ResizeBuffers = this.dxgiSwapChainVTblAddresses[13]; } } } diff --git a/Dalamud/Interface/InterfaceManager.cs b/Dalamud/Interface/InterfaceManager.cs index 7c0c25bd7..2d22a6a4e 100644 --- a/Dalamud/Interface/InterfaceManager.cs +++ b/Dalamud/Interface/InterfaceManager.cs @@ -28,7 +28,11 @@ namespace Dalamud.Interface [UnmanagedFunctionPointer(CallingConvention.ThisCall)] private delegate IntPtr PresentDelegate(IntPtr swapChain, uint syncInterval, uint presentFlags); + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate IntPtr ResizeBuffersDelegate(IntPtr swapChain, uint bufferCount, uint width, uint height, uint newFormat, uint swapChainFlags); + private readonly Hook presentHook; + private readonly Hook resizeBuffersHook; private readonly Hook setCursorHook; @@ -73,6 +77,7 @@ namespace Dalamud.Interface Log.Verbose("===== S W A P C H A I N ====="); Log.Verbose("SetCursor address {SetCursor}", setCursorAddr); Log.Verbose("Present address {Present}", Address.Present); + Log.Verbose("ResizeBuffers address {ResizeBuffers}", Address.ResizeBuffers); this.setCursorHook = new Hook(setCursorAddr, new SetCursorDelegate(SetCursorDetour), this); @@ -80,18 +85,25 @@ namespace Dalamud.Interface new Hook(Address.Present, new PresentDelegate(PresentDetour), this); + + this.resizeBuffersHook = + new Hook(Address.ResizeBuffers, + new ResizeBuffersDelegate(ResizeBuffersDetour), + this); } public void Enable() { this.setCursorHook.Enable(); this.presentHook.Enable(); + this.resizeBuffersHook.Enable(); } private void Disable() { this.setCursorHook.Disable(); this.presentHook.Disable(); + this.resizeBuffersHook.Disable(); } public void Dispose() @@ -107,6 +119,7 @@ namespace Dalamud.Interface this.scene.Dispose(); this.presentHook.Dispose(); + this.resizeBuffersHook.Dispose(); } public TextureWrap LoadImage(string filePath) @@ -182,6 +195,23 @@ namespace Dalamud.Interface return this.presentHook.Original(swapChain, syncInterval, presentFlags); } + private IntPtr ResizeBuffersDetour(IntPtr swapChain, uint bufferCount, uint width, uint height, uint newFormat, uint swapChainFlags) + { + Log.Verbose($"Calling resizebuffers {bufferCount} {width} {height} {newFormat} {swapChainFlags}"); + + this.scene?.OnPreResize(); + + var ret = this.resizeBuffersHook.Original(swapChain, bufferCount, width, height, newFormat, swapChainFlags); + if (ret.ToInt64() == 0x887A0001) + { + Log.Error("invalid call to resizeBuffers"); + } + + this.scene?.OnPostResize((int)width, (int)height); + + return ret; + } + // can't access imgui IO before first present call private bool lastWantCapture = false; diff --git a/lib/ImGuiScene b/lib/ImGuiScene index cd24a6108..8259c373c 160000 --- a/lib/ImGuiScene +++ b/lib/ImGuiScene @@ -1 +1 @@ -Subproject commit cd24a6108c05e52b0dde80e85ff1f9fa812f631b +Subproject commit 8259c373c0b08ace2651445acf1edd03dddf71fd