Force map flushes for command buffers that may reference arbitrary VAs

This commit is contained in:
baldurk
2024-10-16 18:13:26 +01:00
parent 97ff2d67f8
commit 600fd2cb73
4 changed files with 65 additions and 3 deletions
@@ -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;
}
}
@@ -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;
}
}
}
@@ -802,6 +802,9 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists
bool capframe = IsActiveCapturing(m_State);
std::unordered_set<ResourceId> 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<ResourceId> 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());
+3
View File
@@ -489,6 +489,8 @@ struct CmdListRecordingInfo
BarrierSet barriers;
bool forceMapsListEvent = false;
// a list of all resources dirtied by this command list
std::set<ResourceId> 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;
}