Fix #38 - resizing the game window was causing swapchain ResizeBuffers() to fail, leading to corrupt render targets

This commit is contained in:
meli 2020-02-27 23:01:43 -08:00
parent 6f5ac527a7
commit 803e69d1b7
5 changed files with 36 additions and 5 deletions

View file

@ -3,5 +3,6 @@ using System;
namespace Dalamud.Game.Internal.DXGI { namespace Dalamud.Game.Internal.DXGI {
public interface ISwapChainAddressResolver { public interface ISwapChainAddressResolver {
IntPtr Present { get; set; } IntPtr Present { get; set; }
IntPtr ResizeBuffers { get; set; }
} }
} }

View file

@ -11,7 +11,7 @@ namespace Dalamud.Game.Internal.DXGI
public sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver public sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver
{ {
public IntPtr Present { get; set; } public IntPtr Present { get; set; }
//public IntPtr ResizeBuffers { get; private set; } public IntPtr ResizeBuffers { get; set; }
protected override void Setup64Bit(SigScanner sig) 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. // 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; Present = scanner.ScanModule("41 8B F0 8B FA 89 54 24 ?? 48 8B D9 48 89 4D ?? C6 44 24 ?? 00") - 0x37;
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");
// 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");
} }
} }
} }

View file

@ -59,6 +59,7 @@ namespace Dalamud.Game.Internal.DXGI
#region Addresses #region Addresses
public IntPtr Present { get; set; } public IntPtr Present { get; set; }
public IntPtr ResizeBuffers { get; set; }
#endregion #endregion
@ -93,6 +94,7 @@ namespace Dalamud.Game.Internal.DXGI
} }
Present = this.dxgiSwapChainVTblAddresses[8]; Present = this.dxgiSwapChainVTblAddresses[8];
ResizeBuffers = this.dxgiSwapChainVTblAddresses[13];
} }
} }
} }

View file

@ -28,7 +28,11 @@ namespace Dalamud.Interface
[UnmanagedFunctionPointer(CallingConvention.ThisCall)] [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr PresentDelegate(IntPtr swapChain, uint syncInterval, uint presentFlags); 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<PresentDelegate> presentHook; private readonly Hook<PresentDelegate> presentHook;
private readonly Hook<ResizeBuffersDelegate> resizeBuffersHook;
private readonly Hook<SetCursorDelegate> setCursorHook; private readonly Hook<SetCursorDelegate> setCursorHook;
@ -73,6 +77,7 @@ namespace Dalamud.Interface
Log.Verbose("===== S W A P C H A I N ====="); Log.Verbose("===== S W A P C H A I N =====");
Log.Verbose("SetCursor address {SetCursor}", setCursorAddr); Log.Verbose("SetCursor address {SetCursor}", setCursorAddr);
Log.Verbose("Present address {Present}", Address.Present); Log.Verbose("Present address {Present}", Address.Present);
Log.Verbose("ResizeBuffers address {ResizeBuffers}", Address.ResizeBuffers);
this.setCursorHook = new Hook<SetCursorDelegate>(setCursorAddr, new SetCursorDelegate(SetCursorDetour), this); this.setCursorHook = new Hook<SetCursorDelegate>(setCursorAddr, new SetCursorDelegate(SetCursorDetour), this);
@ -80,18 +85,25 @@ namespace Dalamud.Interface
new Hook<PresentDelegate>(Address.Present, new Hook<PresentDelegate>(Address.Present,
new PresentDelegate(PresentDetour), new PresentDelegate(PresentDetour),
this); this);
this.resizeBuffersHook =
new Hook<ResizeBuffersDelegate>(Address.ResizeBuffers,
new ResizeBuffersDelegate(ResizeBuffersDetour),
this);
} }
public void Enable() public void Enable()
{ {
this.setCursorHook.Enable(); this.setCursorHook.Enable();
this.presentHook.Enable(); this.presentHook.Enable();
this.resizeBuffersHook.Enable();
} }
private void Disable() private void Disable()
{ {
this.setCursorHook.Disable(); this.setCursorHook.Disable();
this.presentHook.Disable(); this.presentHook.Disable();
this.resizeBuffersHook.Disable();
} }
public void Dispose() public void Dispose()
@ -107,6 +119,7 @@ namespace Dalamud.Interface
this.scene.Dispose(); this.scene.Dispose();
this.presentHook.Dispose(); this.presentHook.Dispose();
this.resizeBuffersHook.Dispose();
} }
public TextureWrap LoadImage(string filePath) public TextureWrap LoadImage(string filePath)
@ -182,6 +195,23 @@ namespace Dalamud.Interface
return this.presentHook.Original(swapChain, syncInterval, presentFlags); 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 // can't access imgui IO before first present call
private bool lastWantCapture = false; private bool lastWantCapture = false;

@ -1 +1 @@
Subproject commit cd24a6108c05e52b0dde80e85ff1f9fa812f631b Subproject commit 8259c373c0b08ace2651445acf1edd03dddf71fd