diff --git a/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp index 43c633db3..cdaa24b07 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list4_wrap.cpp @@ -1223,6 +1223,42 @@ void WrappedID3D12GraphicsCommandList::BuildRaytracingAccelerationStructure( return ProcessASBuildAfterSubmission(asbWrappedResourceId, asbWrappedResourceBufferOffset, byteSize, buildData); }); + + // an indirect AS build will pull in buffers we can't know about + if(pDesc->Inputs.Type == D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL) + { + if(pDesc->Inputs.DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY_OF_POINTERS) + m_ListRecord->cmdInfo->forceMapsListEvent = true; + + m_ListRecord->MarkResourceFrameReferenced( + WrappedID3D12Resource::GetResIDFromAddr(pDesc->Inputs.InstanceDescs), eFrameRef_Read); + } + else + { + for(UINT i = 0; i < pDesc->Inputs.NumDescs; i++) + { + const D3D12_RAYTRACING_GEOMETRY_DESC &geom = + pDesc->Inputs.DescsLayout == D3D12_ELEMENTS_LAYOUT_ARRAY_OF_POINTERS + ? *pDesc->Inputs.ppGeometryDescs[i] + : pDesc->Inputs.pGeometryDescs[i]; + + if(geom.Type == D3D12_RAYTRACING_GEOMETRY_TYPE_PROCEDURAL_PRIMITIVE_AABBS) + { + m_ListRecord->MarkResourceFrameReferenced( + WrappedID3D12Resource::GetResIDFromAddr(geom.AABBs.AABBs.StartAddress), eFrameRef_Read); + } + else if(geom.Type == D3D12_RAYTRACING_GEOMETRY_TYPE_TRIANGLES) + { + m_ListRecord->MarkResourceFrameReferenced( + WrappedID3D12Resource::GetResIDFromAddr(geom.Triangles.IndexBuffer), eFrameRef_Read); + m_ListRecord->MarkResourceFrameReferenced( + WrappedID3D12Resource::GetResIDFromAddr(geom.Triangles.Transform3x4), eFrameRef_Read); + m_ListRecord->MarkResourceFrameReferenced( + WrappedID3D12Resource::GetResIDFromAddr(geom.Triangles.VertexBuffer.StartAddress), + eFrameRef_Read); + } + } + } } } @@ -1757,6 +1793,9 @@ void WrappedID3D12GraphicsCommandList::DispatchRays(_In_ const D3D12_DISPATCH_RA // during capture track the ray dispatches so the memory can be freed dynamically. On replay we // free all the memory at the end of each replay m_RayDispatches.push_back(patchedDispatch.resources); + + // a ray dispatch certainly will pull in buffers we can't know about + m_ListRecord->cmdInfo->forceMapsListEvent = true; } } diff --git a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp index 3cf66ad63..e53f9df1f 100644 --- a/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_list_wrap.cpp @@ -4429,7 +4429,8 @@ void WrappedID3D12GraphicsCommandList::ExecuteIndirect(ID3D12CommandSignature *p UINT64 argOffset = ArgumentBufferOffset; PatchedRayDispatch patchedDispatch = {}; - if(((WrappedID3D12CommandSignature *)pCommandSignature)->sig.raytraced) + const D3D12CommandSignature &sigData = ((WrappedID3D12CommandSignature *)pCommandSignature)->sig; + if(sigData.raytraced) { patchedDispatch = GetResourceManager()->GetRTManager()->PatchIndirectRayDispatch( m_pList, m_CaptureComputeState.heaps, pCommandSignature, MaxCommandCount, pArgumentBuffer, @@ -4470,6 +4471,18 @@ void WrappedID3D12GraphicsCommandList::ExecuteIndirect(ID3D12CommandSignature *p // free all the memory at the end of each replay m_RayDispatches.push_back(patchedDispatch.resources); } + + // an ExecuteIndirect could reference any buffer at all without us knowing if it has GPU VAs + // anywhere in its arguments + for(const D3D12_INDIRECT_ARGUMENT_DESC &arg : sigData.arguments) + { + if(arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW || + arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW || + arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW || + arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW || + arg.Type == D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW) + m_ListRecord->cmdInfo->forceMapsListEvent = true; + } } } diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index 4c7b94a20..178a27ed6 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -802,6 +802,9 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists bool capframe = IsActiveCapturing(m_State); std::unordered_set refdIDs; + // did an event happen which could use arbitrary GPU VAs (like vulkan BDA) meaning we have to + // consider maps to that memory + bool forceMapsListEvent = false; for(UINT i = 0; i < NumCommandLists; i++) { @@ -814,6 +817,8 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists m_pDevice->ApplyBarriers(record->bakedCommands->cmdInfo->barriers); + forceMapsListEvent |= record->bakedCommands->cmdInfo->forceMapsListEvent; + wrapped->AddRayDispatches(rayDispatches); // need to lock the whole section of code, not just the check on @@ -946,7 +951,9 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists // mapped may not be the one that was bound but they may overlap, so we use the heap as // reference for non-committed resource. std::unordered_set mappableIDs; - WrappedID3D12Resource::GetMappableIDs(GetResourceManager(), refdIDs, mappableIDs); + + if(!forceMapsListEvent) + WrappedID3D12Resource::GetMappableIDs(GetResourceManager(), refdIDs, mappableIDs); for(auto it = maps.begin(); it != maps.end(); ++it) { @@ -955,7 +962,7 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists size_t size = (size_t)it->totalSize; // only need to flush memory that could affect this submitted batch of work - if(mappableIDs.find(res->GetMappableID()) == mappableIDs.end()) + if(!forceMapsListEvent && mappableIDs.find(res->GetMappableID()) == mappableIDs.end()) { RDCDEBUG("Map of memory %s (mappable ID %s) not referenced in this queue - not flushing", ToStr(res->GetResourceID()).c_str(), ToStr(res->GetMappableID()).c_str()); diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index 7313942f6..2dfad6878 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -489,6 +489,8 @@ struct CmdListRecordingInfo BarrierSet barriers; + bool forceMapsListEvent = false; + // a list of all resources dirtied by this command list std::set dirtied; @@ -655,6 +657,7 @@ struct D3D12ResourceRecord : public ResourceRecord cmdInfo->dirtied.swap(bakedCommands->cmdInfo->dirtied); cmdInfo->boundDescs.swap(bakedCommands->cmdInfo->boundDescs); cmdInfo->bundles.swap(bakedCommands->cmdInfo->bundles); + bakedCommands->cmdInfo->forceMapsListEvent = cmdInfo->forceMapsListEvent; bakedCommands->cmdInfo->alloc = cmdInfo->alloc; bakedCommands->cmdInfo->allocRecord = cmdInfo->allocRecord; }