4
4
#include " client/render/Renderer.h"
5
5
6
6
namespace {
7
+ typedef HRESULT (WINAPI* CreateSwapChainForCoreWindow_t)(
8
+ IDXGIFactory2*,
9
+ IUnknown*,
10
+ IUnknown*,
11
+ const DXGI_SWAP_CHAIN_DESC1*,
12
+ IDXGIOutput*,
13
+ IDXGISwapChain1**);
14
+
15
+ bool tearingSupported = false ;
7
16
std::shared_ptr<Hook> PresentHook;
8
17
std::shared_ptr<Hook> ResizeBuffersHook;
9
18
std::shared_ptr<Hook> ExecuteCommandListsHook;
10
19
}
11
20
21
+ void CheckTearingSupport () {
22
+ ComPtr<IDXGIFactory5> factory5;
23
+ if (SUCCEEDED (CreateDXGIFactory1 (IID_PPV_ARGS (&factory5)))) {
24
+ BOOL allowTearing = FALSE ;
25
+ if (SUCCEEDED (factory5->CheckFeatureSupport (
26
+ DXGI_FEATURE_PRESENT_ALLOW_TEARING,
27
+ &allowTearing,
28
+ sizeof (allowTearing)))) {
29
+ tearingSupported = allowTearing;
30
+ }
31
+ }
32
+ }
33
+
34
+ CreateSwapChainForCoreWindow_t origCreateSwapChain = nullptr ;
35
+
36
+ HRESULT WINAPI DXHooks::CreateSwapChainForCoreWindowHook (
37
+ IDXGIFactory2* factory,
38
+ IUnknown* device,
39
+ IUnknown* window,
40
+ const DXGI_SWAP_CHAIN_DESC1* desc,
41
+ IDXGIOutput* output,
42
+ IDXGISwapChain1** swapChain) {
43
+
44
+ DXGI_SWAP_CHAIN_DESC1 modifiedDesc = *desc;
45
+ if (tearingSupported) {
46
+ modifiedDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
47
+ }
48
+
49
+ return origCreateSwapChain (factory, device, window, &modifiedDesc,
50
+ output, swapChain);
51
+ }
52
+
12
53
HRESULT __stdcall DXHooks::SwapChain_Present (IDXGISwapChain* chain, UINT SyncInterval, UINT Flags) {
13
54
if (Latite::getRenderer ().hasInitialized ()) {
14
55
auto lock = Latite::getRenderer ().lock ();
@@ -28,18 +69,42 @@ HRESULT __stdcall DXHooks::SwapChain_Present(IDXGISwapChain* chain, UINT SyncInt
28
69
// hasKilled = true;
29
70
// }
30
71
31
- return PresentHook->oFunc <decltype (&SwapChain_Present)>()(chain, SyncInterval, Flags);
72
+ UINT presentFlags = Flags;
73
+ UINT syncInterval;
74
+ if (tearingSupported) {
75
+ syncInterval = 0 ;
76
+ presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
77
+ } else {
78
+ syncInterval = SyncInterval;
79
+ }
80
+
81
+ return PresentHook->oFunc <decltype (&SwapChain_Present)>()(chain, syncInterval, presentFlags);
32
82
}
33
83
34
- HRESULT __stdcall DXHooks::SwapChain_ResizeBuffers (IDXGISwapChain* chain, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) {
84
+ HRESULT __stdcall DXHooks::SwapChain_ResizeBuffers (
85
+ IDXGISwapChain* chain,
86
+ UINT BufferCount,
87
+ UINT Width,
88
+ UINT Height,
89
+ DXGI_FORMAT NewFormat,
90
+ UINT SwapChainFlags) {
91
+
35
92
Latite::getRenderer ().reinit ();
36
- return ResizeBuffersHook->oFunc <decltype (&SwapChain_ResizeBuffers)>()(chain, BufferCount, Width, Height, NewFormat, SwapChainFlags);
93
+ UINT newFlags = SwapChainFlags;
94
+ if (tearingSupported) {
95
+ newFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
96
+ }
97
+
98
+ return ResizeBuffersHook->oFunc <decltype (&SwapChain_ResizeBuffers)>()(
99
+ chain, BufferCount, Width, Height, NewFormat, newFlags);
37
100
}
38
101
39
- HRESULT __stdcall DXHooks::CommandQueue_ExecuteCommandLists (ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* const * ppCommandLists) {
40
- auto lock = Latite::getRenderer ().lock ();
41
- Latite::getRenderer ().setCommandQueue (queue);
42
- return ExecuteCommandListsHook->oFunc <decltype (&CommandQueue_ExecuteCommandLists)>()(queue, NumCommandLists, ppCommandLists);
102
+ HRESULT __stdcall DXHooks::CommandQueue_ExecuteCommandLists (ID3D12CommandQueue* queue, UINT NumCommandLists,
103
+ ID3D12CommandList* const * ppCommandLists) {
104
+ auto lock = Latite::getRenderer ().lock ();
105
+ Latite::getRenderer ().setCommandQueue (queue);
106
+ return ExecuteCommandListsHook->oFunc <decltype (&CommandQueue_ExecuteCommandLists)>()(
107
+ queue, NumCommandLists, ppCommandLists);
43
108
}
44
109
45
110
DXHooks::DXHooks () : HookGroup(" DirectX" ) {
@@ -51,6 +116,8 @@ DXHooks::DXHooks() : HookGroup("DirectX") {
51
116
ComPtr<ID3D11DeviceContext> dctx;
52
117
ComPtr<ID3D12CommandQueue> cqueue;
53
118
119
+ CheckTearingSupport ();
120
+
54
121
ThrowIfFailed (CreateDXGIFactory (IID_PPV_ARGS (&factory)));
55
122
ThrowIfFailed (factory->EnumAdapters (0 , adapter.GetAddressOf ()));
56
123
@@ -84,8 +151,9 @@ DXHooks::DXHooks() : HookGroup("DirectX") {
84
151
D3D_FEATURE_LEVEL lvl[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
85
152
86
153
D3D_FEATURE_LEVEL featureLevel;
87
- auto hr = D3D11CreateDeviceAndSwapChain (NULL , D3D_DRIVER_TYPE_HARDWARE, NULL , 0 , lvl, 2 , D3D11_SDK_VERSION,
88
- &swapChainDesc, swapChain.GetAddressOf (), device.GetAddressOf (), &featureLevel, dctx.GetAddressOf ());
154
+ auto hr = D3D11CreateDeviceAndSwapChain (nullptr , D3D_DRIVER_TYPE_HARDWARE, nullptr , 0 , lvl, 2 , D3D11_SDK_VERSION,
155
+ &swapChainDesc, swapChain.GetAddressOf (), device.GetAddressOf (),
156
+ &featureLevel, dctx.GetAddressOf ());
89
157
90
158
uintptr_t * vftable = *reinterpret_cast <uintptr_t **>(swapChain.Get ());
91
159
uintptr_t * cqueueVftable = nullptr ;
@@ -109,6 +177,14 @@ DXHooks::DXHooks() : HookGroup("DirectX") {
109
177
DestroyWindow (hWnd);
110
178
UnregisterClass (L" dummywnd" , Latite::get ().dllInst );
111
179
180
+ ComPtr<IDXGIFactory2> factory2;
181
+ if (SUCCEEDED (factory.As (&factory2))) {
182
+ void ** vtable = *(void ***)factory2.Get ();
183
+ MH_CreateHook (vtable[16 ], DXHooks::CreateSwapChainForCoreWindowHook,
184
+ (void **)&origCreateSwapChain);
185
+ MH_EnableHook (vtable[16 ]);
186
+ }
187
+
112
188
PresentHook = addHook (vftable[8 ], SwapChain_Present, " IDXGISwapChain::Present" );
113
189
ResizeBuffersHook = addHook (vftable[13 ], SwapChain_ResizeBuffers, " IDXGISwapChain::ResizeBuffers" );
114
190
0 commit comments