diff --git a/renderdoc/driver/d3d12/d3d12_commands.cpp b/renderdoc/driver/d3d12/d3d12_commands.cpp index 23622d47f..7a4ecc857 100644 --- a/renderdoc/driver/d3d12/d3d12_commands.cpp +++ b/renderdoc/driver/d3d12/d3d12_commands.cpp @@ -757,6 +757,8 @@ bool WrappedID3D12CommandQueue::ProcessChunk(ReadSerialiser &ser, D3D12Chunk chu case D3D12Chunk::Device_CreateCommittedResource1: case D3D12Chunk::Device_CreateHeap1: case D3D12Chunk::Device_ExternalDXGIResource: + case D3D12Chunk::CompatDevice_CreateSharedResource: + case D3D12Chunk::CompatDevice_CreateSharedHeap: RDCERR("Unexpected chunk while processing frame: %s", ToStr(chunk).c_str()); return false; diff --git a/renderdoc/driver/d3d12/d3d12_common.h b/renderdoc/driver/d3d12/d3d12_common.h index ae7743912..001b2a03e 100644 --- a/renderdoc/driver/d3d12/d3d12_common.h +++ b/renderdoc/driver/d3d12/d3d12_common.h @@ -854,5 +854,7 @@ enum class D3D12Chunk : uint32_t Device_ExternalDXGIResource, Swapchain_Present, List_ClearState, + CompatDevice_CreateSharedResource, + CompatDevice_CreateSharedHeap, Max, }; diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index bc4dcc070..5890047b1 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -195,6 +195,89 @@ ULONG STDMETHODCALLTYPE WrappedDREDSettings::Release() return m_pDevice.Release(); } +HRESULT STDMETHODCALLTYPE WrappedCompatibilityDevice::QueryInterface(REFIID riid, void **ppvObject) +{ + return m_pDevice.QueryInterface(riid, ppvObject); +} + +ULONG STDMETHODCALLTYPE WrappedCompatibilityDevice::AddRef() +{ + return m_pDevice.AddRef(); +} + +ULONG STDMETHODCALLTYPE WrappedCompatibilityDevice::Release() +{ + return m_pDevice.Release(); +} + +WriteSerialiser &WrappedCompatibilityDevice::GetThreadSerialiser() +{ + return m_pDevice.GetThreadSerialiser(); +} + +HRESULT STDMETHODCALLTYPE WrappedCompatibilityDevice::CreateSharedResource( + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ const D3D11_RESOURCE_FLAGS *pFlags11, + D3D12_COMPATIBILITY_SHARED_FLAGS CompatibilityFlags, + _In_opt_ ID3D12LifetimeTracker *pLifetimeTracker, + _In_opt_ ID3D12SwapChainAssistant *pOwningSwapchain, REFIID riid, + _COM_Outptr_opt_ void **ppResource) +{ + if(ppResource == NULL) + return E_INVALIDARG; + + HRESULT hr; + + // not exactly sure what to do with these... + RDCASSERT(pLifetimeTracker == NULL); + RDCASSERT(pOwningSwapchain == NULL); + + SERIALISE_TIME_CALL( + hr = m_pReal->CreateSharedResource(pHeapProperties, HeapFlags, pDesc, InitialResourceState, + pOptimizedClearValue, pFlags11, CompatibilityFlags, + pLifetimeTracker, pOwningSwapchain, riid, ppResource)); + + if(FAILED(hr)) + { + IUnknown *unk = (IUnknown *)*ppResource; + SAFE_RELEASE(unk); + return hr; + } + + return m_pDevice.OpenSharedHandleInternal(D3D12Chunk::CompatDevice_CreateSharedResource, riid, + ppResource); +} + +HRESULT STDMETHODCALLTYPE WrappedCompatibilityDevice::CreateSharedHeap( + _In_ const D3D12_HEAP_DESC *pHeapDesc, D3D12_COMPATIBILITY_SHARED_FLAGS CompatibilityFlags, + REFIID riid, _COM_Outptr_opt_ void **ppHeap) +{ + if(ppHeap == NULL) + return E_INVALIDARG; + + HRESULT hr; + + SERIALISE_TIME_CALL(hr = m_pReal->CreateSharedHeap(pHeapDesc, CompatibilityFlags, riid, ppHeap)); + + if(FAILED(hr)) + { + IUnknown *unk = (IUnknown *)*ppHeap; + SAFE_RELEASE(unk); + return hr; + } + + return m_pDevice.OpenSharedHandleInternal(D3D12Chunk::CompatDevice_CreateSharedHeap, riid, ppHeap); +} + +HRESULT STDMETHODCALLTYPE WrappedCompatibilityDevice::ReflectSharedProperties( + _In_ ID3D12Object *pHeapOrResource, D3D12_REFLECT_SHARED_PROPERTY ReflectType, + _Out_writes_bytes_(DataSize) void *pData, UINT DataSize) +{ + return m_pReal->ReflectSharedProperties(Unwrap(pHeapOrResource), ReflectType, pData, DataSize); +} + WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitParams params, bool enabledDebugLayer) : m_RefCounter(realDevice, false), @@ -203,7 +286,8 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara m_debugLayerEnabled(enabledDebugLayer), m_WrappedDownlevel(*this), m_DRED(*this), - m_DREDSettings(*this) + m_DREDSettings(*this), + m_CompatDevice(*this) { if(RenderDoc::Inst().GetCrashHandler()) RenderDoc::Inst().GetCrashHandler()->RegisterMemoryRegion(this, sizeof(WrappedID3D12Device)); @@ -238,6 +322,7 @@ WrappedID3D12Device::WrappedID3D12Device(ID3D12Device *realDevice, D3D12InitPara m_pDevice->QueryInterface(__uuidof(ID3D12DeviceRemovedExtendedDataSettings), (void **)&m_DREDSettings.m_pReal); m_pDevice->QueryInterface(__uuidof(ID3D12DeviceDownlevel), (void **)&m_pDownlevel); + m_pDevice->QueryInterface(__uuidof(ID3D12CompatibilityDevice), (void **)&m_CompatDevice.m_pReal); for(size_t i = 0; i < ARRAY_COUNT(m_DescriptorIncrements); i++) m_DescriptorIncrements[i] = @@ -513,6 +598,7 @@ WrappedID3D12Device::~WrappedID3D12Device() SAFE_RELEASE(m_DRED.m_pReal); SAFE_RELEASE(m_DREDSettings.m_pReal); + SAFE_RELEASE(m_CompatDevice.m_pReal); SAFE_RELEASE(m_pDownlevel); SAFE_RELEASE(m_pDevice6); SAFE_RELEASE(m_pDevice5); @@ -564,19 +650,13 @@ WrappedID3D12Device *WrappedID3D12Device::Create(ID3D12Device *realDevice, D3D12 HRESULT WrappedID3D12Device::QueryInterface(REFIID riid, void **ppvObject) { - // DEFINE_GUID(IID_IDirect3DDevice9, 0xd0223b96, 0xbf7a, 0x43fd, 0x92, 0xbd, 0xa4, 0x3b, 0xd, - // 0x82, 0xb9, 0xeb); - static const GUID IDirect3DDevice9_uuid = { - 0xd0223b96, 0xbf7a, 0x43fd, {0x92, 0xbd, 0xa4, 0x3b, 0xd, 0x82, 0xb9, 0xeb}}; - - // ID3D10Device UUID {9B7E4C0F-342C-4106-A19F-4F2704F689F0} - static const GUID ID3D10Device_uuid = { - 0x9b7e4c0f, 0x342c, 0x4106, {0xa1, 0x9f, 0x4f, 0x27, 0x04, 0xf6, 0x89, 0xf0}}; - // RenderDoc UUID {A7AA6116-9C8D-4BBA-9083-B4D816B71B78} static const GUID IRenderDoc_uuid = { 0xa7aa6116, 0x9c8d, 0x4bba, {0x90, 0x83, 0xb4, 0xd8, 0x16, 0xb7, 0x1b, 0x78}}; + static const GUID ID3D12CompatibilityDevice_uuid = { + 0x8f1c0e3c, 0xfae3, 0x4a82, {0xb0, 0x98, 0xbf, 0xe1, 0x70, 0x82, 0x07, 0xff}}; + HRESULT hr = S_OK; if(riid == __uuidof(IUnknown)) @@ -856,6 +936,19 @@ HRESULT WrappedID3D12Device::QueryInterface(REFIID riid, void **ppvObject) *ppvObject = (IUnknown *)this; return S_OK; } + else if(riid == __uuidof(ID3D12CompatibilityDevice)) + { + if(m_CompatDevice.m_pReal) + { + AddRef(); + *ppvObject = (ID3D12CompatibilityDevice *)&m_CompatDevice; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } else { WarnUnknownGUID("ID3D12Device", riid); @@ -3006,6 +3099,9 @@ bool WrappedID3D12Device::ProcessChunk(ReadSerialiser &ser, D3D12Chunk context) case D3D12Chunk::Device_CreateHeap1: return Serialise_CreateHeap1(ser, NULL, NULL, IID(), NULL); case D3D12Chunk::Device_ExternalDXGIResource: return Serialise_OpenSharedHandle(ser, NULL, IID(), NULL); + case D3D12Chunk::CompatDevice_CreateSharedResource: + case D3D12Chunk::CompatDevice_CreateSharedHeap: + return Serialise_OpenSharedHandle(ser, NULL, IID(), NULL); // in order to get a warning if we miss a case, we explicitly handle the list/queue chunks here. // If we actually encounter one it's an error (we should hit CaptureBegin first and switch to diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index 1cd78ba8c..958009143 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -340,6 +340,89 @@ struct WrappedDREDSettings : public ID3D12DeviceRemovedExtendedDataSettings } }; +// these aren't documented, they're defined in D3D12TranslationLayer in the d3d11on12 codebase +typedef enum D3D12_COMPATIBILITY_SHARED_FLAGS { + D3D12_COMPATIBILITY_SHARED_FLAG_NONE = 0, + D3D12_COMPATIBILITY_SHARED_FLAG_NON_NT_HANDLE = 0x1, + D3D12_COMPATIBILITY_SHARED_FLAG_KEYED_MUTEX = 0x2, + D3D12_COMPATIBILITY_SHARED_FLAG_9_ON_12 = 0x4 +} D3D12_COMPATIBILITY_SHARED_FLAGS; + +typedef enum D3D12_REFLECT_SHARED_PROPERTY { + D3D12_REFLECT_SHARED_PROPERTY_D3D11_RESOURCE_FLAGS = 0, + D3D12_REFELCT_SHARED_PROPERTY_COMPATIBILITY_SHARED_FLAGS = + (D3D12_REFLECT_SHARED_PROPERTY_D3D11_RESOURCE_FLAGS + 1), + D3D12_REFLECT_SHARED_PROPERTY_NON_NT_SHARED_HANDLE = + (D3D12_REFELCT_SHARED_PROPERTY_COMPATIBILITY_SHARED_FLAGS + 1) +} D3D12_REFLECT_SHARED_PROPERTY; + +typedef struct D3D11_RESOURCE_FLAGS +{ + UINT BindFlags; + UINT MiscFlags; + UINT CPUAccessFlags; + UINT StructureByteStride; +} D3D11_RESOURCE_FLAGS; + +MIDL_INTERFACE("8f1c0e3c-fae3-4a82-b098-bfe1708207ff") +ID3D12CompatibilityDevice : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE CreateSharedResource( + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ const D3D11_RESOURCE_FLAGS *pFlags11, + D3D12_COMPATIBILITY_SHARED_FLAGS CompatibilityFlags, + _In_opt_ ID3D12LifetimeTracker *pLifetimeTracker, + _In_opt_ ID3D12SwapChainAssistant *pOwningSwapchain, REFIID riid, + _COM_Outptr_opt_ void **ppResource) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateSharedHeap( + _In_ const D3D12_HEAP_DESC *pHeapDesc, D3D12_COMPATIBILITY_SHARED_FLAGS CompatibilityFlags, + REFIID riid, _COM_Outptr_opt_ void **ppHeap) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReflectSharedProperties( + _In_ ID3D12Object * pHeapOrResource, D3D12_REFLECT_SHARED_PROPERTY ReflectType, + _Out_writes_bytes_(DataSize) void *pData, UINT DataSize) = 0; +}; + +struct WrappedCompatibilityDevice : public ID3D12CompatibilityDevice +{ + WrappedID3D12Device &m_pDevice; + ID3D12CompatibilityDevice *m_pReal = NULL; + + WrappedCompatibilityDevice(WrappedID3D12Device &dev) : m_pDevice(dev) {} + ////////////////////////////// + // implement IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + WriteSerialiser &GetThreadSerialiser(); + + ////////////////////////////// + // implement ID3D12CompatibilityDevice + virtual HRESULT STDMETHODCALLTYPE CreateSharedResource( + _In_ const D3D12_HEAP_PROPERTIES *pHeapProperties, D3D12_HEAP_FLAGS HeapFlags, + _In_ const D3D12_RESOURCE_DESC *pDesc, D3D12_RESOURCE_STATES InitialResourceState, + _In_opt_ const D3D12_CLEAR_VALUE *pOptimizedClearValue, + _In_opt_ const D3D11_RESOURCE_FLAGS *pFlags11, + D3D12_COMPATIBILITY_SHARED_FLAGS CompatibilityFlags, + _In_opt_ ID3D12LifetimeTracker *pLifetimeTracker, + _In_opt_ ID3D12SwapChainAssistant *pOwningSwapchain, REFIID riid, + _COM_Outptr_opt_ void **ppResource); + + virtual HRESULT STDMETHODCALLTYPE CreateSharedHeap(_In_ const D3D12_HEAP_DESC *pHeapDesc, + D3D12_COMPATIBILITY_SHARED_FLAGS CompatibilityFlags, + REFIID riid, _COM_Outptr_opt_ void **ppHeap); + + virtual HRESULT STDMETHODCALLTYPE ReflectSharedProperties(_In_ ID3D12Object *pHeapOrResource, + D3D12_REFLECT_SHARED_PROPERTY ReflectType, + _Out_writes_bytes_(DataSize) void *pData, + UINT DataSize); +}; + class WrappedID3D12CommandQueue; #define IMPLEMENT_FUNCTION_THREAD_SERIALISED(ret, func, ...) \ @@ -383,6 +466,7 @@ private: WrappedDownlevelDevice m_WrappedDownlevel; WrappedDRED m_DRED; WrappedDREDSettings m_DREDSettings; + WrappedCompatibilityDevice m_CompatDevice; rdcarray m_CommandAllocators; diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index 7f338b0b8..de6926aab 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -2316,6 +2316,10 @@ bool WrappedID3D12Device::Serialise_OpenSharedHandle(SerialiserType &ser, HANDLE // always allow SRVs on replay so we can inspect resources desc.Flags &= ~D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; + // the runtime doesn't like us telling it what DENY heap flags will be set, remove them + heapFlags &= ~(D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES | + D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES); + HRESULT hr; ID3D12Resource *ret; hr = m_pDevice->CreateCommittedResource(&heapProperties, heapFlags, &desc, @@ -2454,15 +2458,40 @@ HRESULT WrappedID3D12Device::OpenSharedHandleInternal(D3D12Chunk chunkType, REFI bool isFence = riid == __uuidof(ID3D12Fence) || riid == __uuidof(ID3D12Fence1); bool isHeap = riid == __uuidof(ID3D12Heap) || riid == __uuidof(ID3D12Heap1); bool isDeviceChild = riid == __uuidof(ID3D12DeviceChild); + bool isIUnknown = riid == __uuidof(IUnknown); IID riid_internal = riid; void *ret = *ppvObj; + if(isIUnknown) + { + // same as device child but we're even more in the dark. Hope against hope it's a + // ID3D12DeviceChild + IUnknown *real = (IUnknown *)ret; + + ID3D12DeviceChild *d3d12child = NULL; + isDeviceChild = + SUCCEEDED(real->QueryInterface(__uuidof(ID3D12DeviceChild), (void **)&d3d12child)) && + d3d12child; + SAFE_RELEASE(real); + + if(isDeviceChild) + { + riid_internal = __uuidof(ID3D12DeviceChild); + ret = (void *)d3d12child; + } + else + { + SAFE_RELEASE(d3d12child); + return E_NOINTERFACE; + } + } + if(isDeviceChild) { // In this case we need to find out what the actual underlying type is // Should be one of ID3D12Heap, ID3D12Resource, ID3D12Fence - ID3D12DeviceChild *real = (ID3D12DeviceChild *)(*ppvObj); + ID3D12DeviceChild *real = (ID3D12DeviceChild *)ret; ID3D12Resource *d3d12Res = NULL; ID3D12Fence *d3d12Fence = NULL; @@ -2540,10 +2569,6 @@ HRESULT WrappedID3D12Device::OpenSharedHandleInternal(D3D12Chunk chunkType, REFI wrappedDeviceChild = wrapped; - *ppvObj = (ID3D12Fence *)wrapped; - if(riid_internal == __uuidof(ID3D12Fence1)) - *ppvObj = (ID3D12Fence1 *)wrapped; - record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID()); record->type = Resource_Fence; record->Length = 0; @@ -2559,18 +2584,6 @@ HRESULT WrappedID3D12Device::OpenSharedHandleInternal(D3D12Chunk chunkType, REFI wrappedDeviceChild = wrapped; - if(isDXGIRes) - { - wrapped->QueryInterface(riid_internal, ppvObj); - wrapped->Release(); - } - else - { - *ppvObj = (ID3D12Resource *)wrapped; - if(riid_internal == __uuidof(ID3D12Resource1)) - *ppvObj = (ID3D12Resource1 *)wrapped; - } - D3D12_RESOURCE_DESC desc = wrapped->GetDesc(); D3D12_RESOURCE_STATES InitialResourceState = D3D12_RESOURCE_STATE_COMMON; @@ -2613,14 +2626,16 @@ HRESULT WrappedID3D12Device::OpenSharedHandleInternal(D3D12Chunk chunkType, REFI wrappedDeviceChild = wrapped; - *ppvObj = wrappedDeviceChild; - record = GetResourceManager()->AddResourceRecord(wrapped->GetResourceID()); record->type = Resource_Heap; record->Length = 0; wrapped->SetResourceRecord(record); } + // use queryinterface to get the right interface into ppvObj, then release the reference + wrappedDeviceChild->QueryInterface(riid, ppvObj); + wrappedDeviceChild->Release(); + CACHE_THREAD_SERIALISER(); SCOPED_SERIALISE_CHUNK(chunkType); diff --git a/renderdoc/driver/d3d12/d3d12_stringise.cpp b/renderdoc/driver/d3d12/d3d12_stringise.cpp index 0bba7c716..71f7d8fe6 100644 --- a/renderdoc/driver/d3d12/d3d12_stringise.cpp +++ b/renderdoc/driver/d3d12/d3d12_stringise.cpp @@ -28,7 +28,7 @@ template <> rdcstr DoStringise(const D3D12Chunk &el) { - RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::Max == 1107, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)D3D12Chunk::Max == 1109, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(D3D12Chunk) { @@ -193,6 +193,10 @@ rdcstr DoStringise(const D3D12Chunk &el) STRINGISE_ENUM_CLASS_NAMED(Device_ExternalDXGIResource, "External DXGI Resource import"); STRINGISE_ENUM_CLASS_NAMED(Swapchain_Present, "IDXGISwapChain::Present"); STRINGISE_ENUM_CLASS_NAMED(List_ClearState, "ID3D12GraphicsCommandList::ClearState"); + STRINGISE_ENUM_CLASS_NAMED(CompatDevice_CreateSharedResource, + "ID3D12CompatibilityDevice::CreateSharedResource"); + STRINGISE_ENUM_CLASS_NAMED(CompatDevice_CreateSharedHeap, + "ID3D12CompatibilityDevice::CreateSharedHeap"); 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 eeb686039..b81bc42cf 100644 --- a/renderdoc/driver/dxgi/dxgi_wrapped.cpp +++ b/renderdoc/driver/dxgi/dxgi_wrapped.cpp @@ -66,6 +66,11 @@ bool RefCountDXGIObject::HandleWrap(REFIID riid, void **ppvObject) static const GUID ID3D10Texture2D_uuid = { 0x9b7e4c04, 0x342c, 0x4106, {0xa1, 0x9f, 0x4f, 0x27, 0x04, 0xf6, 0x89, 0xf0}}; + // unknown/undocumented internal interface + // {7abb6563-02bc-47c4-8ef9-acc4795edbcf} + static const GUID IDXGIAdapterInternal2_uuid = { + 0x7abb6563, 0x02bc, 0x47c4, {0x8e, 0xf9, 0xac, 0xc4, 0x79, 0x5e, 0xdb, 0xcf}}; + if(riid == __uuidof(IDXGIDevice)) { // should have been handled elsewhere, so we can properly create this device @@ -172,6 +177,18 @@ bool RefCountDXGIObject::HandleWrap(REFIID riid, void **ppvObject) } return false; } + else if(riid == IDXGIAdapterInternal2_uuid) + { + static bool printed = false; + if(!printed) + { + printed = true; + RDCWARN( + "Querying IDXGIObject for unsupported/undocumented IDXGIAdapterInternal2 interface: %s", + ToStr(riid).c_str()); + } + return false; + } else if(riid == Unknown_uuid) { static bool printed = false;