From 282e76a2f5b63a10e8930729457c816dbef765e9 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 27 Aug 2024 16:25:41 +0100 Subject: [PATCH] Defer state object compilation on D3D12 --- renderdoc/driver/d3d12/d3d12_device_wrap5.cpp | 220 ++++++++++------- renderdoc/driver/d3d12/d3d12_device_wrap7.cpp | 226 +++++++++++------- renderdoc/driver/d3d12/d3d12_resources.cpp | 5 +- renderdoc/driver/d3d12/d3d12_resources.h | 17 +- 4 files changed, 301 insertions(+), 167 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap5.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap5.cpp index c02b076bb..068e2f0fe 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap5.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap5.cpp @@ -23,9 +23,77 @@ ******************************************************************************/ #include "d3d12_device.h" +#include "core/settings.h" #include "driver/dxgi/dxgi_common.h" #include "d3d12_resources.h" +RDOC_EXTERN_CONFIG(bool, Replay_Debug_SingleThreadedCompilation); + +static RDResult DeferredStateObjCompile(ID3D12Device5 *device5, + const D3D12_STATE_OBJECT_DESC &Descriptor, + WrappedID3D12StateObject *wrappedObj) +{ + rdcarray rootSigs; + rdcarray collections; + + // unwrap the referenced objects in place + const D3D12_STATE_SUBOBJECT *subs = Descriptor.pSubobjects; + for(UINT i = 0; i < Descriptor.NumSubobjects; i++) + { + if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || + subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) + { + // both structs are the same + D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; + rootSigs.push_back(global->pGlobalRootSignature); + global->pGlobalRootSignature = Unwrap(global->pGlobalRootSignature); + } + else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) + { + D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; + collections.push_back(coll->pExistingCollection); + // wait for any jobs for existing collections to complete + WrappedID3D12StateObject *wrapped = GetWrapped(coll->pExistingCollection); + coll->pExistingCollection = wrapped->GetReal(); + } + } + + ID3D12StateObject *realObj; + HRESULT hr = + device5->CreateStateObject(&Descriptor, __uuidof(ID3D12StateObject), (void **)&realObj); + + // rewrap the objects for PopulateDatabase below + for(UINT i = 0, r = 0, c = 0; i < Descriptor.NumSubobjects; i++) + { + if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || + subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) + { + D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; + // the same order as above, we can consume the rootSigs in order + global->pGlobalRootSignature = rootSigs[r++]; + } + else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) + { + D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; + coll->pExistingCollection = collections[c++]; + } + } + + wrappedObj->SetNewReal(realObj); + + wrappedObj->exports->SetObjectProperties(wrappedObj->GetProperties()); + + wrappedObj->exports->PopulateDatabase(Descriptor.NumSubobjects, subs); + + if(FAILED(hr)) + { + RETURN_ERROR_RESULT(ResultCode::APIReplayFailed, "Failed creating state object, HRESULT: %s", + ToStr(hr).c_str()); + } + + return ResultCode::Succeeded; +} + HRESULT WrappedID3D12Device::CreateLifetimeTracker(_In_ ID3D12LifetimeOwner *pOwner, REFIID riid, _COM_Outptr_ void **ppvTracker) { @@ -89,98 +157,89 @@ bool WrappedID3D12Device::Serialise_CreateStateObject(SerialiserType &ser, if(IsReplayingAndReading()) { - ID3D12StateObject *ret = NULL; - HRESULT hr = E_NOINTERFACE; - - // unwrap the subobjects that need unwrapping in-place. We'll undo these after creating the - // object - this is probably better than unwrapping to a separate object since that requires - // rebasing all the associations etc - - rdcarray rootSigs; - rdcarray collections; - - const D3D12_STATE_SUBOBJECT *subs = Descriptor.pSubobjects; - for(UINT i = 0; i < Descriptor.NumSubobjects; i++) - { - if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || - subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) - { - // both structs are the same - D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; - rootSigs.push_back(global->pGlobalRootSignature); - global->pGlobalRootSignature = Unwrap(global->pGlobalRootSignature); - } - else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) - { - D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; - collections.push_back(coll->pExistingCollection); - coll->pExistingCollection = Unwrap(coll->pExistingCollection); - } - } + // we steal the serialised descriptor here so we can pass it to jobs without its contents and + // all of the allocated structures and arrays being deserialised. We add a job which waits on + // the compiles then deserialises this manually. + D3D12_STATE_OBJECT_DESC OrigDescriptor = Descriptor; + Descriptor = {}; m_UsedDXIL = true; - if(m_pDevice5) - { - hr = m_pDevice5->CreateStateObject(&Descriptor, guid, (void **)&ret); - } - else + if(!m_pDevice5) { SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, "Capture requires ID3D12Device5 which isn't available"); return false; } - if(FAILED(hr)) + WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject( + GetResourceManager()->CreateDeferredHandle(), true, this); + + wrapped->exports = new D3D12ShaderExportDatabase( + pStateObject, GetResourceManager()->GetRaytracingResourceAndUtilHandler()); + + // TODO: Apply m_GlobalEXTUAV, m_GlobalEXTUAVSpace for processing extensions in the DXBC files? + + AddResource(pStateObject, ResourceType::PipelineState, "State Object"); + + rdcarray parents; + + const D3D12_STATE_SUBOBJECT *subs = OrigDescriptor.pSubobjects; + for(UINT i = 0; i < OrigDescriptor.NumSubobjects; i++) { - SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIReplayFailed, - "Failed creating state object, HRESULT: %s", ToStr(hr).c_str()); - return false; + if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || + subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) + { + // both structs are the same + D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; + DerivedResource(global->pGlobalRootSignature, pStateObject); + } + else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) + { + D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; + DerivedResource(coll->pExistingCollection, pStateObject); + + if(!Replay_Debug_SingleThreadedCompilation()) + { + parents.push_back(GetWrapped(coll->pExistingCollection)->deferredJob); + } + } + } + + if(Replay_Debug_SingleThreadedCompilation()) + { + RDResult res = DeferredStateObjCompile(m_pDevice5, OrigDescriptor, wrapped); + Deserialise(OrigDescriptor); + + if(res != ResultCode::Succeeded) + { + m_FailedReplayResult = res; + return false; + } } else { - for(UINT i = 0, r = 0, c = 0; i < Descriptor.NumSubobjects; i++) - { - if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || - subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) - { - D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; - // the same order as above, we can consume the rootSigs in order - global->pGlobalRootSignature = rootSigs[r++]; - } - else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) - { - D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; - coll->pExistingCollection = collections[c++]; - } - } + wrapped->deferredJob = Threading::JobSystem::AddJob( + [wrappedD3D12 = this, device5 = m_pDevice5, OrigDescriptor, wrapped]() { + PerformanceTimer timer; + wrappedD3D12->CheckDeferredResult( + DeferredStateObjCompile(device5, OrigDescriptor, wrapped)); + wrappedD3D12->AddDeferredTime(timer.GetMilliseconds()); - WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject(ret, this); - - // TODO: Apply m_GlobalEXTUAV, m_GlobalEXTUAVSpace for processing extensions in the DXBC files? - - wrapped->exports = new D3D12ShaderExportDatabase( - pStateObject, GetResourceManager()->GetRaytracingResourceAndUtilHandler(), - wrapped->GetProperties()); - - wrapped->exports->PopulateDatabase(Descriptor.NumSubobjects, subs); - - AddResource(pStateObject, ResourceType::PipelineState, "State Object"); - for(ID3D12RootSignature *rootSig : rootSigs) - DerivedResource(rootSig, pStateObject); - for(ID3D12StateObject *coll : collections) - DerivedResource(coll, pStateObject); - - // if this shader was initialised with nvidia's dynamic UAV, pull in that chunk as one of ours - // and unset it (there will be one for each create that actually used vendor extensions) - if(m_VendorEXT == GPUVendor::nVidia && m_GlobalEXTUAV != ~0U) - { - GetResourceDesc(pStateObject) - .initialisationChunks.push_back((uint32_t)m_StructuredFile->chunks.size() - 2); - m_GlobalEXTUAV = ~0U; - } - GetResourceManager()->AddLiveResource(pStateObject, wrapped); + Deserialise(OrigDescriptor); + }, + parents); } + + // if this shader was initialised with nvidia's dynamic UAV, pull in that chunk as one of ours + // and unset it (there will be one for each create that actually used vendor extensions) + if(m_VendorEXT == GPUVendor::nVidia && m_GlobalEXTUAV != ~0U) + { + GetResourceDesc(pStateObject) + .initialisationChunks.push_back((uint32_t)m_StructuredFile->chunks.size() - 2); + m_GlobalEXTUAV = ~0U; + } + GetResourceManager()->AddLiveResource(pStateObject, wrapped); } return true; @@ -207,7 +266,7 @@ WrappedID3D12Device::CreateStateObject(const D3D12_STATE_OBJECT_DESC *pDesc, REF if(SUCCEEDED(ret)) { - WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject(real, this); + WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject(real, false, this); if(IsCaptureMode(m_State)) { @@ -228,8 +287,9 @@ WrappedID3D12Device::CreateStateObject(const D3D12_STATE_OBJECT_DESC *pDesc, REF Serialise_CreateStateObject(ser, pDesc, riid, (void **)&wrapped); wrapped->exports = new D3D12ShaderExportDatabase( - wrapped->GetResourceID(), GetResourceManager()->GetRaytracingResourceAndUtilHandler(), - wrapped->GetProperties()); + wrapped->GetResourceID(), GetResourceManager()->GetRaytracingResourceAndUtilHandler()); + + wrapped->exports->SetObjectProperties(wrapped->GetProperties()); wrapped->exports->PopulateDatabase(pDesc->NumSubobjects, pDesc->pSubobjects); diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap7.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap7.cpp index 166e3488a..373ec1579 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap7.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap7.cpp @@ -23,9 +23,79 @@ ******************************************************************************/ #include "d3d12_device.h" +#include "core/settings.h" #include "driver/dxgi/dxgi_common.h" #include "d3d12_resources.h" +RDOC_EXTERN_CONFIG(bool, Replay_Debug_SingleThreadedCompilation); + +static RDResult DeferredStateObjGrow(ID3D12Device7 *device7, + const D3D12_STATE_OBJECT_DESC &Descriptor, + ID3D12StateObject *pStateObjectToGrowFrom, + WrappedID3D12StateObject *wrappedObj) +{ + rdcarray rootSigs; + rdcarray collections; + + // unwrap the referenced objects in place + const D3D12_STATE_SUBOBJECT *subs = Descriptor.pSubobjects; + for(UINT i = 0; i < Descriptor.NumSubobjects; i++) + { + if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || + subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) + { + // both structs are the same + D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; + rootSigs.push_back(global->pGlobalRootSignature); + global->pGlobalRootSignature = Unwrap(global->pGlobalRootSignature); + } + else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) + { + D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; + collections.push_back(coll->pExistingCollection); + // wait for any jobs for existing collections to complete + WrappedID3D12StateObject *wrapped = GetWrapped(coll->pExistingCollection); + coll->pExistingCollection = wrapped->GetReal(); + } + } + + ID3D12StateObject *realObj; + HRESULT hr = device7->AddToStateObject(&Descriptor, Unwrap(pStateObjectToGrowFrom), + __uuidof(ID3D12StateObject), (void **)&realObj); + + // rewrap the objects for PopulateDatabase below + for(UINT i = 0, r = 0, c = 0; i < Descriptor.NumSubobjects; i++) + { + if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || + subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) + { + D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; + // the same order as above, we can consume the rootSigs in order + global->pGlobalRootSignature = rootSigs[r++]; + } + else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) + { + D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; + coll->pExistingCollection = collections[c++]; + } + } + + wrappedObj->SetNewReal(realObj); + + wrappedObj->exports->SetObjectProperties(wrappedObj->GetProperties()); + + wrappedObj->exports->GrowFrom(GetWrapped(pStateObjectToGrowFrom)->exports); + wrappedObj->exports->PopulateDatabase(Descriptor.NumSubobjects, subs); + + if(FAILED(hr)) + { + RETURN_ERROR_RESULT(ResultCode::APIReplayFailed, "Failed creating state object, HRESULT: %s", + ToStr(hr).c_str()); + } + + return ResultCode::Succeeded; +} + template bool WrappedID3D12Device::Serialise_AddToStateObject(SerialiserType &ser, const D3D12_STATE_OBJECT_DESC *pAddition, @@ -44,100 +114,93 @@ bool WrappedID3D12Device::Serialise_AddToStateObject(SerialiserType &ser, if(IsReplayingAndReading()) { - ID3D12StateObject *ret = NULL; - HRESULT hr = E_NOINTERFACE; - - // unwrap the subobjects that need unwrapping in-place. We'll undo these after creating the - // object - this is probably better than unwrapping to a separate object since that requires - // rebasing all the associations etc - - rdcarray rootSigs; - rdcarray collections; - - const D3D12_STATE_SUBOBJECT *subs = Addition.pSubobjects; - for(UINT i = 0; i < Addition.NumSubobjects; i++) - { - if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || - subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) - { - // both structs are the same - D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; - rootSigs.push_back(global->pGlobalRootSignature); - global->pGlobalRootSignature = Unwrap(global->pGlobalRootSignature); - } - else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) - { - D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; - collections.push_back(coll->pExistingCollection); - coll->pExistingCollection = Unwrap(coll->pExistingCollection); - } - } + // we steal the serialised descriptor here so we can pass it to jobs without its contents and + // all of the allocated structures and arrays being deserialised. We add a job which waits on + // the compiles then deserialises this manually. + D3D12_STATE_OBJECT_DESC OrigAddition = Addition; + Addition = {}; m_UsedDXIL = true; - if(m_pDevice7) - { - hr = m_pDevice7->AddToStateObject(&Addition, Unwrap(pStateObjectToGrowFrom), guid, - (void **)&ret); - } - else + if(!m_pDevice7) { SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIHardwareUnsupported, "Capture requires ID3D12Device7 which isn't available"); return false; } - if(FAILED(hr)) + WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject( + GetResourceManager()->CreateDeferredHandle(), true, this); + + // TODO: Apply m_GlobalEXTUAV, m_GlobalEXTUAVSpace for processing extensions in the DXBC files? + + wrapped->exports = new D3D12ShaderExportDatabase( + pNewStateObject, GetResourceManager()->GetRaytracingResourceAndUtilHandler()); + + AddResource(pNewStateObject, ResourceType::PipelineState, "State Object"); + DerivedResource(pStateObjectToGrowFrom, pNewStateObject); + + rdcarray parents; + + const D3D12_STATE_SUBOBJECT *subs = OrigAddition.pSubobjects; + for(UINT i = 0; i < OrigAddition.NumSubobjects; i++) { - SET_ERROR_RESULT(m_FailedReplayResult, ResultCode::APIReplayFailed, - "Failed creating state object, HRESULT: %s", ToStr(hr).c_str()); - return false; + if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || + subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) + { + // both structs are the same + D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; + DerivedResource(global->pGlobalRootSignature, pNewStateObject); + } + else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) + { + D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; + DerivedResource(coll->pExistingCollection, pNewStateObject); + + if(!Replay_Debug_SingleThreadedCompilation()) + { + parents.push_back(GetWrapped(coll->pExistingCollection)->deferredJob); + } + } + } + + if(Replay_Debug_SingleThreadedCompilation()) + { + RDResult res = DeferredStateObjGrow(m_pDevice7, OrigAddition, pStateObjectToGrowFrom, wrapped); + Deserialise(OrigAddition); + + if(res != ResultCode::Succeeded) + { + m_FailedReplayResult = res; + return false; + } } else { - for(UINT i = 0, r = 0, c = 0; i < Addition.NumSubobjects; i++) - { - if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE || - subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE) - { - D3D12_GLOBAL_ROOT_SIGNATURE *global = (D3D12_GLOBAL_ROOT_SIGNATURE *)subs[i].pDesc; - // the same order as above, we can consume the rootSigs in order - global->pGlobalRootSignature = rootSigs[r++]; - } - else if(subs[i].Type == D3D12_STATE_SUBOBJECT_TYPE_EXISTING_COLLECTION) - { - D3D12_EXISTING_COLLECTION_DESC *coll = (D3D12_EXISTING_COLLECTION_DESC *)subs[i].pDesc; - coll->pExistingCollection = collections[c++]; - } - } + // first wait on the parent + parents.push_back(GetWrapped(pStateObjectToGrowFrom)->deferredJob); - WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject(ret, this); + wrapped->deferredJob = Threading::JobSystem::AddJob( + [wrappedD3D12 = this, device7 = m_pDevice7, OrigAddition, pStateObjectToGrowFrom, wrapped]() { + PerformanceTimer timer; + wrappedD3D12->CheckDeferredResult( + DeferredStateObjGrow(device7, OrigAddition, pStateObjectToGrowFrom, wrapped)); + wrappedD3D12->AddDeferredTime(timer.GetMilliseconds()); - // TODO: Apply m_GlobalEXTUAV, m_GlobalEXTUAVSpace for processing extensions in the DXBC files? - - wrapped->exports = new D3D12ShaderExportDatabase( - pNewStateObject, GetResourceManager()->GetRaytracingResourceAndUtilHandler(), - wrapped->GetProperties()); - - wrapped->exports->GrowFrom(((WrappedID3D12StateObject *)pStateObjectToGrowFrom)->exports); - wrapped->exports->PopulateDatabase(Addition.NumSubobjects, subs); - - AddResource(pNewStateObject, ResourceType::PipelineState, "State Object"); - for(ID3D12RootSignature *rootSig : rootSigs) - DerivedResource(rootSig, pNewStateObject); - for(ID3D12StateObject *coll : collections) - DerivedResource(coll, pNewStateObject); - - // if this shader was initialised with nvidia's dynamic UAV, pull in that chunk as one of ours - // and unset it (there will be one for each create that actually used vendor extensions) - if(m_VendorEXT == GPUVendor::nVidia && m_GlobalEXTUAV != ~0U) - { - GetResourceDesc(pNewStateObject) - .initialisationChunks.push_back((uint32_t)m_StructuredFile->chunks.size() - 2); - m_GlobalEXTUAV = ~0U; - } - GetResourceManager()->AddLiveResource(pNewStateObject, wrapped); + Deserialise(OrigAddition); + }, + parents); } + + // if this shader was initialised with nvidia's dynamic UAV, pull in that chunk as one of ours + // and unset it (there will be one for each create that actually used vendor extensions) + if(m_VendorEXT == GPUVendor::nVidia && m_GlobalEXTUAV != ~0U) + { + GetResourceDesc(pNewStateObject) + .initialisationChunks.push_back((uint32_t)m_StructuredFile->chunks.size() - 2); + m_GlobalEXTUAV = ~0U; + } + GetResourceManager()->AddLiveResource(pNewStateObject, wrapped); } return true; @@ -167,7 +230,7 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12Device::AddToStateObject( if(SUCCEEDED(ret)) { - WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject(real, this); + WrappedID3D12StateObject *wrapped = new WrappedID3D12StateObject(real, false, this); if(IsCaptureMode(m_State)) { @@ -188,8 +251,9 @@ HRESULT STDMETHODCALLTYPE WrappedID3D12Device::AddToStateObject( Serialise_AddToStateObject(ser, pAddition, pStateObjectToGrowFrom, riid, (void **)&wrapped); wrapped->exports = new D3D12ShaderExportDatabase( - wrapped->GetResourceID(), GetResourceManager()->GetRaytracingResourceAndUtilHandler(), - wrapped->GetProperties()); + wrapped->GetResourceID(), GetResourceManager()->GetRaytracingResourceAndUtilHandler()); + + wrapped->exports->SetObjectProperties(wrapped->GetProperties()); wrapped->exports->GrowFrom(((WrappedID3D12StateObject *)pStateObjectToGrowFrom)->exports); wrapped->exports->PopulateDatabase(pAddition->NumSubobjects, pAddition->pSubobjects); diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 4cc48e512..1d6bc449d 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -840,9 +840,8 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess() } D3D12ShaderExportDatabase::D3D12ShaderExportDatabase(ResourceId id, - D3D12RaytracingResourceAndUtilHandler *rayManager, - ID3D12StateObjectProperties *obj) - : RefCounter12(NULL), objectOriginalId(id), m_RayManager(rayManager), m_StateObjectProps(obj) + D3D12RaytracingResourceAndUtilHandler *rayManager) + : RefCounter12(NULL), objectOriginalId(id), m_RayManager(rayManager) { m_RayManager->RegisterExportDatabase(this); } diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 2f5d339c1..0d9a8ee97 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -1036,10 +1036,11 @@ typedef WrappedID3D12PipelineState::ShaderEntry WrappedID3D12Shader; struct D3D12ShaderExportDatabase : public RefCounter12 { public: - D3D12ShaderExportDatabase(ResourceId id, D3D12RaytracingResourceAndUtilHandler *rayManager, - ID3D12StateObjectProperties *obj); + D3D12ShaderExportDatabase(ResourceId id, D3D12RaytracingResourceAndUtilHandler *rayManager); ~D3D12ShaderExportDatabase(); + void SetObjectProperties(ID3D12StateObjectProperties *obj) { m_StateObjectProps = obj; } + ResourceId GetResourceId() { return objectOriginalId; } void GrowFrom(D3D12ShaderExportDatabase *existing) { InheritAllCollectionExports(existing); } @@ -1167,16 +1168,26 @@ public: D3D12ShaderExportDatabase *exports = NULL; + Threading::JobSystem::Job *deferredJob = NULL; + enum { TypeEnum = Resource_StateObject, }; - WrappedID3D12StateObject(ID3D12StateObject *real, WrappedID3D12Device *device) + WrappedID3D12StateObject(ID3D12StateObject *real, bool deferredHandle, WrappedID3D12Device *device) : WrappedDeviceChild12(real, device) { + if(!deferredHandle) + SetNewReal(real); + } + + void SetNewReal(ID3D12StateObject *real) + { + m_pReal = real; real->QueryInterface(__uuidof(ID3D12StateObjectProperties), (void **)&properties); } + virtual ~WrappedID3D12StateObject() { SAFE_RELEASE(properties);