From 410d3b2c02535306a454804178fe8611bb4603e7 Mon Sep 17 00:00:00 2001 From: "s.makeev_local" Date: Tue, 6 Jun 2017 17:04:38 +0300 Subject: [PATCH] Workaround to fix crash in applications with invalid use of DXGI. --- renderdoc/driver/dxgi/dxgi_wrapped.cpp | 116 +++++++++++++- renderdoc/driver/dxgi/dxgi_wrapped.h | 204 ++++++++++++++++++++++++- 2 files changed, 313 insertions(+), 7 deletions(-) diff --git a/renderdoc/driver/dxgi/dxgi_wrapped.cpp b/renderdoc/driver/dxgi/dxgi_wrapped.cpp index 7437db562..6c78e981d 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.cpp +++ b/renderdoc/driver/dxgi/dxgi_wrapped.cpp @@ -204,7 +204,7 @@ HRESULT RefCountDXGIObject::WrapQueryInterface(IUnknown *real, REFIID riid, void } WrappedIDXGISwapChain4::WrappedIDXGISwapChain4(IDXGISwapChain *real, HWND wnd, ID3DDevice *device) - : RefCountDXGIObject(real), m_pReal(real), m_pDevice(device), m_iRefcount(1), m_Wnd(wnd) + : RefCountDXGIObject(real), m_pReal(real), m_pDevice(device), m_Wnd(wnd) { DXGI_SWAP_CHAIN_DESC desc; real->GetDesc(&desc); @@ -532,8 +532,118 @@ HRESULT WrappedIDXGISwapChain4::Present1(UINT SyncInterval, UINT Flags, return m_pReal1->Present1(SyncInterval, Flags, pPresentParameters); } +WrappedIDXGIOutput5::WrappedIDXGIOutput5(RefCountDXGIObject *owner, IDXGIOutput *real) + : RefCountDXGIObject(real), m_Owner(owner), m_pReal(real) +{ + SAFE_ADDREF(m_Owner); + + m_pReal1 = NULL; + real->QueryInterface(__uuidof(IDXGIOutput1), (void **)&m_pReal1); + m_pReal2 = NULL; + real->QueryInterface(__uuidof(IDXGIOutput2), (void **)&m_pReal2); + m_pReal3 = NULL; + real->QueryInterface(__uuidof(IDXGIOutput3), (void **)&m_pReal3); + m_pReal4 = NULL; + real->QueryInterface(__uuidof(IDXGIOutput4), (void **)&m_pReal4); + m_pReal5 = NULL; + real->QueryInterface(__uuidof(IDXGIOutput5), (void **)&m_pReal5); +} + +WrappedIDXGIOutput5::~WrappedIDXGIOutput5() +{ + SAFE_RELEASE(m_pReal1); + SAFE_RELEASE(m_pReal2); + SAFE_RELEASE(m_pReal3); + SAFE_RELEASE(m_pReal4); + SAFE_RELEASE(m_pReal5); + SAFE_RELEASE(m_pReal); + SAFE_RELEASE(m_Owner); +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput5::QueryInterface(REFIID riid, void **ppvObject) +{ + if(riid == __uuidof(IDXGIOutput)) + { + AddRef(); + *ppvObject = (IDXGIOutput *)this; + return S_OK; + } + else if(riid == __uuidof(IDXGIOutput1)) + { + if(m_pReal1) + { + AddRef(); + *ppvObject = (IDXGIOutput1 *)this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } + else if(riid == __uuidof(IDXGIOutput2)) + { + if(m_pReal2) + { + AddRef(); + *ppvObject = (IDXGIOutput2 *)this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } + else if(riid == __uuidof(IDXGIOutput3)) + { + if(m_pReal3) + { + AddRef(); + *ppvObject = (IDXGIOutput3 *)this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } + else if(riid == __uuidof(IDXGIOutput4)) + { + if(m_pReal3) + { + AddRef(); + *ppvObject = (IDXGIOutput4 *)this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } + else if(riid == __uuidof(IDXGIOutput5)) + { + if(m_pReal3) + { + AddRef(); + *ppvObject = (IDXGIOutput5 *)this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } + else + { + string guid = ToStr::Get(riid); + RDCWARN("Querying IDXGIOutput for interface: %s", guid.c_str()); + } + + return RefCountDXGIObject::QueryInterface(riid, ppvObject); +} + WrappedIDXGIAdapter3::WrappedIDXGIAdapter3(IDXGIAdapter *real) - : RefCountDXGIObject(real), m_pReal(real), m_iRefcount(1) + : RefCountDXGIObject(real), m_pReal(real) { m_pReal1 = NULL; real->QueryInterface(__uuidof(IDXGIAdapter1), (void **)&m_pReal1); @@ -708,7 +818,7 @@ HRESULT STDMETHODCALLTYPE WrappedIDXGIDevice4::QueryInterface(REFIID riid, void } WrappedIDXGIFactory5::WrappedIDXGIFactory5(IDXGIFactory *real) - : RefCountDXGIObject(real), m_pReal(real), m_iRefcount(1) + : RefCountDXGIObject(real), m_pReal(real) { m_pReal1 = NULL; real->QueryInterface(__uuidof(IDXGIFactory1), (void **)&m_pReal1); diff --git a/renderdoc/driver/dxgi/dxgi_wrapped.h b/renderdoc/driver/dxgi/dxgi_wrapped.h index f9d9ce6e9..b6dd71d9e 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.h +++ b/renderdoc/driver/dxgi/dxgi_wrapped.h @@ -548,7 +548,6 @@ class WrappedIDXGISwapChain4 : public IDXGISwapChain4, public RefCountDXGIObject IDXGISwapChain3 *m_pReal3; IDXGISwapChain4 *m_pReal4; ID3DDevice *m_pDevice; - unsigned int m_iRefcount; static std::vector m_D3DCallbacks; @@ -844,13 +843,206 @@ public: } }; +class WrappedIDXGIOutput5 : public IDXGIOutput5, public RefCountDXGIObject +{ + RefCountDXGIObject *m_Owner; + IDXGIOutput *m_pReal; + IDXGIOutput1 *m_pReal1; + IDXGIOutput2 *m_pReal2; + IDXGIOutput3 *m_pReal3; + IDXGIOutput4 *m_pReal4; + IDXGIOutput5 *m_pReal5; + +public: + IMPLEMENT_IDXGIOBJECT_WITH_REFCOUNTDXGIOBJECT_CUSTOMQUERY; + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + + WrappedIDXGIOutput5(RefCountDXGIObject *owner, IDXGIOutput *real); + ~WrappedIDXGIOutput5(); + + ////////////////////////////// + // implement IDXGIOutput + + virtual HRESULT STDMETHODCALLTYPE GetDesc( + /* [annotation][out] */ + _Out_ DXGI_OUTPUT_DESC *pDesc) + { + return m_pReal->GetDesc(pDesc); + } + + virtual HRESULT STDMETHODCALLTYPE GetDisplayModeList( + /* [in] */ DXGI_FORMAT EnumFormat, + /* [in] */ UINT Flags, + /* [annotation][out][in] */ + _Inout_ UINT *pNumModes, + /* [annotation][out] */ + _Out_writes_to_opt_(*pNumModes, *pNumModes) DXGI_MODE_DESC *pDesc) + { + return m_pReal->GetDisplayModeList(EnumFormat, Flags, pNumModes, pDesc); + } + + virtual HRESULT STDMETHODCALLTYPE FindClosestMatchingMode( + /* [annotation][in] */ + _In_ const DXGI_MODE_DESC *pModeToMatch, + /* [annotation][out] */ + _Out_ DXGI_MODE_DESC *pClosestMatch, + /* [annotation][in] */ + _In_opt_ IUnknown *pConcernedDevice) + { + return m_pReal->FindClosestMatchingMode(pModeToMatch, pClosestMatch, pConcernedDevice); + } + + virtual HRESULT STDMETHODCALLTYPE WaitForVBlank(void) { return m_pReal->WaitForVBlank(); } + virtual HRESULT STDMETHODCALLTYPE TakeOwnership( + /* [annotation][in] */ + _In_ IUnknown *pDevice, BOOL Exclusive) + { + return m_pReal->TakeOwnership(pDevice, Exclusive); + } + + virtual void STDMETHODCALLTYPE ReleaseOwnership(void) { return m_pReal->ReleaseOwnership(); } + virtual HRESULT STDMETHODCALLTYPE GetGammaControlCapabilities( + /* [annotation][out] */ + _Out_ DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps) + { + return m_pReal->GetGammaControlCapabilities(pGammaCaps); + } + + virtual HRESULT STDMETHODCALLTYPE SetGammaControl( + /* [annotation][in] */ + _In_ const DXGI_GAMMA_CONTROL *pArray) + { + return m_pReal->SetGammaControl(pArray); + } + + virtual HRESULT STDMETHODCALLTYPE GetGammaControl( + /* [annotation][out] */ + _Out_ DXGI_GAMMA_CONTROL *pArray) + { + return m_pReal->GetGammaControl(pArray); + } + + virtual HRESULT STDMETHODCALLTYPE SetDisplaySurface( + /* [annotation][in] */ + _In_ IDXGISurface *pScanoutSurface) + { + return m_pReal->SetDisplaySurface(pScanoutSurface); + } + + virtual HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData( + /* [annotation][in] */ + _In_ IDXGISurface *pDestination) + { + return m_pReal->GetDisplaySurfaceData(pDestination); + } + + virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics( + /* [annotation][out] */ + _Out_ DXGI_FRAME_STATISTICS *pStats) + { + return m_pReal->GetFrameStatistics(pStats); + } + + ////////////////////////////// + // implement IDXGIOutput1 + + virtual HRESULT STDMETHODCALLTYPE GetDisplayModeList1( + /* [in] */ DXGI_FORMAT EnumFormat, + /* [in] */ UINT Flags, + /* [annotation][out][in] */ + _Inout_ UINT *pNumModes, + /* [annotation][out] */ + _Out_writes_to_opt_(*pNumModes, *pNumModes) DXGI_MODE_DESC1 *pDesc) + { + return m_pReal1->GetDisplayModeList1(EnumFormat, Flags, pNumModes, pDesc); + } + + virtual HRESULT STDMETHODCALLTYPE FindClosestMatchingMode1( + /* [annotation][in] */ + _In_ const DXGI_MODE_DESC1 *pModeToMatch, + /* [annotation][out] */ + _Out_ DXGI_MODE_DESC1 *pClosestMatch, + /* [annotation][in] */ + _In_opt_ IUnknown *pConcernedDevice) + { + return m_pReal1->FindClosestMatchingMode1(pModeToMatch, pClosestMatch, pConcernedDevice); + } + + virtual HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData1( + /* [annotation][in] */ + _In_ IDXGIResource *pDestination) + { + return m_pReal1->GetDisplaySurfaceData1(pDestination); + } + + virtual HRESULT STDMETHODCALLTYPE DuplicateOutput( + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][out] */ + _COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication) + { + return m_pReal1->DuplicateOutput(pDevice, ppOutputDuplication); + } + + ////////////////////////////// + // implement IDXGIOutput2 + + virtual BOOL STDMETHODCALLTYPE SupportsOverlays(void) { return m_pReal2->SupportsOverlays(); } + ////////////////////////////// + // implement IDXGIOutput3 + + virtual HRESULT STDMETHODCALLTYPE CheckOverlaySupport( + /* [annotation][in] */ + _In_ DXGI_FORMAT EnumFormat, + /* [annotation][out] */ + _In_ IUnknown *pConcernedDevice, + /* [annotation][out] */ + _Out_ UINT *pFlags) + { + return m_pReal3->CheckOverlaySupport(EnumFormat, pConcernedDevice, pFlags); + } + + ////////////////////////////// + // implement IDXGIOutput4 + + virtual HRESULT STDMETHODCALLTYPE CheckOverlayColorSpaceSupport( + /* [annotation][in] */ + _In_ DXGI_FORMAT Format, + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace, + /* [annotation][in] */ + _In_ IUnknown *pConcernedDevice, + /* [annotation][out] */ + _Out_ UINT *pFlags) + { + return m_pReal4->CheckOverlayColorSpaceSupport(Format, ColorSpace, pConcernedDevice, pFlags); + } + + ////////////////////////////// + // implement IDXGIOutput5 + + virtual HRESULT STDMETHODCALLTYPE DuplicateOutput1( + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [in] */ UINT Flags, + /* [annotation][in] */ + _In_ UINT SupportedFormatsCount, + /* [annotation][in] */ + _In_reads_(SupportedFormatsCount) const DXGI_FORMAT *pSupportedFormats, + /* [annotation][out] */ + _COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication) + { + return m_pReal5->DuplicateOutput1(pDevice, Flags, SupportedFormatsCount, pSupportedFormats, + ppOutputDuplication); + } +}; + class WrappedIDXGIAdapter3 : public IDXGIAdapter3, public RefCountDXGIObject { IDXGIAdapter *m_pReal; IDXGIAdapter1 *m_pReal1; IDXGIAdapter2 *m_pReal2; IDXGIAdapter3 *m_pReal3; - unsigned int m_iRefcount; public: WrappedIDXGIAdapter3(IDXGIAdapter *real); @@ -867,7 +1059,12 @@ public: /* [annotation][out][in] */ __out IDXGIOutput **ppOutput) { - return m_pReal->EnumOutputs(Output, ppOutput); + HRESULT ret = m_pReal->EnumOutputs(Output, ppOutput); + + if(SUCCEEDED(ret)) + *ppOutput = (IDXGIOutput *)(new WrappedIDXGIOutput5(this, *ppOutput)); + + return ret; } virtual HRESULT STDMETHODCALLTYPE GetDesc( @@ -1120,7 +1317,6 @@ class WrappedIDXGIFactory5 : public IDXGIFactory5, public RefCountDXGIObject IDXGIFactory3 *m_pReal3; IDXGIFactory4 *m_pReal4; IDXGIFactory5 *m_pReal5; - unsigned int m_iRefcount; public: WrappedIDXGIFactory5(IDXGIFactory *real);