From 3ac5b9a84276a796af8a89cc8c587bd3056e5f64 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 28 Jan 2021 12:29:16 +0000 Subject: [PATCH] Allow any UUID in DXGI swapchain GetBuffer() * The only requirements are that we can get the interface as the one we want (ID3D11Texture or ID3D12Resource) so we query it straight away as that first. Then we also need to be able to convert from that to whatever the user requested, so we do that as a second step. * Because this is all undocumented it's unknown if there's any combination of UUIDs that would fail this but might make sense in a different order (e.g. queried as the user's UUID first and then we fetch our interface off that). --- renderdoc/driver/dxgi/dxgi_wrapped.cpp | 94 +++++++++----------------- 1 file changed, 31 insertions(+), 63 deletions(-) diff --git a/renderdoc/driver/dxgi/dxgi_wrapped.cpp b/renderdoc/driver/dxgi/dxgi_wrapped.cpp index 61e83c3ef..865226501 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.cpp +++ b/renderdoc/driver/dxgi/dxgi_wrapped.cpp @@ -462,81 +462,49 @@ HRESULT WrappedIDXGISwapChain4::GetBuffer( static const GUID ID3D10Resource_uuid = { 0x9b7e4c01, 0x342c, 0x4106, {0xa1, 0x9f, 0x4f, 0x27, 0x04, 0xf6, 0x89, 0xf0}}; - IID uuid = riid; - - if(uuid == ID3D10Texture2D_uuid || uuid == ID3D10Resource_uuid) + if(riid == ID3D10Texture2D_uuid || riid == ID3D10Resource_uuid) { RDCERR("Querying swapchain buffers via D3D10 interface UUIDs is not supported"); return E_NOINTERFACE; } - else if(uuid == __uuidof(IDXGISurface) || uuid == __uuidof(IDXGIObject) || - uuid == __uuidof(IUnknown)) - { - RDCWARN("Querying swapchain buffer for ambiguous UUID."); - // query as native format so that wrapping works as expected - uuid = m_pDevice->GetBackbufferUUID(); - } - else if(uuid != __uuidof(ID3D11Texture2D) && uuid != __uuidof(ID3D11Texture2D1) && - uuid != __uuidof(ID3D11Resource) && uuid != __uuidof(ID3D12Resource) && - uuid != __uuidof(ID3D12Resource1)) + IUnknown *unwrappedBackbuffer = NULL; + + // query as the device's native backbuffer format + HRESULT ret = + m_pReal->GetBuffer(Buffer, m_pDevice->GetBackbufferUUID(), (void **)&unwrappedBackbuffer); + + // if this fails we can't continue, the wrapping below assumes it's a native resource + if(FAILED(ret)) { - RDCERR("Unsupported or unrecognised UUID passed to IDXGISwapChain::GetBuffer - %s", - ToStr(uuid).c_str()); - return E_NOINTERFACE; + RDCERR("Failed to get swapchain backbuffer %d as %s: HRESULT: %s", Buffer, + ToStr(m_pDevice->GetBackbufferUUID()).c_str(), ToStr(ret).c_str()); + SAFE_RELEASE(unwrappedBackbuffer); + return ret; } - HRESULT ret = m_pReal->GetBuffer(Buffer, uuid, ppSurface); + DXGI_SWAP_CHAIN_DESC desc; + GetDesc(&desc); + // this wraps and takes the reference, so unwrappedBackbuffer no longer holds a reference + IUnknown *wrappedBackbuffer = + m_pDevice->WrapSwapchainBuffer(this, desc.BufferDesc.Format, Buffer, unwrappedBackbuffer); + unwrappedBackbuffer = NULL; + + // now query the original UUID the user wanted + ret = wrappedBackbuffer->QueryInterface(riid, ppSurface); + + if(FAILED(ret) || *ppSurface == NULL) { - IUnknown *realSurface = (IUnknown *)*ppSurface; - IUnknown *tex = realSurface; - - if(FAILED(ret)) - { - RDCERR("Failed to get swapchain backbuffer %d: HRESULT: %s", Buffer, ToStr(ret).c_str()); - SAFE_RELEASE(realSurface); - tex = NULL; - } - else - { - DXGI_SWAP_CHAIN_DESC desc; - GetDesc(&desc); - tex = m_pDevice->WrapSwapchainBuffer(this, desc.BufferDesc.Format, Buffer, realSurface); - } - - // if the original UUID was IDXGISurface, fixup for the expected interface being returned - if(tex && riid == __uuidof(IDXGISurface)) - { - IDXGISurface *surf = NULL; - HRESULT hr = tex->QueryInterface(__uuidof(IDXGISurface), (void **)&surf); - RDCASSERTEQUAL(hr, S_OK); - - tex->Release(); - tex = surf; - } - else if(tex && riid == __uuidof(IDXGIObject)) - { - IDXGIObject *obj = NULL; - HRESULT hr = tex->QueryInterface(__uuidof(IDXGIObject), (void **)&obj); - RDCASSERTEQUAL(hr, S_OK); - - tex->Release(); - tex = obj; - } - else if(tex && riid == __uuidof(IUnknown)) - { - IUnknown *obj = NULL; - HRESULT hr = tex->QueryInterface(__uuidof(IUnknown), (void **)&obj); - RDCASSERTEQUAL(hr, S_OK); - - tex->Release(); - tex = obj; - } - - *ppSurface = tex; + RDCERR("Couldn't convert wrapped swapchain backbuffer %d to %s: HRESULT: %s", Buffer, + ToStr(riid).c_str(), ToStr(ret).c_str()); + SAFE_RELEASE(wrappedBackbuffer); + return ret; } + // now the reference is in ppSurface + SAFE_RELEASE(wrappedBackbuffer); + return ret; }