From 086e661798da710225f06abc76c0147fa9e7add5 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Thu, 22 Jun 2017 23:55:24 +0800 Subject: [PATCH] Wrap D3D8 vertex and index buffers --- renderdoc/driver/d3d8/d3d8_common.h | 4 + renderdoc/driver/d3d8/d3d8_device.cpp | 132 ++++++- renderdoc/driver/d3d8/d3d8_device.h | 13 + renderdoc/driver/d3d8/d3d8_manager.cpp | 77 ++++ renderdoc/driver/d3d8/d3d8_manager.h | 73 ++++ renderdoc/driver/d3d8/d3d8_resources.cpp | 121 +++++++ renderdoc/driver/d3d8/d3d8_resources.h | 332 ++++++++++++++++++ renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj | 4 + .../d3d8/renderdoc_d3d8.vcxproj.filters | 15 + renderdoc/driver/dx/official/d3d8.h | 24 +- 10 files changed, 777 insertions(+), 18 deletions(-) create mode 100644 renderdoc/driver/d3d8/d3d8_manager.cpp create mode 100644 renderdoc/driver/d3d8/d3d8_manager.h create mode 100644 renderdoc/driver/d3d8/d3d8_resources.cpp create mode 100644 renderdoc/driver/d3d8/d3d8_resources.h diff --git a/renderdoc/driver/d3d8/d3d8_common.h b/renderdoc/driver/d3d8/d3d8_common.h index 377481c9d..07f559ecc 100644 --- a/renderdoc/driver/d3d8/d3d8_common.h +++ b/renderdoc/driver/d3d8/d3d8_common.h @@ -77,3 +77,7 @@ public: unsigned int SoftRef(WrappedD3DDevice8 *device); unsigned int SoftRelease(WrappedD3DDevice8 *device); }; + +#define IMPLEMENT_FUNCTION_SERIALISED(ret, func) \ + ret func; \ + bool CONCAT(Serialise_, func); \ No newline at end of file diff --git a/renderdoc/driver/d3d8/d3d8_device.cpp b/renderdoc/driver/d3d8/d3d8_device.cpp index d0a7a0fe7..a6ef9d124 100644 --- a/renderdoc/driver/d3d8/d3d8_device.cpp +++ b/renderdoc/driver/d3d8/d3d8_device.cpp @@ -26,6 +26,7 @@ #include "core/core.h" #include "serialise/serialiser.h" #include "d3d8_debug.h" +#include "d3d8_resources.h" WrappedD3DDevice8::WrappedD3DDevice8(IDirect3DDevice8 *device, HWND wnd, D3DPRESENT_PARAMETERS *pPresentationParameters) @@ -43,8 +44,17 @@ WrappedD3DDevice8::WrappedD3DDevice8(IDirect3DDevice8 *device, HWND wnd, m_InternalRefcount = 0; m_Alive = true; +#if ENABLED(RDOC_RELEASE) + const bool debugSerialiser = false; +#else + const bool debugSerialiser = true; +#endif + if(!RenderDoc::Inst().IsReplayApp()) { + m_State = READING; + m_pSerialiser = NULL; + RenderDoc::Inst().AddDeviceFrameCapturer((IDirect3DDevice8 *)this, this); m_Wnd = wnd; @@ -52,6 +62,15 @@ WrappedD3DDevice8::WrappedD3DDevice8(IDirect3DDevice8 *device, HWND wnd, if(wnd != NULL) RenderDoc::Inst().AddFrameCapturer((IDirect3DDevice8 *)this, wnd, this); } + else + { + m_State = WRITING_IDLE; + m_pSerialiser = new Serialiser(NULL, Serialiser::WRITING, debugSerialiser); + + m_pSerialiser->SetDebugText(true); + } + + m_ResourceManager = new D3D8ResourceManager(m_State, m_pSerialiser, this); } void WrappedD3DDevice8::CheckForDeath() @@ -80,7 +99,40 @@ WrappedD3DDevice8::~WrappedD3DDevice8() SAFE_DELETE(m_DebugManager); + m_ResourceManager->Shutdown(); + + SAFE_DELETE(m_ResourceManager); + SAFE_RELEASE(m_device); + + SAFE_DELETE(m_pSerialiser); + + RDCASSERT(WrappedIDirect3DVertexBuffer8::m_BufferList.empty()); + RDCASSERT(WrappedIDirect3DIndexBuffer8::m_BufferList.empty()); +} + +bool WrappedD3DDevice8::Serialise_ReleaseResource(IDirect3DResource8 *res) +{ + return true; +} + +void WrappedD3DDevice8::ReleaseResource(IDirect3DResource8 *res) +{ + ResourceId id = GetResID((IUnknown *)res); + + D3D8ResourceRecord *record = GetResourceManager()->GetResourceRecord(id); + + if(record) + record->Delete(GetResourceManager()); + + // wrapped resources get released all the time, we don't want to + // try and slerp in a resource release. Just the explicit ones + if(m_State < WRITING) + { + if(GetResourceManager()->HasLiveResource(id)) + GetResourceManager()->EraseLiveResource(id); + return; + } } HRESULT WrappedD3DDevice8::QueryInterface(REFIID riid, void **ppvObject) @@ -295,14 +347,62 @@ HRESULT __stdcall WrappedD3DDevice8::CreateVertexBuffer(UINT Length, DWORD Usage D3DPOOL Pool, IDirect3DVertexBuffer8 **ppVertexBuffer) { - return m_device->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer); + IDirect3DVertexBuffer8 *real = NULL; + IDirect3DVertexBuffer8 *wrapped = NULL; + HRESULT ret = m_device->CreateVertexBuffer(Length, Usage, FVF, Pool, &real); + + if(SUCCEEDED(ret)) + { + SCOPED_LOCK(m_D3DLock); + + wrapped = new WrappedIDirect3DVertexBuffer8(real, Length, this); + + if(m_State >= WRITING) + { + // TODO: Serialise + } + else + { + WrappedIDirect3DVertexBuffer8 *w = (WrappedIDirect3DVertexBuffer8 *)wrapped; + + m_ResourceManager->AddLiveResource(w->GetResourceID(), wrapped); + } + + *ppVertexBuffer = wrapped; + } + + return ret; } HRESULT __stdcall WrappedD3DDevice8::CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8 **ppIndexBuffer) { - return m_device->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer); + IDirect3DIndexBuffer8 *real = NULL; + IDirect3DIndexBuffer8 *wrapped = NULL; + HRESULT ret = m_device->CreateIndexBuffer(Length, Usage, Format, Pool, &real); + + if(SUCCEEDED(ret)) + { + SCOPED_LOCK(m_D3DLock); + + wrapped = new WrappedIDirect3DIndexBuffer8(real, Length, this); + + if(m_State >= WRITING) + { + // TODO: Serialise + } + else + { + WrappedIDirect3DIndexBuffer8 *w = (WrappedIDirect3DIndexBuffer8 *)wrapped; + + m_ResourceManager->AddLiveResource(w->GetResourceID(), wrapped); + } + + *ppIndexBuffer = wrapped; + } + + return ret; } HRESULT __stdcall WrappedD3DDevice8::CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, @@ -638,26 +738,46 @@ HRESULT __stdcall WrappedD3DDevice8::GetVertexShaderFunction(DWORD Handle, void HRESULT __stdcall WrappedD3DDevice8::SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer8 *pStreamData, UINT Stride) { - return m_device->SetStreamSource(StreamNumber, pStreamData, Stride); + return m_device->SetStreamSource(StreamNumber, Unwrap(pStreamData), Stride); } HRESULT __stdcall WrappedD3DDevice8::GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer8 **ppStreamData, UINT *pStride) { - return m_device->GetStreamSource(StreamNumber, ppStreamData, pStride); + IDirect3DVertexBuffer8 *real; + HRESULT ret = m_device->GetStreamSource(StreamNumber, &real, pStride); + + if(SUCCEEDED(ret)) + { + SAFE_RELEASE_NOCLEAR(real); + *ppStreamData = (IDirect3DVertexBuffer8 *)GetResourceManager()->GetWrapper(real); + SAFE_ADDREF(*ppStreamData); + } + + return ret; } HRESULT __stdcall WrappedD3DDevice8::SetIndices(IDirect3DIndexBuffer8 *pIndexData, UINT BaseVertexIndex) { - return m_device->SetIndices(pIndexData, BaseVertexIndex); + return m_device->SetIndices(Unwrap(pIndexData), BaseVertexIndex); } HRESULT __stdcall WrappedD3DDevice8::GetIndices(IDirect3DIndexBuffer8 **ppIndexData, UINT *pBaseVertexIndex) { - return m_device->GetIndices(ppIndexData, pBaseVertexIndex); + IDirect3DIndexBuffer8 *real; + HRESULT ret = m_device->GetIndices(&real, pBaseVertexIndex); + + if(SUCCEEDED(ret)) + { + SAFE_RELEASE_NOCLEAR(real); + *ppIndexData = (IDirect3DIndexBuffer8 *)GetResourceManager()->GetWrapper(real); + SAFE_ADDREF(*ppIndexData); + } + + return ret; } HRESULT __stdcall WrappedD3DDevice8::CreatePixelShader(CONST DWORD *pFunction, DWORD *pHandle) diff --git a/renderdoc/driver/d3d8/d3d8_device.h b/renderdoc/driver/d3d8/d3d8_device.h index f3a4191f0..514d327aa 100644 --- a/renderdoc/driver/d3d8/d3d8_device.h +++ b/renderdoc/driver/d3d8/d3d8_device.h @@ -25,6 +25,7 @@ #pragma once #include "common/timing.h" #include "d3d8_common.h" +#include "d3d8_manager.h" class D3D8DebugManager; @@ -50,6 +51,10 @@ public: } D3D8DebugManager *GetDebugManager() { return m_DebugManager; } + D3D8ResourceManager *GetResourceManager() { return m_ResourceManager; } + Threading::CriticalSection &D3DLock() { return m_D3DLock; } + IMPLEMENT_FUNCTION_SERIALISED(void, ReleaseResource(IDirect3DResource8 *res)); + /*** IUnknown methods ***/ ULONG STDMETHODCALLTYPE AddRef() { return m_RefCounter.AddRef(); } ULONG STDMETHODCALLTYPE Release() @@ -205,11 +210,19 @@ private: IDirect3DDevice8 *m_device; D3D8DebugManager *m_DebugManager; + D3D8ResourceManager *m_ResourceManager; D3DPRESENT_PARAMETERS m_PresentParameters; HWND m_Wnd; + // ensure all calls in via the D3D wrapped interface are thread safe + // protects wrapped resource creation and serialiser access + Threading::CriticalSection m_D3DLock; + + Serialiser *m_pSerialiser; + LogState m_State; + unsigned int m_InternalRefcount; RefCounter8 m_RefCounter; RefCounter8 m_SoftRefCounter; diff --git a/renderdoc/driver/d3d8/d3d8_manager.cpp b/renderdoc/driver/d3d8/d3d8_manager.cpp new file mode 100644 index 000000000..21b476c31 --- /dev/null +++ b/renderdoc/driver/d3d8/d3d8_manager.cpp @@ -0,0 +1,77 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include "d3d8_manager.h" +#include "d3d8_resources.h" + +bool D3D8ResourceManager::SerialisableResource(ResourceId id, D3D8ResourceRecord *record) +{ + return true; +} + +ResourceId D3D8ResourceManager::GetID(IUnknown *res) +{ + return GetResID(res); +} + +bool D3D8ResourceManager::ResourceTypeRelease(IUnknown *res) +{ + if(res) + res->Release(); + + return true; +} + +bool D3D8ResourceManager::Force_InitialState(IUnknown *res, bool prepare) +{ + return false; +} + +bool D3D8ResourceManager::Need_InitialStateChunk(IUnknown *res) +{ + return true; +} + +bool D3D8ResourceManager::Prepare_InitialState(IUnknown *res) +{ + // TODO + return false; +} + +bool D3D8ResourceManager::Serialise_InitialState(ResourceId id, IUnknown *res) +{ + // TODO + return false; +} + +void D3D8ResourceManager::Create_InitialState(ResourceId id, IUnknown *live, bool hasData) +{ +} + +void D3D8ResourceManager::Apply_InitialState(IUnknown *live, InitialContentData data) +{ + // TODO +} diff --git a/renderdoc/driver/d3d8/d3d8_manager.h b/renderdoc/driver/d3d8/d3d8_manager.h new file mode 100644 index 000000000..584080850 --- /dev/null +++ b/renderdoc/driver/d3d8/d3d8_manager.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include "api/replay/renderdoc_replay.h" +#include "common/wrapped_pool.h" +#include "core/core.h" +#include "core/resource_manager.h" +#include "serialise/serialiser.h" +#include "d3d8_common.h" + +enum D3D8ResourceType +{ + Resource_Unknown = 0, + Resource_VertexBuffer, + Resource_IndexBuffer, +}; + +struct D3D8ResourceRecord : public ResourceRecord +{ + enum + { + NullResource = NULL + }; + + D3D8ResourceRecord(ResourceId id) : ResourceRecord(id, true) {} +}; + +class D3D8ResourceManager : public ResourceManager +{ +public: + D3D8ResourceManager(LogState state, Serialiser *ser, WrappedD3DDevice8 *dev) + : ResourceManager(state, ser), m_Device(dev) + { + } + +private: + bool SerialisableResource(ResourceId id, D3D8ResourceRecord *record); + ResourceId GetID(IUnknown *res); + + bool ResourceTypeRelease(IUnknown *res); + + bool Force_InitialState(IUnknown *res, bool prepare); + bool Need_InitialStateChunk(IUnknown *res); + bool Prepare_InitialState(IUnknown *res); + bool Serialise_InitialState(ResourceId resid, IUnknown *res); + void Create_InitialState(ResourceId id, IUnknown *live, bool hasData); + void Apply_InitialState(IUnknown *live, InitialContentData data); + + WrappedD3DDevice8 *m_Device; +}; diff --git a/renderdoc/driver/d3d8/d3d8_resources.cpp b/renderdoc/driver/d3d8/d3d8_resources.cpp new file mode 100644 index 000000000..20b7b4d05 --- /dev/null +++ b/renderdoc/driver/d3d8/d3d8_resources.cpp @@ -0,0 +1,121 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "d3d8_resources.h" + +#undef D3D8_TYPE_MACRO +#define D3D8_TYPE_MACRO(iface) WRAPPED_POOL_INST(CONCAT(Wrapped, iface)); + +ALL_D3D8_TYPES; + +map + WrappedD3DBuffer8::m_BufferList; +map + WrappedD3DBuffer8::m_BufferList; + +D3D8ResourceType IdentifyTypeByPtr(IUnknown *ptr) +{ + if(ptr == NULL) + return Resource_Unknown; + +#undef D3D8_TYPE_MACRO +#define D3D8_TYPE_MACRO(iface) \ + if(UnwrapHelper::IsAlloc(ptr)) \ + return UnwrapHelper::GetTypeEnum(); + + ALL_D3D8_TYPES; + + RDCERR("Unknown type for ptr 0x%p", ptr); + + return Resource_Unknown; +} + +TrackedResource8 *GetTracked(IUnknown *ptr) +{ + if(ptr == NULL) + return NULL; + +#undef D3D8_TYPE_MACRO +#define D3D8_TYPE_MACRO(iface) \ + if(UnwrapHelper::IsAlloc(ptr)) \ + return (TrackedResource8 *)GetWrapped((iface *)ptr); + + ALL_D3D8_TYPES; + + return NULL; +} + +template <> +IUnknown *Unwrap(IUnknown *ptr) +{ + if(ptr == NULL) + return NULL; + +#undef D3D8_TYPE_MACRO +#define D3D8_TYPE_MACRO(iface) \ + if(UnwrapHelper::IsAlloc(ptr)) \ + return (IUnknown *)GetWrapped((iface *)ptr)->GetReal(); + + ALL_D3D8_TYPES; + + RDCERR("Unknown type of ptr 0x%p", ptr); + + return NULL; +} + +template <> +ResourceId GetResID(IUnknown *ptr) +{ + if(ptr == NULL) + return ResourceId(); + + TrackedResource8 *res = GetTracked(ptr); + + if(res == NULL) + { + RDCERR("Unknown type of ptr 0x%p", ptr); + + return ResourceId(); + } + + return res->GetResourceID(); +} + +template <> +D3D8ResourceRecord *GetRecord(IUnknown *ptr) +{ + if(ptr == NULL) + return NULL; + + TrackedResource8 *res = GetTracked(ptr); + + if(res == NULL) + { + RDCERR("Unknown type of ptr 0x%p", ptr); + + return NULL; + } + + return res->GetResourceRecord(); +} \ No newline at end of file diff --git a/renderdoc/driver/d3d8/d3d8_resources.h b/renderdoc/driver/d3d8/d3d8_resources.h new file mode 100644 index 000000000..074b7c6af --- /dev/null +++ b/renderdoc/driver/d3d8/d3d8_resources.h @@ -0,0 +1,332 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +#include "d3d8_device.h" +#include "d3d8_manager.h" + +class TrackedResource8 +{ +public: + TrackedResource8() { m_ID = ResourceIDGen::GetNewUniqueID(); } + ResourceId GetResourceID() { return m_ID; } + D3D8ResourceRecord *GetResourceRecord() { return m_pRecord; } + void SetResourceRecord(D3D8ResourceRecord *record) { m_pRecord = record; } +private: + TrackedResource8(const TrackedResource8 &); + TrackedResource8 &operator=(const TrackedResource8 &); + + ResourceId m_ID; + D3D8ResourceRecord *m_pRecord; +}; + +template +class WrappedIDirect3DResource8 : public RefCounter8, public NestedType, public TrackedResource8 +{ +protected: + WrappedD3DDevice8 *m_pDevice; + NestedType *m_pReal; + unsigned int m_PipelineRefs; + + WrappedIDirect3DResource8(NestedType *real, WrappedD3DDevice8 *device) + : RefCounter8(real), m_pDevice(device), m_pReal(real), m_PipelineRefs(0) + { + m_pDevice->SoftRef(); + + bool ret = m_pDevice->GetResourceManager()->AddWrapper(this, real); + if(!ret) + RDCERR("Error adding wrapper for type %s", ToStr::Get(__uuidof(NestedType)).c_str()); + + m_pDevice->GetResourceManager()->AddCurrentResource(GetResourceID(), this); + } + + virtual void Shutdown() + { + m_pDevice->GetResourceManager()->RemoveWrapper(m_pReal); + m_pDevice->GetResourceManager()->ReleaseCurrentResource(GetResourceID()); + m_pDevice->ReleaseResource((NestedType *)this); + SAFE_RELEASE(m_pReal); + m_pDevice = NULL; + } + + virtual ~WrappedIDirect3DResource8() + { + // should have already called shutdown (needs to be called from child class to ensure + // vtables are still in place when we call ReleaseResource) + RDCASSERT(m_pDevice == NULL && m_pReal == NULL); + } + +public: + typedef NestedType InnerType; + + NestedType *GetReal() { return m_pReal; } + ULONG STDMETHODCALLTYPE AddRef() { return RefCounter8::SoftRef(m_pDevice) - m_PipelineRefs; } + ULONG STDMETHODCALLTYPE Release() + { + unsigned int piperefs = m_PipelineRefs; + return RefCounter8::SoftRelease(m_pDevice) - piperefs; + } + + void PipelineAddRef() { InterlockedIncrement(&m_PipelineRefs); } + void PipelineRelease() { InterlockedDecrement(&m_PipelineRefs); } + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) + { + if(riid == __uuidof(IUnknown)) + { + *ppvObject = (IUnknown *)(NestedType *)this; + AddRef(); + return S_OK; + } + if(riid == __uuidof(NestedType)) + { + *ppvObject = (NestedType *)this; + AddRef(); + return S_OK; + } + if(riid == __uuidof(IDirect3DResource8)) + { + *ppvObject = (IDirect3DResource8 *)this; + AddRef(); + return S_OK; + } + + return RefCounter8::QueryInterface(riid, ppvObject); + } + + ////////////////////////////// + // implement IDirect3DResource8 + + HRESULT STDMETHODCALLTYPE GetDevice(__out IDirect3DDevice8 **ppDevice) + { + if(ppDevice) + { + *ppDevice = m_pDevice; + m_pDevice->AddRef(); + return S_OK; + } + return E_INVALIDARG; + } + + HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid, void *pData, DWORD *pSizeOfData) + { + return m_pReal->GetPrivateData(guid, pData, pSizeOfData); + } + + HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid, const void *pData, DWORD SizeOfData, + DWORD Flags) + { + return m_pReal->SetPrivateData(guid, pData, SizeOfData, Flags); + } + + HRESULT STDMETHODCALLTYPE FreePrivateData(REFGUID guid) { return m_pReal->FreePrivateData(guid); } + DWORD STDMETHODCALLTYPE SetPriority(DWORD PriorityNew) + { + return m_pReal->SetPriority(PriorityNew); + } + + DWORD STDMETHODCALLTYPE GetPriority() { return m_pReal->GetPriority(); } + void STDMETHODCALLTYPE PreLoad() { return m_pReal->PreLoad(); } + D3DRESOURCETYPE STDMETHODCALLTYPE GetType() { return m_pReal->GetType(); } +}; + +template +class WrappedD3DBuffer8 : public WrappedIDirect3DResource8 +{ +protected: +#if ENABLED(RDOC_DEVEL) + DescType m_Desc; +#endif + +public: + struct BufferEntry + { + BufferEntry(WrappedD3DBuffer8 *b = NULL, uint32_t l = 0) : m_Buffer(b), length(l) {} + WrappedD3DBuffer8 *m_Buffer; + uint32_t length; + }; + + static map m_BufferList; + + WrappedD3DBuffer8(NestedType *real, uint32_t byteLength, WrappedD3DDevice8 *device) + : WrappedIDirect3DResource8(real, device) + { +#if ENABLED(RDOC_DEVEL) + real->GetDesc(&m_Desc); +#endif + SCOPED_LOCK(m_pDevice->D3DLock()); + + RDCASSERT(m_BufferList.find(GetResourceID()) == m_BufferList.end()); + m_BufferList[GetResourceID()] = BufferEntry(this, byteLength); + } + + virtual ~WrappedD3DBuffer8() + { + SCOPED_LOCK(m_pDevice->D3DLock()); + + if(m_BufferList.find(GetResourceID()) != m_BufferList.end()) + m_BufferList.erase(GetResourceID()); + + Shutdown(); + } + + HRESULT STDMETHODCALLTYPE Lock(UINT OffsetToLock, UINT SizeToLock, BYTE **ppbData, DWORD Flags) + { + // TODO + return m_pReal->Lock(OffsetToLock, SizeToLock, ppbData, Flags); + } + + HRESULT STDMETHODCALLTYPE Unlock() + { + // TODO + return m_pReal->Unlock(); + } + + HRESULT STDMETHODCALLTYPE GetDesc(DescType *pDesc) { return m_pReal->GetDesc(pDesc); } +}; + +class WrappedIDirect3DVertexBuffer8 + : public WrappedD3DBuffer8 +{ +public: + ALLOCATE_WITH_WRAPPED_POOL(WrappedIDirect3DVertexBuffer8); + + enum + { + TypeEnum = Resource_VertexBuffer, + }; + + WrappedIDirect3DVertexBuffer8(IDirect3DVertexBuffer8 *real, uint32_t byteLength, + WrappedD3DDevice8 *device) + : WrappedD3DBuffer8(real, byteLength, device) + { + } +}; + +class WrappedIDirect3DIndexBuffer8 + : public WrappedD3DBuffer8 +{ +public: + ALLOCATE_WITH_WRAPPED_POOL(WrappedIDirect3DIndexBuffer8); + + enum + { + TypeEnum = Resource_IndexBuffer, + }; + + WrappedIDirect3DIndexBuffer8(IDirect3DIndexBuffer8 *real, uint32_t byteLength, + WrappedD3DDevice8 *device) + : WrappedD3DBuffer8(real, byteLength, device) + { + } +}; + +#define ALL_D3D8_TYPES \ + D3D8_TYPE_MACRO(IDirect3DVertexBuffer8); \ + D3D8_TYPE_MACRO(IDirect3DIndexBuffer8); + +// template magic voodoo to unwrap types +template +struct UnwrapHelper +{ +}; + +#undef D3D8_TYPE_MACRO +#define D3D8_TYPE_MACRO(iface) \ + template <> \ + struct UnwrapHelper \ + { \ + typedef CONCAT(Wrapped, iface) Outer; \ + static bool IsAlloc(void *ptr) { return Outer::IsAlloc(ptr); } \ + static D3D8ResourceType GetTypeEnum() { return (D3D8ResourceType)Outer::TypeEnum; } \ + static Outer *FromHandle(iface *wrapped) { return (Outer *)wrapped; } \ + }; \ + template <> \ + struct UnwrapHelper \ + { \ + typedef CONCAT(Wrapped, iface) Outer; \ + static bool IsAlloc(void *ptr) { return Outer::IsAlloc(ptr); } \ + static D3D8ResourceType GetTypeEnum() { return (D3D8ResourceType)Outer::TypeEnum; } \ + static Outer *FromHandle(iface *wrapped) { return (Outer *)wrapped; } \ + }; + +ALL_D3D8_TYPES; + +D3D8ResourceType IdentifyTypeByPtr(IUnknown *ptr); + +#define WRAPPING_DEBUG 0 + +template +typename UnwrapHelper::Outer *GetWrapped(iface *obj) +{ + if(obj == NULL) + return NULL; + + typename UnwrapHelper::Outer *wrapped = UnwrapHelper::FromHandle(obj); + +#if WRAPPING_DEBUG + if(obj != NULL && !wrapped->IsAlloc(wrapped)) + { + RDCERR("Trying to unwrap invalid type"); + return NULL; + } +#endif + + return wrapped; +} + +template +ifaceptr Unwrap(ifaceptr obj) +{ + if(obj == NULL) + return NULL; + + return GetWrapped(obj)->GetReal(); +} + +template +ResourceId GetResID(ifaceptr obj) +{ + if(obj == NULL) + return ResourceId(); + + return GetWrapped(obj)->GetResourceID(); +} + +template +D3D8ResourceRecord *GetRecord(ifaceptr obj) +{ + if(obj == NULL) + return NULL; + + return GetWrapped(obj)->GetResourceRecord(); +} + +// specialisations that use the IsAlloc() function to identify the real type +template <> +ResourceId GetResID(IUnknown *ptr); +template <> +IUnknown *Unwrap(IUnknown *ptr); +template <> +D3D8ResourceRecord *GetRecord(IUnknown *ptr); \ No newline at end of file diff --git a/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj b/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj index 3f259ed6e..49b40d46f 100644 --- a/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj +++ b/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj @@ -102,7 +102,9 @@ + + Create @@ -116,6 +118,8 @@ + + diff --git a/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj.filters b/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj.filters index f26e08ec1..a1ff02441 100644 --- a/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj.filters +++ b/renderdoc/driver/d3d8/renderdoc_d3d8.vcxproj.filters @@ -19,6 +19,9 @@ {74FA3D85-A524-442D-9682-BB832AB5E136} + + {025d23be-15d8-4d7d-bcbb-5899d5984f30} + @@ -39,6 +42,12 @@ PCH + + Util + + + Util + @@ -68,5 +77,11 @@ PCH + + Util + + + Util + \ No newline at end of file diff --git a/renderdoc/driver/dx/official/d3d8.h b/renderdoc/driver/dx/official/d3d8.h index adf91ebf0..ef8a61f75 100644 --- a/renderdoc/driver/dx/official/d3d8.h +++ b/renderdoc/driver/dx/official/d3d8.h @@ -162,7 +162,7 @@ IDirect3D8 * WINAPI Direct3DCreate8(UINT SDKVersion); #undef INTERFACE #define INTERFACE IDirect3D8 -DECLARE_INTERFACE_(IDirect3D8, IUnknown) +DECLARE_INTERFACE_IID_(IDirect3D8, IUnknown, "1DD9E8DA-1C77-4d40-B0CF-98FEFDFF9512") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -244,7 +244,7 @@ typedef struct IDirect3D8 *LPDIRECT3D8, *PDIRECT3D8; #undef INTERFACE #define INTERFACE IDirect3DDevice8 -DECLARE_INTERFACE_(IDirect3DDevice8, IUnknown) +DECLARE_INTERFACE_IID_(IDirect3DDevice8, IUnknown, "7385E5DF-8FE8-41D5-86B6-D7B48547B6CF") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -553,7 +553,7 @@ typedef struct IDirect3DDevice8 *LPDIRECT3DDEVICE8, *PDIRECT3DDEVICE8; #undef INTERFACE #define INTERFACE IDirect3DSwapChain8 -DECLARE_INTERFACE_(IDirect3DSwapChain8, IUnknown) +DECLARE_INTERFACE_IID_(IDirect3DSwapChain8, IUnknown, "928C088B-76B9-4C6B-A536-A590853876CD") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -586,7 +586,7 @@ typedef struct IDirect3DSwapChain8 *LPDIRECT3DSWAPCHAIN8, *PDIRECT3DSWAPCHAIN8; #undef INTERFACE #define INTERFACE IDirect3DResource8 -DECLARE_INTERFACE_(IDirect3DResource8, IUnknown) +DECLARE_INTERFACE_IID_(IDirect3DResource8, IUnknown, "1B36BB7B-09B7-410a-B445-7D1430D7B33F") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -638,7 +638,7 @@ typedef struct IDirect3DResource8 *LPDIRECT3DRESOURCE8, *PDIRECT3DRESOURCE8; #undef INTERFACE #define INTERFACE IDirect3DBaseTexture8 -DECLARE_INTERFACE_(IDirect3DBaseTexture8, IDirect3DResource8) +DECLARE_INTERFACE_IID_(IDirect3DBaseTexture8, IDirect3DResource8, "B4211CFA-51B9-4a9f-AB78-DB99B2BB678E") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -700,7 +700,7 @@ typedef struct IDirect3DBaseTexture8 *LPDIRECT3DBASETEXTURE8, *PDIRECT3DBASETEXT #undef INTERFACE #define INTERFACE IDirect3DTexture8 -DECLARE_INTERFACE_(IDirect3DTexture8, IDirect3DBaseTexture8) +DECLARE_INTERFACE_IID_(IDirect3DTexture8, IDirect3DBaseTexture8, "E4CDD575-2866-4f01-B12E-7EECE1EC9358") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -777,7 +777,7 @@ typedef struct IDirect3DTexture8 *LPDIRECT3DTEXTURE8, *PDIRECT3DTEXTURE8; #undef INTERFACE #define INTERFACE IDirect3DVolumeTexture8 -DECLARE_INTERFACE_(IDirect3DVolumeTexture8, IDirect3DBaseTexture8) +DECLARE_INTERFACE_IID_(IDirect3DVolumeTexture8, IDirect3DBaseTexture8, "4B8AAAFA-140F-42ba-9131-597EAFAA2EAD") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -854,7 +854,7 @@ typedef struct IDirect3DVolumeTexture8 *LPDIRECT3DVOLUMETEXTURE8, *PDIRECT3DVOLU #undef INTERFACE #define INTERFACE IDirect3DCubeTexture8 -DECLARE_INTERFACE_(IDirect3DCubeTexture8, IDirect3DBaseTexture8) +DECLARE_INTERFACE_IID_(IDirect3DCubeTexture8, IDirect3DBaseTexture8, "3EE5B968-2ACA-4c34-8BB5-7E0C3D19B750") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -930,7 +930,7 @@ typedef struct IDirect3DCubeTexture8 *LPDIRECT3DCUBETEXTURE8, *PDIRECT3DCUBETEXT #undef INTERFACE #define INTERFACE IDirect3DVertexBuffer8 -DECLARE_INTERFACE_(IDirect3DVertexBuffer8, IDirect3DResource8) +DECLARE_INTERFACE_IID_(IDirect3DVertexBuffer8, IDirect3DResource8, "8AEEEAC7-05F9-44d4-B591-000B0DF1CB95") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -991,7 +991,7 @@ typedef struct IDirect3DVertexBuffer8 *LPDIRECT3DVERTEXBUFFER8, *PDIRECT3DVERTEX #undef INTERFACE #define INTERFACE IDirect3DIndexBuffer8 -DECLARE_INTERFACE_(IDirect3DIndexBuffer8, IDirect3DResource8) +DECLARE_INTERFACE_IID_(IDirect3DIndexBuffer8, IDirect3DResource8, "0E689C9A-053D-44a0-9D92-DB0E3D750F86") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -1052,7 +1052,7 @@ typedef struct IDirect3DIndexBuffer8 *LPDIRECT3DINDEXBUFFER8, *PDIRECT3DINDEXBUF #undef INTERFACE #define INTERFACE IDirect3DSurface8 -DECLARE_INTERFACE_(IDirect3DSurface8, IUnknown) +DECLARE_INTERFACE_IID_(IDirect3DSurface8, IUnknown, "B96EEBCA-B326-4ea5-882F-2FF5BAE021DD") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE; @@ -1104,7 +1104,7 @@ typedef struct IDirect3DSurface8 *LPDIRECT3DSURFACE8, *PDIRECT3DSURFACE8; #undef INTERFACE #define INTERFACE IDirect3DVolume8 -DECLARE_INTERFACE_(IDirect3DVolume8, IUnknown) +DECLARE_INTERFACE_IID_(IDirect3DVolume8, IUnknown, "BD7349F5-14F1-42e4-9C79-972380DB40C0") { /*** IUnknown methods ***/ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;