From dd530e80b1f9d09d970784e9afb00e5e43877792 Mon Sep 17 00:00:00 2001 From: Nemirtingas Date: Mon, 26 Aug 2019 16:38:01 +0200 Subject: [PATCH] Now passing to hooks device object. Added Base_Hook::get_lib_name to track what renderer is hooked for overlay. Objects used to detect renderer type are now also used to hook the rendering functions. So we don't have to build another device. Updated VTables for DX12. --- overlay_experimental/Base_Hook.cpp | 5 ++ overlay_experimental/Base_Hook.h | 1 + overlay_experimental/DX10_Hook.cpp | 64 ++++---------- overlay_experimental/DX10_Hook.h | 1 + overlay_experimental/DX11_Hook.cpp | 65 ++++---------- overlay_experimental/DX11_Hook.h | 1 + overlay_experimental/DX9_Hook.cpp | 66 +++++---------- overlay_experimental/DX9_Hook.h | 3 +- overlay_experimental/DirectX_VTables.h | 105 +++++++++++++++++++++++ overlay_experimental/Hook_Manager.cpp | 112 ++++++++++++++++--------- overlay_experimental/Hook_Manager.h | 13 +-- overlay_experimental/OpenGL_Hook.cpp | 5 ++ overlay_experimental/OpenGL_Hook.h | 1 + overlay_experimental/Windows_Hook.cpp | 5 ++ overlay_experimental/Windows_Hook.h | 1 + overlay_experimental/steam_overlay.cpp | 13 ++- overlay_experimental/steam_overlay.h | 1 + 17 files changed, 277 insertions(+), 185 deletions(-) diff --git a/overlay_experimental/Base_Hook.cpp b/overlay_experimental/Base_Hook.cpp index 452309e..3c73584 100644 --- a/overlay_experimental/Base_Hook.cpp +++ b/overlay_experimental/Base_Hook.cpp @@ -45,6 +45,11 @@ void Base_Hook::UnhookAll() } } +const char* Base_Hook::get_lib_name() const +{ + return ""; +} + void Base_Hook::HookFunc(std::pair hook) { if( DetourAttach(hook.first, hook.second) == 0 ) diff --git a/overlay_experimental/Base_Hook.h b/overlay_experimental/Base_Hook.h index bb0c2dd..55fbfae 100644 --- a/overlay_experimental/Base_Hook.h +++ b/overlay_experimental/Base_Hook.h @@ -29,6 +29,7 @@ public: void EndHook(); void UnhookAll(); + virtual const char* get_lib_name() const; void HookFunc(std::pair hook); template diff --git a/overlay_experimental/DX10_Hook.cpp b/overlay_experimental/DX10_Hook.cpp index 54e43b7..6f5db63 100644 --- a/overlay_experimental/DX10_Hook.cpp +++ b/overlay_experimental/DX10_Hook.cpp @@ -18,56 +18,21 @@ bool DX10_Hook::start_hook() if (!Windows_Hook::Inst().start_hook()) return false; - HWND hWnd = GetGameWindow(); - if (!hWnd) - return false; + PRINT_DEBUG("Hooked DirectX 10\n"); + _hooked = true; - IDXGISwapChain* pSwapChain; - ID3D10Device* pDevice; - DXGI_SWAP_CHAIN_DESC SwapChainDesc = {}; - decltype(D3D10CreateDeviceAndSwapChain)* D3D10CreateDeviceAndSwapChain = - (decltype(D3D10CreateDeviceAndSwapChain))GetProcAddress(reinterpret_cast(_library), "D3D10CreateDeviceAndSwapChain"); - SwapChainDesc.BufferCount = 1; - SwapChainDesc.BufferDesc.Width = 1; - SwapChainDesc.BufferDesc.Height = 1; - SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - SwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0; - SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.OutputWindow = hWnd; - SwapChainDesc.SampleDesc.Count = 1; - SwapChainDesc.SampleDesc.Quality = 0; - SwapChainDesc.Windowed = TRUE; + Hook_Manager::Inst().FoundRenderer(this); - D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice); + UnhookAll(); + BeginHook(); + HookFuncs( + std::make_pair(&(PVOID&)DX10_Hook::Present, &DX10_Hook::MyPresent), + std::make_pair(&(PVOID&)DX10_Hook::ResizeTarget, &DX10_Hook::MyResizeTarget), + std::make_pair(&(PVOID&)DX10_Hook::ResizeBuffers, &DX10_Hook::MyResizeBuffers) + ); + EndHook(); - if (pDevice != nullptr && pSwapChain != nullptr) - { - PRINT_DEBUG("Hooked DirectX 10\n"); - - _hooked = true; - Hook_Manager::Inst().FoundRenderer(this); - - loadFunctions(pDevice, pSwapChain); - - UnhookAll(); - BeginHook(); - HookFuncs( - std::make_pair(&(PVOID&)DX10_Hook::Present, &DX10_Hook::MyPresent), - std::make_pair(&(PVOID&)DX10_Hook::ResizeTarget, &DX10_Hook::MyResizeTarget), - std::make_pair(&(PVOID&)DX10_Hook::ResizeBuffers, &DX10_Hook::MyResizeBuffers) - ); - EndHook(); - - get_steam_client()->steam_overlay->HookReady(); - } - else - { - PRINT_DEBUG("Failed to hook DirectX 10\n"); - res = false; - } - if(pDevice)pDevice->Release(); - if(pSwapChain)pSwapChain->Release(); + get_steam_client()->steam_overlay->HookReady(); } return res; } @@ -220,6 +185,11 @@ DX10_Hook* DX10_Hook::Inst() return _inst; } +const char* DX10_Hook::get_lib_name() const +{ + return DLL_NAME; +} + void DX10_Hook::loadFunctions(ID3D10Device *pDevice, IDXGISwapChain *pSwapChain) { void** vTable = *reinterpret_cast(pDevice); diff --git a/overlay_experimental/DX10_Hook.h b/overlay_experimental/DX10_Hook.h index e66e840..4979e74 100644 --- a/overlay_experimental/DX10_Hook.h +++ b/overlay_experimental/DX10_Hook.h @@ -46,6 +46,7 @@ private: public: bool start_hook(); static DX10_Hook* Inst(); + virtual const char* get_lib_name() const; void loadFunctions(ID3D10Device *pDevice, IDXGISwapChain *pSwapChain); }; diff --git a/overlay_experimental/DX11_Hook.cpp b/overlay_experimental/DX11_Hook.cpp index c27ede6..9cda270 100644 --- a/overlay_experimental/DX11_Hook.cpp +++ b/overlay_experimental/DX11_Hook.cpp @@ -28,57 +28,21 @@ bool DX11_Hook::start_hook() if (!Windows_Hook::Inst().start_hook()) return false; - HWND hWnd = GetGameWindow(); - if (!hWnd) - return false; + PRINT_DEBUG("Hooked DirectX 11\n"); + _hooked = true; - IDXGISwapChain* pSwapChain; - ID3D11Device* pDevice; - DXGI_SWAP_CHAIN_DESC SwapChainDesc = {}; - decltype(D3D11CreateDeviceAndSwapChain)* D3D11CreateDeviceAndSwapChain = - (decltype(D3D11CreateDeviceAndSwapChain))GetProcAddress(reinterpret_cast(_library), "D3D11CreateDeviceAndSwapChain"); - SwapChainDesc.BufferCount = 1; - SwapChainDesc.BufferDesc.Width = 1; - SwapChainDesc.BufferDesc.Height = 1; - SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - SwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0; - SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.OutputWindow = hWnd; - SwapChainDesc.SampleDesc.Count = 1; - SwapChainDesc.SampleDesc.Quality = 0; - SwapChainDesc.Windowed = TRUE; + Hook_Manager::Inst().FoundRenderer(this); - D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, NULL, D3D11_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice, NULL, NULL); + UnhookAll(); + BeginHook(); + HookFuncs( + std::make_pair(&(PVOID&)DX11_Hook::Present, &DX11_Hook::MyPresent), + std::make_pair(&(PVOID&)DX11_Hook::ResizeTarget, &DX11_Hook::MyResizeTarget), + std::make_pair(&(PVOID&)DX11_Hook::ResizeBuffers, &DX11_Hook::MyResizeBuffers) + ); + EndHook(); - if (pDevice != nullptr && pSwapChain != nullptr) - { - PRINT_DEBUG("Hooked DirectX 11\n"); - - _hooked = true; - Hook_Manager::Inst().FoundRenderer(this); - - loadFunctions(pDevice, pSwapChain); - - UnhookAll(); - BeginHook(); - HookFuncs( - std::make_pair(&(PVOID&)DX11_Hook::Present, &DX11_Hook::MyPresent), - std::make_pair(&(PVOID&)DX11_Hook::ResizeTarget, &DX11_Hook::MyResizeTarget), - std::make_pair(&(PVOID&)DX11_Hook::ResizeBuffers, &DX11_Hook::MyResizeBuffers) - ); - EndHook(); - - get_steam_client()->steam_overlay->HookReady(); - } - else - { - PRINT_DEBUG("Failed to hook DirectX 11\n"); - res = false; - } - - if(pDevice) pDevice->Release(); - if(pSwapChain) pSwapChain->Release(); + get_steam_client()->steam_overlay->HookReady(); } return res; } @@ -239,6 +203,11 @@ DX11_Hook* DX11_Hook::Inst() return _inst; } +const char* DX11_Hook::get_lib_name() const +{ + return DLL_NAME; +} + void DX11_Hook::loadFunctions(ID3D11Device *pDevice, IDXGISwapChain *pSwapChain) { void** vTable = *reinterpret_cast(pDevice); diff --git a/overlay_experimental/DX11_Hook.h b/overlay_experimental/DX11_Hook.h index 207252f..83de88d 100644 --- a/overlay_experimental/DX11_Hook.h +++ b/overlay_experimental/DX11_Hook.h @@ -46,6 +46,7 @@ private: public: bool start_hook(); static DX11_Hook* Inst(); + virtual const char* get_lib_name() const; void loadFunctions(ID3D11Device *pDevice, IDXGISwapChain *pSwapChain); }; diff --git a/overlay_experimental/DX9_Hook.cpp b/overlay_experimental/DX9_Hook.cpp index 1842493..e5a0113 100644 --- a/overlay_experimental/DX9_Hook.cpp +++ b/overlay_experimental/DX9_Hook.cpp @@ -14,60 +14,34 @@ DX9_Hook* DX9_Hook::_inst = nullptr; bool DX9_Hook::start_hook() { - bool res = true; if (!_hooked) { if (!Windows_Hook::Inst().start_hook()) return false; - HWND hWnd = GetGameWindow(); - if (!hWnd) - return false; + PRINT_DEBUG("Hooked DirectX 9\n"); + _hooked = true; - IDirect3D9Ex* pD3D; - IDirect3DDevice9Ex* pDeviceEx; - decltype(Direct3DCreate9Ex)* Direct3DCreate9Ex = (decltype(Direct3DCreate9Ex))GetProcAddress(reinterpret_cast(_library), "Direct3DCreate9Ex"); - - Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D); - - D3DPRESENT_PARAMETERS params = {}; - params.BackBufferWidth = 1; - params.BackBufferHeight = 1; - params.hDeviceWindow = hWnd; - - pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, NULL, &pDeviceEx); - - if (pDeviceEx != nullptr) + Hook_Manager::Inst().FoundRenderer(this); + + UnhookAll(); + BeginHook(); + HookFuncs( + std::make_pair(&(PVOID&)Reset, &DX9_Hook::MyReset), + std::make_pair(&(PVOID&)Present, &DX9_Hook::MyPresent) + ); + if (PresentEx != nullptr) { - PRINT_DEBUG("Hooked DirectX 9\n"); - - _hooked = true; - Hook_Manager::Inst().FoundRenderer(this); - - loadFunctions(pDeviceEx); - - UnhookAll(); - BeginHook(); HookFuncs( - std::make_pair(&(PVOID&)Reset, &DX9_Hook::MyReset), - std::make_pair(&(PVOID&)Present, &DX9_Hook::MyPresent), std::make_pair(&(PVOID&)PresentEx, &DX9_Hook::MyPresentEx) //std::make_pair(&(PVOID&)EndScene, &DX9_Hook::MyEndScene) ); - EndHook(); - - get_steam_client()->steam_overlay->HookReady(); - } - else - { - PRINT_DEBUG("Failed to DirectX 9\n"); - res = false; } + EndHook(); - if(pDeviceEx)pDeviceEx->Release(); - if(pD3D)pD3D->Release(); + get_steam_client()->steam_overlay->HookReady(); } - return res; + return true; } void DX9_Hook::resetRenderState() @@ -220,15 +194,21 @@ DX9_Hook* DX9_Hook::Inst() return _inst; } -void DX9_Hook::loadFunctions(IDirect3DDevice9Ex* pDeviceEx) +const char* DX9_Hook::get_lib_name() const { - void** vTable = *reinterpret_cast(pDeviceEx); + return DLL_NAME; +} + +void DX9_Hook::loadFunctions(IDirect3DDevice9* pDevice, bool ex) +{ + void** vTable = *reinterpret_cast(pDevice); #define LOAD_FUNC(X) (void*&)X = vTable[(int)IDirect3DDevice9VTable::X] LOAD_FUNC(Reset); LOAD_FUNC(EndScene); LOAD_FUNC(Present); - LOAD_FUNC(PresentEx); + if (ex) + LOAD_FUNC(PresentEx); #undef LOAD_FUNC } diff --git a/overlay_experimental/DX9_Hook.h b/overlay_experimental/DX9_Hook.h index c795fe3..6239f1b 100644 --- a/overlay_experimental/DX9_Hook.h +++ b/overlay_experimental/DX9_Hook.h @@ -47,8 +47,9 @@ private: public: bool start_hook(); static DX9_Hook* Inst(); + virtual const char* get_lib_name() const; - void loadFunctions(IDirect3DDevice9Ex *pDeviceEx); + void loadFunctions(IDirect3DDevice9 *pDevice, bool ex); }; #endif//NO_OVERLAY diff --git a/overlay_experimental/DirectX_VTables.h b/overlay_experimental/DirectX_VTables.h index 73a2847..46f0497 100644 --- a/overlay_experimental/DirectX_VTables.h +++ b/overlay_experimental/DirectX_VTables.h @@ -44,6 +44,111 @@ enum class IDXGISwapChainVTable GetRotation, }; +enum class ID3D12CommandQueueVTable +{ + // IUnknown + QueryInterface, + AddRef, + Release, + + // ID3D12Object + GetPrivateData, + SetPrivateData, + SetPrivateDataInterface, + SetName, + + // ID3D12DeviceChild + GetDevice, + + // ID3D12Pageable + + // ID3D12CommandQueue + UpdateTileMappings, + CopyTileMappings, + ExecuteCommandLists, + SetMarker, + BeginEvent, + EndEvent, + Signal, + Wait, + GetTimestampFrequency, + GetClockCalibration, + GetDesc, +}; + +enum class ID3D12GraphicsCommandListVTable +{ + // IUnknown + QueryInterface, + AddRef, + Release, + + // ID3D12Object + GetPrivateData, + SetPrivateData, + SetPrivateDataInterface, + SetName, + + // ID3D12DeviceChild + GetDevice, + + // ID3D12CommandList + GetType, + + // ID3D12GraphicsCommandList + Close, + Reset, + ClearState, + DrawInstanced, + DrawIndexedInstanced, + Dispatch, + CopyBufferRegion, + CopyTextureRegion, + CopyResource, + CopyTiles, + ResolveSubresource, + IASetPrimitiveTopology, + RSSetViewports, + RSSetScissorRects, + OMSetBlendFactor, + OMSetStencilRef, + SetPipelineState, + ResourceBarrier, + ExecuteBundle, + SetDescriptorHeaps, + SetComputeRootSignature, + SetGraphicsRootSignature, + SetComputeRootDescriptorTable, + SetGraphicsRootDescriptorTable, + SetComputeRoot32BitConstant, + SetGraphicsRoot32BitConstant, + SetComputeRoot32BitConstants, + SetGraphicsRoot32BitConstants, + SetComputeRootConstantBufferView, + SetGraphicsRootConstantBufferView, + SetComputeRootShaderResourceView, + SetGraphicsRootShaderResourceView, + SetComputeRootUnorderedAccessView, + SetGraphicsRootUnorderedAccessView, + IASetIndexBuffer, + IASetVertexBuffers, + SOSetTargets, + OMSetRenderTargets, + ClearDepthStencilView, + ClearRenderTargetView, + ClearUnorderedAccessViewUint, + ClearUnorderedAccessViewFloat, + DiscardResource, + BeginQuery, + EndQuery, + ResolveQueryData, + SetPredication, + SetMarker, + BeginEvent, + EndEvent, + ExecuteIndirect, +}; + enum class ID3D11DeviceVTable { // IUnknown diff --git a/overlay_experimental/Hook_Manager.cpp b/overlay_experimental/Hook_Manager.cpp index a6458e7..4b18fa6 100644 --- a/overlay_experimental/Hook_Manager.cpp +++ b/overlay_experimental/Hook_Manager.cpp @@ -20,10 +20,10 @@ constexpr int max_hook_retries = 500; #ifdef STEAM_WIN32 -static decltype(&IDXGISwapChain::Present) _IDXGISwapChain_Present; -static decltype(&IDirect3DDevice9::Present) _IDirect3DDevice9_Present; -static decltype(&IDirect3DDevice9Ex::PresentEx) _IDirect3DDevice9Ex_PresentEx; -static decltype(wglMakeCurrent)* _wglMakeCurrent; +static decltype(&IDXGISwapChain::Present) _IDXGISwapChain_Present = nullptr; +static decltype(&IDirect3DDevice9::Present) _IDirect3DDevice9_Present = nullptr; +static decltype(&IDirect3DDevice9Ex::PresentEx) _IDirect3DDevice9Ex_PresentEx = nullptr; +static decltype(wglMakeCurrent)* _wglMakeCurrent = nullptr; HRESULT STDMETHODCALLTYPE Hook_Manager::MyIDXGISwapChain_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags) { @@ -100,11 +100,13 @@ BOOL WINAPI Hook_Manager::MywglMakeCurrent(HDC hDC, HGLRC hGLRC) return _wglMakeCurrent(hDC, hGLRC); } -void Hook_Manager::HookDXGIPresent() +void Hook_Manager::HookDXGIPresent(IDXGISwapChain *pSwapChain) { if (!_dxgi_hooked) { _dxgi_hooked = true; + (void*&)_IDXGISwapChain_Present = (*reinterpret_cast(pSwapChain))[(int)IDXGISwapChainVTable::Present]; + rendererdetect_hook->BeginHook(); rendererdetect_hook->HookFuncs( @@ -115,17 +117,26 @@ void Hook_Manager::HookDXGIPresent() } } -void Hook_Manager::HookDX9Present() +void Hook_Manager::HookDX9Present(IDirect3DDevice9* pDevice, bool ex) { if (!_dx9_hooked) { _dx9_hooked = true; + (void*&)_IDirect3DDevice9_Present = (*reinterpret_cast(pDevice))[(int)IDirect3DDevice9VTable::Present]; + if (ex) + (void*&)_IDirect3DDevice9Ex_PresentEx = (*reinterpret_cast(pDevice))[(int)IDirect3DDevice9VTable::PresentEx]; + rendererdetect_hook->BeginHook(); rendererdetect_hook->HookFuncs( - std::pair((PVOID*)& _IDirect3DDevice9_Present, &Hook_Manager::MyPresent), - std::pair((PVOID*)& _IDirect3DDevice9Ex_PresentEx, &Hook_Manager::MyPresentEx) + std::pair((PVOID*)& _IDirect3DDevice9_Present, &Hook_Manager::MyPresent) ); + if (ex) + { + rendererdetect_hook->HookFuncs( + std::pair((PVOID*)& _IDirect3DDevice9Ex_PresentEx, &Hook_Manager::MyPresentEx) + ); + } rendererdetect_hook->EndHook(); } @@ -154,33 +165,48 @@ void Hook_Manager::hook_dx9() if (!hWnd) return; - IDirect3D9Ex* pD3D; - IDirect3DDevice9Ex* pDeviceEx; - decltype(Direct3DCreate9Ex)* Direct3DCreate9Ex = (decltype(Direct3DCreate9Ex))GetProcAddress(GetModuleHandle(DX9_Hook::DLL_NAME), "Direct3DCreate9Ex"); - - Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D); + IDirect3D9Ex* pD3D = nullptr; + IUnknown* pDevice = nullptr; D3DPRESENT_PARAMETERS params = {}; params.BackBufferWidth = 1; params.BackBufferHeight = 1; params.hDeviceWindow = hWnd; + params.BackBufferCount = 1; + params.Windowed = TRUE; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; - pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, NULL, &pDeviceEx); - - if (pDeviceEx) + decltype(Direct3DCreate9Ex)* Direct3DCreate9Ex = (decltype(Direct3DCreate9Ex))GetProcAddress(GetModuleHandle(DX9_Hook::DLL_NAME), "Direct3DCreate9Ex"); + if (Direct3DCreate9Ex != nullptr) + { + Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D); + pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, NULL, reinterpret_cast(&pDevice)); + } + else + { + decltype(Direct3DCreate9)* Direct3DCreate9 = (decltype(Direct3DCreate9))GetProcAddress(GetModuleHandle(DX9_Hook::DLL_NAME), "Direct3DCreate9"); + if (Direct3DCreate9) + { + pD3D = reinterpret_cast(Direct3DCreate9(D3D_SDK_VERSION)); + pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, reinterpret_cast(&pDevice)); + } + } + + if (pDevice != nullptr) { PRINT_DEBUG("Hooked D3D9::Present to detect DX Version\n"); - (void*&)_IDirect3DDevice9_Present = (*reinterpret_cast(pDeviceEx))[(int)IDirect3DDevice9VTable::Present]; - (void*&)_IDirect3DDevice9Ex_PresentEx = (*reinterpret_cast(pDeviceEx))[(int)IDirect3DDevice9VTable::PresentEx]; - HookDX9Present(); + auto h = DX9_Hook::Inst(); + h->loadFunctions(reinterpret_cast(pDevice), Direct3DCreate9Ex != nullptr); + _hooks.insert(h); + HookDX9Present(reinterpret_cast(pDevice), Direct3DCreate9Ex != nullptr); } else { PRINT_DEBUG("Failed to hook D3D9::Present to detect DX Version\n"); } - if (pDeviceEx)pDeviceEx->Release(); - if (pD3D)pD3D->Release(); + if (pDevice) pDevice->Release(); + if (pD3D) pD3D->Release(); } } @@ -214,8 +240,10 @@ void Hook_Manager::hook_dx10() if (pDevice != nullptr && pSwapChain != nullptr) { PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); - (void*&)_IDXGISwapChain_Present = (*reinterpret_cast(pSwapChain))[(int)IDXGISwapChainVTable::Present]; - HookDXGIPresent(); + auto h = DX10_Hook::Inst(); + h->loadFunctions(pDevice, pSwapChain); + _hooks.insert(h); + HookDXGIPresent(pSwapChain); } else { @@ -256,8 +284,10 @@ void Hook_Manager::hook_dx11() if (pDevice != nullptr && pSwapChain != nullptr) { PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); - (void*&)_IDXGISwapChain_Present = (*reinterpret_cast(pSwapChain))[(int)IDXGISwapChainVTable::Present]; - HookDXGIPresent(); + auto h = DX11_Hook::Inst(); + h->loadFunctions(pDevice, pSwapChain); + _hooks.insert(h); + HookDXGIPresent(pSwapChain); } else { @@ -282,6 +312,7 @@ void Hook_Manager::hook_dx12() D3D12_COMMAND_QUEUE_DESC queueDesc = {}; ID3D12CommandQueue* pCommandQueue = nullptr; ID3D12Device* pDevice = nullptr; + decltype(D3D12CreateDevice)* D3D12CreateDevice = (decltype(D3D12CreateDevice))GetProcAddress(GetModuleHandle(DX12_Hook::DLL_NAME), "D3D12CreateDevice"); @@ -290,14 +321,14 @@ void Hook_Manager::hook_dx12() if (pDevice) { DXGI_SWAP_CHAIN_DESC1 SwapChainDesc = {}; - SwapChainDesc.Width = 0; - SwapChainDesc.Height = 0; + SwapChainDesc.BufferCount = 2; + SwapChainDesc.Width = 1; + SwapChainDesc.Height = 1; SwapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; SwapChainDesc.Stereo = FALSE; SwapChainDesc.SampleDesc = { 1, 0 }; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.BufferCount = 3; - SwapChainDesc.Scaling = DXGI_SCALING_STRETCH; + SwapChainDesc.Scaling = DXGI_SCALING_NONE; SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; @@ -312,8 +343,11 @@ void Hook_Manager::hook_dx12() if (pSwapChain != nullptr) { PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); - (void*&)_IDXGISwapChain_Present = (*reinterpret_cast(pSwapChain))[(int)IDXGISwapChainVTable::Present]; - HookDXGIPresent(); + + auto h = DX12_Hook::Inst(); + h->loadFunctions(pDevice, pCommandQueue, pSwapChain); + _hooks.insert(h); + HookDXGIPresent(pSwapChain); } else { @@ -472,6 +506,7 @@ void Hook_Manager::FoundRenderer(Base_Hook* hook) if (!_renderer_found) { _renderer_found = true; + game_renderer = hook; if (hook == nullptr) PRINT_DEBUG("We found a renderer but couldn't hook it, aborting overlay hook.\n"); @@ -480,16 +515,15 @@ void Hook_Manager::FoundRenderer(Base_Hook* hook) _hook_thread->join(); delete _hook_thread; + _hook_thread = nullptr; // Remove all hooks that are unused - _hooks.erase(std::remove_if(_hooks.begin(), _hooks.end(), [&hook](Base_Hook* it_hook) { - if (hook != it_hook) - { - delete it_hook; - return true; - } - return false; - }), _hooks.end()); + std::set::iterator item; + while ((item = std::find_if(_hooks.begin(), _hooks.end(), [hook](Base_Hook* item) {return item != hook; })) != _hooks.end()) + { + delete *item; + _hooks.erase(item); + } } } diff --git a/overlay_experimental/Hook_Manager.h b/overlay_experimental/Hook_Manager.h index ec0318e..8f1e367 100644 --- a/overlay_experimental/Hook_Manager.h +++ b/overlay_experimental/Hook_Manager.h @@ -5,7 +5,7 @@ #ifndef NO_OVERLAY -#include +#include #include #if defined(_WIN32) || defined(WIN32) @@ -30,13 +30,14 @@ protected: // TODO: If needed, create a second vector with only the renderers hook // Cause actually, a call to FoundRenderer will unhook everything registered except the renderer hook // If you do that, you should consider moving the renderer hooks to its own class and keep this one generic ? - std::vector _hooks; + std::set _hooks; std::thread *_hook_thread; unsigned int _hook_retries; bool _renderer_found; // Is the renderer hooked ? bool _ogl_hooked; // wglMakeCurrent is hooked ? (opengl) Base_Hook* rendererdetect_hook; + Base_Hook* game_renderer; class Steam_Overlay* overlay; Hook_Manager(); @@ -54,9 +55,9 @@ protected: bool _dxgi_hooked; // DXGI Present is hooked ? (DX10, DX11, DX12) // DXGIPresent will be used to detect if DX10, DX11 or DX12 should be used for overlay - void HookDXGIPresent(); + void HookDXGIPresent(IDXGISwapChain* pSwapChain); // DX9 Present and PresentEx will be used to detect if DX9 should be used for overlay - void HookDX9Present(); + void HookDX9Present(IDirect3DDevice9* pDevice, bool ex); // wglMakeCurrent will be used to detect if OpenGL3 should be used for overlay void HookwglMakeCurrent(); // Setup DX9 Device and get vtable @@ -97,7 +98,9 @@ public: // Set the found hook and free all other hooks void FoundRenderer(Base_Hook *hook); - inline void AddHook(Base_Hook* hook) { _hooks.push_back(hook); } + inline void AddHook(Base_Hook* hook) { _hooks.insert(hook); } + + inline Base_Hook* get_renderer() const { return game_renderer; } }; #endif//NO_OVERLAY diff --git a/overlay_experimental/OpenGL_Hook.cpp b/overlay_experimental/OpenGL_Hook.cpp index de3071b..0b77924 100644 --- a/overlay_experimental/OpenGL_Hook.cpp +++ b/overlay_experimental/OpenGL_Hook.cpp @@ -152,4 +152,9 @@ OpenGL_Hook* OpenGL_Hook::Inst() return _inst; } +const char* OpenGL_Hook::get_lib_name() const +{ + return DLL_NAME; +} + #endif//NO_OVERLAY \ No newline at end of file diff --git a/overlay_experimental/OpenGL_Hook.h b/overlay_experimental/OpenGL_Hook.h index f6e2a9f..a0bdb2c 100644 --- a/overlay_experimental/OpenGL_Hook.h +++ b/overlay_experimental/OpenGL_Hook.h @@ -38,6 +38,7 @@ private: public: bool start_hook(); static OpenGL_Hook* Inst(); + virtual const char* get_lib_name() const; }; #endif//NO_OVERLAY diff --git a/overlay_experimental/Windows_Hook.cpp b/overlay_experimental/Windows_Hook.cpp index 4483a14..b7e5731 100644 --- a/overlay_experimental/Windows_Hook.cpp +++ b/overlay_experimental/Windows_Hook.cpp @@ -188,4 +188,9 @@ Windows_Hook& Windows_Hook::Inst() { static Windows_Hook _inst; return _inst; +} + +const char* Windows_Hook::get_lib_name() const +{ + return DLL_NAME; } \ No newline at end of file diff --git a/overlay_experimental/Windows_Hook.h b/overlay_experimental/Windows_Hook.h index be2a0e4..e4c03d3 100644 --- a/overlay_experimental/Windows_Hook.h +++ b/overlay_experimental/Windows_Hook.h @@ -40,6 +40,7 @@ public: WNDPROC GetGameWndProc() const; static Windows_Hook& Inst(); + virtual const char* get_lib_name() const; }; HWND GetGameWindow(); diff --git a/overlay_experimental/steam_overlay.cpp b/overlay_experimental/steam_overlay.cpp index 62c144e..f22712d 100644 --- a/overlay_experimental/steam_overlay.cpp +++ b/overlay_experimental/steam_overlay.cpp @@ -30,12 +30,13 @@ void Steam_Overlay::steam_overlay_callback(void* object, Common_Message* msg) _this->Callback(msg); } -Steam_Overlay::Steam_Overlay(Settings* settings, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking *network) : +Steam_Overlay::Steam_Overlay(Settings* settings, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking* network) : settings(settings), callback_results(callback_results), callbacks(callbacks), run_every_runcb(run_every_runcb), network(network), + setup_overlay_called(false), show_overlay(false), is_ready(false), notif_position(ENotificationPosition::k_EPositionBottomLeft), @@ -75,7 +76,12 @@ void Steam_Overlay::SetNotificationInset(int nHorizontalInset, int nVerticalInse void Steam_Overlay::SetupOverlay() { - Hook_Manager::Inst().HookRenderer(); + std::lock_guard lock(global_mutex); + if (!setup_overlay_called) + { + setup_overlay_called = true; + Hook_Manager::Inst().HookRenderer(); + } } void Steam_Overlay::HookReady() @@ -390,6 +396,9 @@ void Steam_Overlay::OverlayProc( int width, int height ) settings->get_local_name(), settings->get_local_steam_id().ConvertToUint64(), settings->get_local_game_id().AppID()); + ImGui::SameLine(); + Base_Hook *hook = Hook_Manager::Inst().get_renderer(); + ImGui::LabelText("##label", "Renderer: %s", (hook == nullptr ? "Unknown" : hook->get_lib_name())); ImGui::Spacing(); diff --git a/overlay_experimental/steam_overlay.h b/overlay_experimental/steam_overlay.h index c5dee4b..c3337f5 100644 --- a/overlay_experimental/steam_overlay.h +++ b/overlay_experimental/steam_overlay.h @@ -52,6 +52,7 @@ class Steam_Overlay // friend id, show client window (to chat and accept invite maybe) std::map friends; + bool setup_overlay_called; bool is_ready; bool show_overlay; ENotificationPosition notif_position;