diff --git a/renderdoc/driver/d3d11/d3d11_common.h b/renderdoc/driver/d3d11/d3d11_common.h index eeadac30a..dee7490ee 100644 --- a/renderdoc/driver/d3d11/d3d11_common.h +++ b/renderdoc/driver/d3d11/d3d11_common.h @@ -421,6 +421,7 @@ enum class D3D11Chunk : uint32_t PostExecuteCommandList, PostFinishCommandListSet, SwapDeviceContextState, + ExternalDXGIResource, Max, }; diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 622480fab..24c459bd4 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -993,6 +993,7 @@ bool WrappedID3D11Device::ProcessChunk(ReadSerialiser &ser, D3D11Chunk context) case D3D11Chunk::CreateDeferredContext: return Serialise_CreateDeferredContext(ser, 0, 0x0); case D3D11Chunk::SetExceptionMode: return Serialise_SetExceptionMode(ser, 0); + case D3D11Chunk::ExternalDXGIResource: case D3D11Chunk::OpenSharedResource: { IID nul; @@ -1468,6 +1469,24 @@ IUnknown *WrappedID3D11Device::WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_F return pTex; } +IDXGIResource *WrappedID3D11Device::WrapExternalDXGIResource(IDXGIResource *res) +{ + ID3D11Resource *d3d11res; + res->QueryInterface(__uuidof(ID3D11Resource), (void **)&d3d11res); + if(GetResourceManager()->HasWrapper(d3d11res)) + { + ID3D11DeviceChild *wrapper = GetResourceManager()->GetWrapper(d3d11res); + IDXGIResource *ret = NULL; + wrapper->QueryInterface(__uuidof(IDXGIResource), (void **)&ret); + res->Release(); + return ret; + } + + void *voidRes = (void *)res; + OpenSharedResourceInternal(true, 0, __uuidof(IDXGIResource), &voidRes); + return (IDXGIResource *)voidRes; +} + void WrappedID3D11Device::SetMarker(uint32_t col, const wchar_t *name) { if(m_pCurrentWrappedDevice == NULL) diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 44a45f9e7..58abe258b 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -548,6 +548,8 @@ public: void ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount, IUnknown *const *ppPresentQueue, IUnknown **unwrappedQueues); + virtual IDXGIResource *WrapExternalDXGIResource(IDXGIResource *res); + ResourceId GetBackbufferResourceID() { return m_BBID; } void InternalRef() { InterlockedIncrement(&m_InternalRefcount); } void InternalRelease() { InterlockedDecrement(&m_InternalRefcount); } @@ -607,6 +609,9 @@ public: SerialiserType &ser, ID3D11Resource *tex, ResourceId id, const D3D11_SUBRESOURCE_DATA *data, UINT w, UINT h, UINT d, DXGI_FORMAT fmt, UINT mips, UINT arr, bool HasData); + HRESULT STDMETHODCALLTYPE OpenSharedResourceInternal(bool externalResource, HANDLE hResource, + REFIID ReturnedInterface, void **ppResource); + // this is defined as a macro so that we can re-use it to explicitly instantiate these functions as // templates in the wrapper definition file. #define SERIALISED_ID3D11DEVICE_FUNCTIONS() \ diff --git a/renderdoc/driver/d3d11/d3d11_device_wrap.cpp b/renderdoc/driver/d3d11/d3d11_device_wrap.cpp index 8804f1d74..1748974ff 100644 --- a/renderdoc/driver/d3d11/d3d11_device_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_device_wrap.cpp @@ -3273,6 +3273,12 @@ bool WrappedID3D11Device::Serialise_OpenSharedResource(SerialiserType &ser, HAND HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID ReturnedInterface, void **ppResource) +{ + return OpenSharedResourceInternal(false, hResource, ReturnedInterface, ppResource); +} + +HRESULT WrappedID3D11Device::OpenSharedResourceInternal(bool externalResource, HANDLE hResource, + REFIID ReturnedInterface, void **ppResource) { if(IsReplayMode(m_State)) { @@ -3294,7 +3300,16 @@ HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID Returne { void *res = NULL; HRESULT hr; - SERIALISE_TIME_CALL(hr = m_pDevice->OpenSharedResource(hResource, ReturnedInterface, &res)); + + if(externalResource) + { + res = *ppResource; + SERIALISE_TIME_CALL(hr = S_OK); + } + else + { + SERIALISE_TIME_CALL(hr = m_pDevice->OpenSharedResource(hResource, ReturnedInterface, &res)); + } if(FAILED(hr)) { @@ -3362,6 +3377,8 @@ HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID Returne ID3D11Resource *realRes = NULL; + void *ppvWrapped = NULL; + if(isBuf) { WrappedID3D11Buffer *w = new WrappedID3D11Buffer((ID3D11Buffer *)res, 0, this); @@ -3369,7 +3386,21 @@ HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID Returne realRes = w->GetReal(); - *ppResource = (ID3D11Buffer *)w; + ppvWrapped = (ID3D11Buffer *)w; + + if(isDXGIRes) + { + w->QueryInterface(__uuidof(IDXGIResource), ppResource); + w->Release(); + } + else if(isRes) + { + *ppResource = (ID3D11Resource *)w; + } + else + { + *ppResource = (ID3D11Buffer *)w; + } } else if(isTex1D) { @@ -3378,7 +3409,21 @@ HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID Returne realRes = w->GetReal(); - *ppResource = (ID3D11Texture1D *)w; + ppvWrapped = (ID3D11Texture1D *)w; + + if(isDXGIRes) + { + w->QueryInterface(__uuidof(IDXGIResource), ppResource); + w->Release(); + } + else if(isRes) + { + *ppResource = (ID3D11Resource *)w; + } + else + { + *ppResource = (ID3D11Texture1D *)w; + } } else if(isTex2D) { @@ -3387,7 +3432,21 @@ HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID Returne realRes = w->GetReal(); - *ppResource = (ID3D11Texture2D *)w; + ppvWrapped = (ID3D11Texture2D *)w; + + if(isDXGIRes) + { + w->QueryInterface(__uuidof(IDXGIResource), ppResource); + w->Release(); + } + else if(isRes) + { + *ppResource = (ID3D11Resource *)w; + } + else + { + *ppResource = (ID3D11Texture2D *)w; + } } else if(isTex3D) { @@ -3396,15 +3455,30 @@ HRESULT WrappedID3D11Device::OpenSharedResource(HANDLE hResource, REFIID Returne realRes = w->GetReal(); - *ppResource = (ID3D11Texture3D *)w; + ppvWrapped = (ID3D11Texture3D *)w; + + if(isDXGIRes) + { + w->QueryInterface(__uuidof(IDXGIResource), ppResource); + w->Release(); + } + else if(isRes) + { + *ppResource = (ID3D11Resource *)w; + } + else + { + *ppResource = (ID3D11Texture3D *)w; + } } Chunk *chunk = NULL; { USE_SCRATCH_SERIALISER(); - SCOPED_SERIALISE_CHUNK(D3D11Chunk::OpenSharedResource); - Serialise_OpenSharedResource(GET_SERIALISER, hResource, ReturnedInterface, ppResource); + SCOPED_SERIALISE_CHUNK(externalResource ? D3D11Chunk::ExternalDXGIResource + : D3D11Chunk::OpenSharedResource); + Serialise_OpenSharedResource(GET_SERIALISER, hResource, ReturnedInterface, &ppvWrapped); chunk = scope.Get(); } diff --git a/renderdoc/driver/d3d11/d3d11_stringise.cpp b/renderdoc/driver/d3d11/d3d11_stringise.cpp index fd50c1cd4..471dc66a1 100644 --- a/renderdoc/driver/d3d11/d3d11_stringise.cpp +++ b/renderdoc/driver/d3d11/d3d11_stringise.cpp @@ -59,7 +59,7 @@ rdcstr DoStringise(const D3D11ResourceType &el) template <> rdcstr DoStringise(const D3D11Chunk &el) { - RDCCOMPILE_ASSERT((uint32_t)D3D11Chunk::Max == 1127, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)D3D11Chunk::Max == 1128, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(D3D11Chunk) { @@ -209,6 +209,7 @@ rdcstr DoStringise(const D3D11Chunk &el) STRINGISE_ENUM_CLASS_NAMED(PostFinishCommandListSet, "ID3D11DeviceContext::FinishCommandList"); STRINGISE_ENUM_CLASS_NAMED(SwapDeviceContextState, "ID3D11DeviceContext1::SwapDeviceContextState"); + STRINGISE_ENUM_CLASS_NAMED(ExternalDXGIResource, "External DXGI Resource import"); STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk"); } END_ENUM_STRINGISE() diff --git a/renderdoc/driver/d3d12/d3d12_command_queue.h b/renderdoc/driver/d3d12/d3d12_command_queue.h index a67359ffc..ab98c733f 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue.h +++ b/renderdoc/driver/d3d12/d3d12_command_queue.h @@ -195,6 +195,10 @@ public: { return m_pDevice->WrapSwapchainBuffer(swapper, bufferFormat, buffer, realSurface); } + virtual IDXGIResource *WrapExternalDXGIResource(IDXGIResource *res) + { + return m_pDevice->WrapExternalDXGIResource(res); + } virtual HRESULT Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags) { diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index ecc6be6d7..a9db2404c 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -826,5 +826,6 @@ enum class D3D12Chunk : uint32_t List_EndRenderPass, List_RSSetShadingRate, List_RSSetShadingRateImage, + Device_ExternalDXGIResource, Max, }; diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 5e6ee201e..ca8de4dd6 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -1135,6 +1135,24 @@ IUnknown *WrappedID3D12Device::WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_F return pRes; } +IDXGIResource *WrappedID3D12Device::WrapExternalDXGIResource(IDXGIResource *res) +{ + ID3D12Resource *d3d12res; + res->QueryInterface(__uuidof(ID3D12Resource), (void **)&d3d12res); + if(GetResourceManager()->HasWrapper(d3d12res)) + { + ID3D12DeviceChild *wrapper = GetResourceManager()->GetWrapper(d3d12res); + IDXGIResource *ret = NULL; + wrapper->QueryInterface(__uuidof(IDXGIResource), (void **)&ret); + res->Release(); + return ret; + } + + void *voidRes = (void *)res; + OpenSharedHandleInternal(true, 0, __uuidof(IDXGIResource), &voidRes); + return (IDXGIResource *)voidRes; +} + void WrappedID3D12Device::Map(ID3D12Resource *Resource, UINT Subresource) { MapState map; @@ -2896,6 +2914,9 @@ bool WrappedID3D12Device::ProcessChunk(ReadSerialiser &ser, D3D12Chunk context) return Serialise_CreateCommittedResource1(ser, NULL, D3D12_HEAP_FLAG_NONE, NULL, D3D12_RESOURCE_STATE_COMMON, NULL, NULL, IID(), NULL); case D3D12Chunk::Device_CreateHeap1: return Serialise_CreateHeap1(ser, NULL, NULL, IID(), NULL); + case D3D12Chunk::Device_ExternalDXGIResource: + return Serialise_OpenSharedHandle(ser, NULL, IID(), NULL); + break; default: { SystemChunk system = (SystemChunk)context; diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index bd0b1c174..9ec3171ee 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -713,6 +713,8 @@ public: void ReleaseSwapchainResources(IDXGISwapper *swapper, UINT QueueCount, IUnknown *const *ppPresentQueue, IUnknown **unwrappedQueues); + IDXGIResource *WrapExternalDXGIResource(IDXGIResource *res); + void Map(ID3D12Resource *Resource, UINT Subresource); void Unmap(ID3D12Resource *Resource, UINT Subresource, byte *mapPtr, const D3D12_RANGE *pWrittenRange); @@ -954,6 +956,9 @@ public: const SECURITY_ATTRIBUTES *pAttributes, DWORD Access, LPCWSTR Name, HANDLE *pHandle); + HRESULT STDMETHODCALLTYPE OpenSharedHandleInternal(bool externalResource, HANDLE NTHandle, + REFIID riid, void **ppvObj); + IMPLEMENT_FUNCTION_THREAD_SERIALISED(virtual HRESULT STDMETHODCALLTYPE, OpenSharedHandle, HANDLE NTHandle, REFIID riid, void **ppvObj); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index bdf3b588b..6a874d623 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -2284,7 +2284,7 @@ bool WrappedID3D12Device::Serialise_OpenSharedHandle(SerialiserType &ser, HANDLE D3D12_HEAP_PROPERTIES heapProperties; D3D12_HEAP_FLAGS heapFlags; - ID3D12Resource *res{}; + ID3D12Resource *res = NULL; if(ser.IsWriting()) { res = (ID3D12Resource *)*ppvObj; @@ -2375,6 +2375,12 @@ bool WrappedID3D12Device::Serialise_OpenSharedHandle(SerialiserType &ser, HANDLE } HRESULT WrappedID3D12Device::OpenSharedHandle(HANDLE NTHandle, REFIID riid, void **ppvObj) +{ + return OpenSharedHandleInternal(false, NTHandle, riid, ppvObj); +} + +HRESULT WrappedID3D12Device::OpenSharedHandleInternal(bool externalResource, HANDLE NTHandle, + REFIID riid, void **ppvObj) { if(IsReplayMode(m_State)) { @@ -2385,12 +2391,22 @@ HRESULT WrappedID3D12Device::OpenSharedHandle(HANDLE NTHandle, REFIID riid, void if(ppvObj == NULL) return E_INVALIDARG; + bool isDXGIRes = (riid == __uuidof(IDXGIResource) ? true : false); bool isRes = (riid == __uuidof(ID3D12Resource) ? true : false); - if(isRes) + if(isDXGIRes || isRes) { void *ret = NULL; HRESULT hr; - SERIALISE_TIME_CALL(hr = m_pDevice->OpenSharedHandle(NTHandle, riid, &ret)); + + if(externalResource) + { + ret = *ppvObj; + SERIALISE_TIME_CALL(hr = S_OK); + } + else + { + SERIALISE_TIME_CALL(hr = m_pDevice->OpenSharedHandle(NTHandle, riid, &ret)); + } if(FAILED(hr)) { @@ -2400,15 +2416,44 @@ HRESULT WrappedID3D12Device::OpenSharedHandle(HANDLE NTHandle, REFIID riid, void } else { + if(isDXGIRes) + { + IDXGIResource *dxgiRes = (IDXGIResource *)ret; + + ID3D12Resource *d3d12Res = NULL; + hr = dxgiRes->QueryInterface(__uuidof(ID3D12Resource), (void **)&d3d12Res); + + // if we can't get a d3d11Res then we can't properly wrap this resource, + // whatever it is. + if(FAILED(hr) || d3d12Res == NULL) + { + SAFE_RELEASE(d3d12Res); + SAFE_RELEASE(dxgiRes); + return E_NOINTERFACE; + } + + // release this interface + SAFE_RELEASE(dxgiRes); + + // and use this one, so it'll be casted back below + ret = (void *)d3d12Res; + isRes = true; + } + ID3D12Resource *real = (ID3D12Resource *)ret; WrappedID3D12Resource1 *wrapped = new WrappedID3D12Resource1(real, this); - *ppvObj = (ID3D12Resource *)wrapped; + + if(isDXGIRes) + wrapped->QueryInterface(__uuidof(IDXGIResource), ppvObj); + else + *ppvObj = (ID3D12Resource *)wrapped; CACHE_THREAD_SERIALISER(); - SCOPED_SERIALISE_CHUNK(D3D12Chunk::Device_OpenSharedHandle); - Serialise_OpenSharedHandle(ser, NTHandle, riid, ppvObj); + SCOPED_SERIALISE_CHUNK(externalResource ? D3D12Chunk::Device_ExternalDXGIResource + : D3D12Chunk::Device_OpenSharedHandle); + Serialise_OpenSharedHandle(ser, NTHandle, __uuidof(ID3D12Resource), (void **)&wrapped); D3D12_RESOURCE_DESC desc = wrapped->GetDesc(); D3D12_RESOURCE_STATES InitialResourceState = D3D12_RESOURCE_STATE_COMMON; diff --git a/renderdoc/driver/d3d12/d3d12_hooks.cpp b/renderdoc/driver/d3d12/d3d12_hooks.cpp index cdbe13ffe..7306ccd46 100644 --- a/renderdoc/driver/d3d12/d3d12_hooks.cpp +++ b/renderdoc/driver/d3d12/d3d12_hooks.cpp @@ -51,6 +51,9 @@ ID3DDevice *GetD3D12DeviceIfAlloc(IUnknown *dev) if(WrappedID3D12CommandQueue::IsAlloc(dev)) return (WrappedID3D12CommandQueue *)dev; + if(WrappedID3D12Device::IsAlloc(dev)) + return (WrappedID3D12Device *)dev; + return NULL; } diff --git a/renderdoc/driver/d3d12/d3d12_stringise.cpp b/renderdoc/driver/d3d12/d3d12_stringise.cpp index 653a3c9aa..5bfd1af57 100644 --- a/renderdoc/driver/d3d12/d3d12_stringise.cpp +++ b/renderdoc/driver/d3d12/d3d12_stringise.cpp @@ -28,9 +28,7 @@ template <> rdcstr DoStringise(const D3D12Chunk &el) { - RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::Max == 1104, "Chunks changed without updating names"); - RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::List_RSSetShadingRateImage == 1103, - "New chunks must be appended otherwise it breaks old captures"); + RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::Max == 1105, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(D3D12Chunk) { @@ -192,6 +190,7 @@ rdcstr DoStringise(const D3D12Chunk &el) "ID3D12GraphicsCommandList5::RSSetShadingRate"); STRINGISE_ENUM_CLASS_NAMED(List_RSSetShadingRateImage, "ID3D12GraphicsCommandList5::RSSetShadingRateImage"); + STRINGISE_ENUM_CLASS_NAMED(Device_ExternalDXGIResource, "External DXGI Resource import"); STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk"); } END_ENUM_STRINGISE() diff --git a/renderdoc/driver/dxgi/dxgi_wrapped.cpp b/renderdoc/driver/dxgi/dxgi_wrapped.cpp index ff6cbdf84..02f622b4b 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.cpp +++ b/renderdoc/driver/dxgi/dxgi_wrapped.cpp @@ -605,6 +605,125 @@ WrappedIDXGIOutput6::~WrappedIDXGIOutput6() SAFE_RELEASE(m_Owner); } +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::FindClosestMatchingMode( + const DXGI_MODE_DESC *pModeToMatch, DXGI_MODE_DESC *pClosestMatch, IUnknown *pConcernedDevice) +{ + ID3DDevice *wrapDevice = GetD3DDevice(pConcernedDevice); + + if(wrapDevice) + return m_pReal->FindClosestMatchingMode(pModeToMatch, pClosestMatch, + wrapDevice->GetRealIUnknown()); + + if(pConcernedDevice) + RDCERR("Unrecognised device in FindClosestMatchingMode()"); + + return E_INVALIDARG; +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::TakeOwnership(IUnknown *pDevice, BOOL Exclusive) +{ + ID3DDevice *wrapDevice = GetD3DDevice(pDevice); + + if(wrapDevice) + return m_pReal->TakeOwnership(wrapDevice->GetRealIUnknown(), Exclusive); + + // since this is supposed to be an internal function, allow passing through the pointer directly + // just in case + return m_pReal->TakeOwnership(pDevice, Exclusive); +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::FindClosestMatchingMode1( + const DXGI_MODE_DESC1 *pModeToMatch, DXGI_MODE_DESC1 *pClosestMatch, IUnknown *pConcernedDevice) +{ + ID3DDevice *wrapDevice = GetD3DDevice(pConcernedDevice); + + if(wrapDevice) + return m_pReal1->FindClosestMatchingMode1(pModeToMatch, pClosestMatch, + wrapDevice->GetRealIUnknown()); + + if(pConcernedDevice) + RDCERR("Unrecognised device in FindClosestMatchingMode1()"); + + return E_INVALIDARG; +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::GetDisplaySurfaceData1(IDXGIResource *pDestination) +{ + return m_pReal1->GetDisplaySurfaceData1(UnwrapDXGIResource(pDestination)); +} + +HRESULT STDMETHODCALLTYPE +WrappedIDXGIOutput6::DuplicateOutput(IUnknown *pDevice, IDXGIOutputDuplication **ppOutputDuplication) +{ + if(!ppOutputDuplication) + return E_INVALIDARG; + + ID3DDevice *wrapDevice = GetD3DDevice(pDevice); + + if(wrapDevice) + { + IDXGIOutputDuplication *dup = NULL; + HRESULT ret = m_pReal1->DuplicateOutput(wrapDevice->GetRealIUnknown(), &dup); + + if(SUCCEEDED(ret) && dup) + dup = new WrappedIDXGIOutputDuplication(wrapDevice, dup); + + *ppOutputDuplication = dup; + + return ret; + } + + if(pDevice) + RDCERR("Unrecognised device in DuplicateOutput()"); + + return E_INVALIDARG; +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::CheckOverlaySupport(DXGI_FORMAT EnumFormat, + IUnknown *pConcernedDevice, + UINT *pFlags) +{ + ID3DDevice *wrapDevice = GetD3DDevice(pConcernedDevice); + + if(wrapDevice) + return m_pReal3->CheckOverlaySupport(EnumFormat, wrapDevice->GetRealIUnknown(), pFlags); + + if(pConcernedDevice) + RDCERR("Unrecognised device in CheckOverlaySupport()"); + + return E_INVALIDARG; +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::DuplicateOutput1( + IUnknown *pDevice, UINT Flags, UINT SupportedFormatsCount, const DXGI_FORMAT *pSupportedFormats, + IDXGIOutputDuplication **ppOutputDuplication) +{ + if(!ppOutputDuplication) + return E_INVALIDARG; + + ID3DDevice *wrapDevice = GetD3DDevice(pDevice); + + if(wrapDevice) + { + IDXGIOutputDuplication *dup = NULL; + HRESULT ret = + m_pReal5->DuplicateOutput1(wrapDevice->GetRealIUnknown(), Flags, SupportedFormatsCount, + pSupportedFormats, ppOutputDuplication); + + if(SUCCEEDED(ret) && dup) + dup = new WrappedIDXGIOutputDuplication(wrapDevice, dup); + + *ppOutputDuplication = dup; + + return ret; + } + + if(pDevice) + RDCERR("Unrecognised device in DuplicateOutput()"); + + return E_INVALIDARG; +} + HRESULT STDMETHODCALLTYPE WrappedIDXGIOutput6::QueryInterface(REFIID riid, void **ppvObject) { if(riid == __uuidof(IDXGIOutput)) @@ -1272,3 +1391,47 @@ HRESULT WrappedIDXGIFactory::CreateSwapChainForComposition(IUnknown *pDevice, return m_pReal2->CreateSwapChainForComposition(pDevice, pDesc, unwrappedOutput, ppSwapChain); } + +WrappedIDXGIOutputDuplication::WrappedIDXGIOutputDuplication(ID3DDevice *device, + IDXGIOutputDuplication *real) + : RefCountDXGIObject(real), m_Device(device), m_pReal(real) +{ +} + +WrappedIDXGIOutputDuplication::~WrappedIDXGIOutputDuplication() +{ + SAFE_RELEASE(m_pReal); +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutputDuplication::AcquireNextFrame( + UINT TimeoutInMilliseconds, DXGI_OUTDUPL_FRAME_INFO *pFrameInfo, IDXGIResource **ppDesktopResource) +{ + if(!ppDesktopResource) + return E_INVALIDARG; + + IDXGIResource *desktop = NULL; + HRESULT ret = m_pReal->AcquireNextFrame(TimeoutInMilliseconds, pFrameInfo, &desktop); + + if(SUCCEEDED(ret) && desktop) + desktop = m_Device->WrapExternalDXGIResource(desktop); + + *ppDesktopResource = desktop; + + return ret; +} + +HRESULT STDMETHODCALLTYPE WrappedIDXGIOutputDuplication::QueryInterface(REFIID riid, void **ppvObject) +{ + if(riid == __uuidof(IDXGIOutputDuplication)) + { + AddRef(); + *ppvObject = (IDXGIOutputDuplication *)this; + return S_OK; + } + else + { + WarnUnknownGUID("IDXGIOutputDuplication", riid); + } + + return RefCountDXGIObject::QueryInterface(riid, ppvObject); +} \ No newline at end of file diff --git a/renderdoc/driver/dxgi/dxgi_wrapped.h b/renderdoc/driver/dxgi/dxgi_wrapped.h index d497faf55..62371c2da 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.h +++ b/renderdoc/driver/dxgi/dxgi_wrapped.h @@ -192,6 +192,8 @@ struct ID3DDevice virtual IUnknown *WrapSwapchainBuffer(IDXGISwapper *swapper, DXGI_FORMAT bufferFormat, UINT buffer, IUnknown *realSurface) = 0; + virtual IDXGIResource *WrapExternalDXGIResource(IDXGIResource *res) = 0; + virtual HRESULT Present(IDXGISwapper *swapper, UINT SyncInterval, UINT Flags) = 0; }; @@ -903,6 +905,93 @@ public: } }; +class WrappedIDXGIOutputDuplication : public IDXGIOutputDuplication, public RefCountDXGIObject +{ + ID3DDevice *m_Device; + IDXGIOutputDuplication *m_pReal; + +public: + IMPLEMENT_IDXGIOBJECT_WITH_REFCOUNTDXGIOBJECT_CUSTOMQUERY; + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + + WrappedIDXGIOutputDuplication(ID3DDevice *device, IDXGIOutputDuplication *real); + ~WrappedIDXGIOutputDuplication(); + + IDXGIOutputDuplication *GetReal() { return m_pReal; } + ////////////////////////////// + // implement IDXGIOutputDuplication + + virtual void STDMETHODCALLTYPE GetDesc( + /* [annotation][out] */ + _Out_ DXGI_OUTDUPL_DESC *pDesc) + { + return m_pReal->GetDesc(pDesc); + } + + virtual HRESULT STDMETHODCALLTYPE AcquireNextFrame( + /* [annotation][in] */ + _In_ UINT TimeoutInMilliseconds, + /* [annotation][out] */ + _Out_ DXGI_OUTDUPL_FRAME_INFO *pFrameInfo, + /* [annotation][out] */ + _COM_Outptr_ IDXGIResource **ppDesktopResource); + + virtual HRESULT STDMETHODCALLTYPE GetFrameDirtyRects( + /* [annotation][in] */ + _In_ UINT DirtyRectsBufferSize, + /* [annotation][out] */ + _Out_writes_bytes_to_(DirtyRectsBufferSize, *pDirtyRectsBufferSizeRequired) + RECT *pDirtyRectsBuffer, + /* [annotation][out] */ + _Out_ UINT *pDirtyRectsBufferSizeRequired) + { + return m_pReal->GetFrameDirtyRects(DirtyRectsBufferSize, pDirtyRectsBuffer, + pDirtyRectsBufferSizeRequired); + } + + virtual HRESULT STDMETHODCALLTYPE GetFrameMoveRects( + /* [annotation][in] */ + _In_ UINT MoveRectsBufferSize, + /* [annotation][out] */ + _Out_writes_bytes_to_(MoveRectsBufferSize, *pMoveRectsBufferSizeRequired) + DXGI_OUTDUPL_MOVE_RECT *pMoveRectBuffer, + /* [annotation][out] */ + _Out_ UINT *pMoveRectsBufferSizeRequired) + { + return m_pReal->GetFrameMoveRects(MoveRectsBufferSize, pMoveRectBuffer, + pMoveRectsBufferSizeRequired); + } + + virtual HRESULT STDMETHODCALLTYPE GetFramePointerShape( + /* [annotation][in] */ + _In_ UINT PointerShapeBufferSize, + /* [annotation][out] */ + _Out_writes_bytes_to_(PointerShapeBufferSize, + *pPointerShapeBufferSizeRequired) void *pPointerShapeBuffer, + /* [annotation][out] */ + _Out_ UINT *pPointerShapeBufferSizeRequired, + /* [annotation][out] */ + _Out_ DXGI_OUTDUPL_POINTER_SHAPE_INFO *pPointerShapeInfo) + { + return m_pReal->GetFramePointerShape(PointerShapeBufferSize, pPointerShapeBuffer, + pPointerShapeBufferSizeRequired, pPointerShapeInfo); + } + + virtual HRESULT STDMETHODCALLTYPE MapDesktopSurface( + /* [annotation][out] */ + _Out_ DXGI_MAPPED_RECT *pLockedRect) + { + return m_pReal->MapDesktopSurface(pLockedRect); + } + + virtual HRESULT STDMETHODCALLTYPE UnMapDesktopSurface(void) + { + return m_pReal->UnMapDesktopSurface(); + } + + virtual HRESULT STDMETHODCALLTYPE ReleaseFrame(void) { return m_pReal->ReleaseFrame(); } +}; + class WrappedIDXGIOutput6 : public IDXGIOutput6, public RefCountDXGIObject { RefCountDXGIObject *m_Owner; @@ -949,18 +1038,12 @@ public: /* [annotation][out] */ _Out_ DXGI_MODE_DESC *pClosestMatch, /* [annotation][in] */ - _In_opt_ IUnknown *pConcernedDevice) - { - return m_pReal->FindClosestMatchingMode(pModeToMatch, pClosestMatch, pConcernedDevice); - } + _In_opt_ IUnknown *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); - } + _In_ IUnknown *pDevice, BOOL Exclusive); virtual void STDMETHODCALLTYPE ReleaseOwnership(void) { return m_pReal->ReleaseOwnership(); } virtual HRESULT STDMETHODCALLTYPE GetGammaControlCapabilities( @@ -1025,26 +1108,17 @@ public: /* [annotation][out] */ _Out_ DXGI_MODE_DESC1 *pClosestMatch, /* [annotation][in] */ - _In_opt_ IUnknown *pConcernedDevice) - { - return m_pReal1->FindClosestMatchingMode1(pModeToMatch, pClosestMatch, pConcernedDevice); - } + _In_opt_ IUnknown *pConcernedDevice); virtual HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData1( /* [annotation][in] */ - _In_ IDXGIResource *pDestination) - { - return m_pReal1->GetDisplaySurfaceData1(pDestination); - } + _In_ IDXGIResource *pDestination); virtual HRESULT STDMETHODCALLTYPE DuplicateOutput( /* [annotation][in] */ _In_ IUnknown *pDevice, /* [annotation][out] */ - _COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication) - { - return m_pReal1->DuplicateOutput(pDevice, ppOutputDuplication); - } + _COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication); ////////////////////////////// // implement IDXGIOutput2 @@ -1059,10 +1133,7 @@ public: /* [annotation][out] */ _In_ IUnknown *pConcernedDevice, /* [annotation][out] */ - _Out_ UINT *pFlags) - { - return m_pReal3->CheckOverlaySupport(EnumFormat, pConcernedDevice, pFlags); - } + _Out_ UINT *pFlags); ////////////////////////////// // implement IDXGIOutput4 @@ -1092,11 +1163,7 @@ public: /* [annotation][in] */ _In_reads_(SupportedFormatsCount) const DXGI_FORMAT *pSupportedFormats, /* [annotation][out] */ - _COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication) - { - return m_pReal5->DuplicateOutput1(pDevice, Flags, SupportedFormatsCount, pSupportedFormats, - ppOutputDuplication); - } + _COM_Outptr_ IDXGIOutputDuplication **ppOutputDuplication); ////////////////////////////// // implement IDXGIOutput6