Skip to content

Commit

Permalink
Fix more cases where calls into DXGI could crash when render GPU is n…
Browse files Browse the repository at this point in the history
…ot the display GPU
  • Loading branch information
crosire committed Jan 11, 2021
1 parent 8a34bdb commit ef82a78
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 9 deletions.
2 changes: 1 addition & 1 deletion source/d3d10/d3d10.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ HOOK_EXPORT HRESULT WINAPI D3D10CreateDeviceAndSwapChain(IDXGIAdapter *pAdapter,

HOOK_EXPORT HRESULT WINAPI D3D10CreateDeviceAndSwapChain1(IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, D3D10_FEATURE_LEVEL1 HardwareLevel, UINT SDKVersion, DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D10Device1 **ppDevice)
{
// Pass on unmodified in case this called from within 'IDXGISwapChain::Present' or 'IDXGIFactory::CreateSwapChain', which indicates that the DXGI runtime is trying to create an internal device, which should not be hooked
// Pass on unmodified in case this called from within 'CDXGISwapChain::EnsureChildDeviceInternal', which indicates that the DXGI runtime is trying to create an internal device, which should not be hooked
if (g_in_dxgi_runtime)
return reshade::hooks::call(D3D10CreateDeviceAndSwapChain1)(
pAdapter, DriverType, Software, Flags, HardwareLevel, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice);
Expand Down
2 changes: 1 addition & 1 deletion source/d3d11/d3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ HOOK_EXPORT HRESULT WINAPI D3D11CreateDevice(IDXGIAdapter *pAdapter, D3D_DRIVER_

HOOK_EXPORT HRESULT WINAPI D3D11CreateDeviceAndSwapChain(IDXGIAdapter *pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, UINT Flags, const D3D_FEATURE_LEVEL *pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, IDXGISwapChain **ppSwapChain, ID3D11Device **ppDevice, D3D_FEATURE_LEVEL *pFeatureLevel, ID3D11DeviceContext **ppImmediateContext)
{
// Pass on unmodified in case this called from within 'IDXGISwapChain::Present' or 'IDXGIFactory::CreateSwapChain' or 'D3D10CreateDeviceAndSwapChain1', which indicates that the DXGI runtime is trying to create an internal device, which should not be hooked
// Pass on unmodified in case this called from within 'CDXGISwapChain::EnsureChildDeviceInternal' or 'D3D10CreateDeviceAndSwapChain1', which indicates that the DXGI runtime is trying to create an internal device, which should not be hooked
if (g_in_dxgi_runtime)
return reshade::hooks::call(D3D11CreateDeviceAndSwapChain)(
pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, pSwapChainDesc, ppSwapChain, ppDevice, pFeatureLevel, ppImmediateContext);
Expand Down
2 changes: 1 addition & 1 deletion source/dxgi/dxgi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

extern bool is_windows7();

// Use this to filter out internal device created by the DXGI runtime in the D3D device creation hooks
// Needs to be set whenever a DXGI call can end up in 'CDXGISwapChain::EnsureChildDeviceInternal', to avoid hooking internal D3D device creation
extern thread_local bool g_in_dxgi_runtime;

static void dump_format(DXGI_FORMAT format)
Expand Down
32 changes: 26 additions & 6 deletions source/dxgi/dxgi_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

extern UINT query_device(IUnknown *&device, com_ptr<IUnknown> &device_proxy);

// Needs to be set whenever a DXGI call can end up in 'CDXGISwapChain::EnsureChildDeviceInternal', to avoid hooking internal D3D device creation
thread_local bool g_in_dxgi_runtime = false;

DXGISwapChain::DXGISwapChain(D3D10Device *device, IDXGISwapChain *original) :
Expand Down Expand Up @@ -238,7 +239,7 @@ ULONG STDMETHODCALLTYPE DXGISwapChain::Release()
{
case 10:
delete static_cast<reshade::d3d10::runtime_d3d10 *>(_runtime);
break;
break;
case 11:
delete static_cast<reshade::d3d11::runtime_d3d11 *>(_runtime);
break;
Expand Down Expand Up @@ -306,15 +307,24 @@ HRESULT STDMETHODCALLTYPE DXGISwapChain::SetFullscreenState(BOOL Fullscreen, IDX
{
LOG(INFO) << "Redirecting " << "IDXGISwapChain::SetFullscreenState" << '(' << "this = " << this << ", Fullscreen = " << (Fullscreen ? "TRUE" : "FALSE") << ", pTarget = " << pTarget << ')' << " ...";

return _orig->SetFullscreenState(Fullscreen, pTarget);
g_in_dxgi_runtime = true;
const HRESULT hr = _orig->SetFullscreenState(Fullscreen, pTarget);
g_in_dxgi_runtime = false;
return hr;
}
HRESULT STDMETHODCALLTYPE DXGISwapChain::GetFullscreenState(BOOL *pFullscreen, IDXGIOutput **ppTarget)
{
return _orig->GetFullscreenState(pFullscreen, ppTarget);
g_in_dxgi_runtime = true;
const HRESULT hr = _orig->GetFullscreenState(pFullscreen, ppTarget);
g_in_dxgi_runtime = false;
return hr;
}
HRESULT STDMETHODCALLTYPE DXGISwapChain::GetDesc(DXGI_SWAP_CHAIN_DESC *pDesc)
{
return _orig->GetDesc(pDesc);
g_in_dxgi_runtime = true;
const HRESULT hr = _orig->GetDesc(pDesc);
g_in_dxgi_runtime = false;
return hr;
}
HRESULT STDMETHODCALLTYPE DXGISwapChain::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags)
{
Expand All @@ -336,7 +346,9 @@ HRESULT STDMETHODCALLTYPE DXGISwapChain::ResizeBuffers(UINT BufferCount, UINT Wi
if (_force_10_bit_format)
NewFormat = DXGI_FORMAT_R10G10B10A2_UNORM;

g_in_dxgi_runtime = true;
const HRESULT hr = _orig->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags);
g_in_dxgi_runtime = false;
if (hr == DXGI_ERROR_INVALID_CALL) // Ignore invalid call errors since the device is still in a usable state afterwards
{
LOG(WARN) << "IDXGISwapChain::ResizeBuffers" << " failed with error code " << "DXGI_ERROR_INVALID_CALL" << '.';
Expand All @@ -353,7 +365,10 @@ HRESULT STDMETHODCALLTYPE DXGISwapChain::ResizeBuffers(UINT BufferCount, UINT Wi
}
HRESULT STDMETHODCALLTYPE DXGISwapChain::ResizeTarget(const DXGI_MODE_DESC *pNewTargetParameters)
{
return _orig->ResizeTarget(pNewTargetParameters);
g_in_dxgi_runtime = true;
const HRESULT hr = _orig->ResizeTarget(pNewTargetParameters);
g_in_dxgi_runtime = false;
return hr;
}
HRESULT STDMETHODCALLTYPE DXGISwapChain::GetContainingOutput(IDXGIOutput **ppOutput)
{
Expand All @@ -371,7 +386,10 @@ HRESULT STDMETHODCALLTYPE DXGISwapChain::GetLastPresentCount(UINT *pLastPresentC
HRESULT STDMETHODCALLTYPE DXGISwapChain::GetDesc1(DXGI_SWAP_CHAIN_DESC1 *pDesc)
{
assert(_interface_version >= 1);
return static_cast<IDXGISwapChain1 *>(_orig)->GetDesc1(pDesc);
g_in_dxgi_runtime = true;
const HRESULT hr = static_cast<IDXGISwapChain1 *>(_orig)->GetDesc1(pDesc);
g_in_dxgi_runtime = false;
return hr;
}
HRESULT STDMETHODCALLTYPE DXGISwapChain::GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pDesc)
{
Expand Down Expand Up @@ -517,7 +535,9 @@ HRESULT STDMETHODCALLTYPE DXGISwapChain::ResizeBuffers1(UINT BufferCount, UINT W
}

assert(_interface_version >= 3);
g_in_dxgi_runtime = true;
const HRESULT hr = static_cast<IDXGISwapChain3 *>(_orig)->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, present_queues.data());
g_in_dxgi_runtime = false;
if (hr == DXGI_ERROR_INVALID_CALL)
{
LOG(WARN) << "IDXGISwapChain3::ResizeBuffers1" << " failed with error code " << "DXGI_ERROR_INVALID_CALL" << '.';
Expand Down

0 comments on commit ef82a78

Please sign in to comment.