Add to track the lifetime of acceleration structs

* During recording of acceleration structure builds, add a callback to
  track lifetime of virtual acceleration structure resource.
* Execute the callback at time command list execution to ensure the
  order of correct acceleration structure on the backing buffer storage.
This commit is contained in:
Amit Prakash
2024-02-05 18:42:29 -05:00
committed by baldurk
parent ae8bc03c18
commit 475dc0aabf
6 changed files with 250 additions and 6 deletions
@@ -191,6 +191,8 @@ private:
static rdcstr GetChunkName(uint32_t idx);
D3D12ResourceManager *GetResourceManager() { return m_pDevice->GetResourceManager(); }
rdcarray<std::function<bool()>> m_accStructPostBuildQueueFunc;
public:
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12GraphicsCommandList);
@@ -237,6 +239,24 @@ public:
bool ValidateRootGPUVA(D3D12_GPU_VIRTUAL_ADDRESS buffer);
void EnqueueAccStructPostBuild(const std::function<bool()> &postBldExec)
{
m_accStructPostBuildQueueFunc.push_back(postBldExec);
}
bool ExecuteAccStructPostBuilds()
{
bool success = true;
for(std::function<bool()> &func : m_accStructPostBuildQueueFunc)
{
success &= func();
}
m_accStructPostBuildQueueFunc.clear();
return success;
}
//////////////////////////////
// implement IUnknown
ULONG STDMETHODCALLTYPE AddRef() { return m_RefCounter.SoftRef(m_pDevice); }
@@ -742,8 +742,88 @@ void WrappedID3D12GraphicsCommandList::BuildRaytracingAccelerationStructure(
_In_reads_opt_(NumPostbuildInfoDescs)
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO_DESC *pPostbuildInfoDescs)
{
// TODO AMD
RDCERR("BuildRaytracingAccelerationStructure called but raytracing is not supported!");
SERIALISE_TIME_CALL(m_pList4->BuildRaytracingAccelerationStructure(pDesc, NumPostbuildInfoDescs,
pPostbuildInfoDescs));
if(IsCaptureMode(m_State))
{
// Acceleration structure (AS) are created on buffer created with Acceleration structure init
// state which helps them differentiate between non-Acceleration structure buffers (non-ASB).
// AS creation at recording can happen at any offset, given offset + its size is less than the
// resource size. It can also be recorded for overwriting on same or another command list,
// invalidating occupying previous acceleration structure(s) in order of command list execution.
// It can also be updated but there are many update constraints around it.
CACHE_THREAD_SERIALISER();
SCOPED_SERIALISE_CHUNK(D3D12Chunk::List_BuildRaytracingAccelerationStructure);
D3D12ResourceManager *resManager = m_pDevice->GetResourceManager();
ResourceId asbWrappedResourceId;
D3D12BufferOffset asbWrappedResourceBufferOffset;
WrappedID3D12Resource::GetResIDFromAddr(pDesc->DestAccelerationStructureData,
asbWrappedResourceId, asbWrappedResourceBufferOffset);
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO preBldInfo;
m_pDevice->GetRaytracingAccelerationStructurePrebuildInfo(&pDesc->Inputs, &preBldInfo);
auto PostBldExecute = [resManager, asbWrappedResourceId, asbWrappedResourceBufferOffset,
preBldInfo]() -> bool {
bool success = false;
D3D12AccelerationStructure *accStructAtOffset = NULL;
WrappedID3D12Resource *asbWrappedResource =
resManager->GetCurrentAs<WrappedID3D12Resource>(asbWrappedResourceId);
// See if acc already exist at the given offset
bool accStructExistAtOffset = asbWrappedResource->GetAccStructIfExist(
asbWrappedResourceBufferOffset, &accStructAtOffset);
bool createAccStruct = false;
if(accStructExistAtOffset)
{
if(accStructAtOffset && accStructAtOffset->Size() != preBldInfo.ResultDataMaxSizeInBytes)
{
asbWrappedResource->DeleteAccStructAtOffset(asbWrappedResourceBufferOffset);
createAccStruct = true;
}
}
else
{
createAccStruct = true;
}
if(createAccStruct)
{
// CreateAccStruct also deletes any previous overlapping ASs on the ASB
if(asbWrappedResource->CreateAccStruct(asbWrappedResourceBufferOffset, preBldInfo,
&accStructAtOffset))
{
success = true;
D3D12ResourceRecord *record =
resManager->AddResourceRecord(accStructAtOffset->GetResourceID());
record->type = Resource_AccelerationStructure;
record->Length = 0;
accStructAtOffset->SetResourceRecord(record);
resManager->MarkDirtyResource(accStructAtOffset->GetResourceID());
record->AddParent(
resManager->GetResourceRecord(accStructAtOffset->GetBackingBufferResourceId()));
}
else
{
RDCERR("Unable to create acceleration structure");
success = false;
}
}
return success;
};
EnqueueAccStructPostBuild(PostBldExecute);
}
}
template <typename SerialiserType>
@@ -738,6 +738,17 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists
if(!SkipRealExecute)
{
SERIALISE_TIME_CALL(m_pReal->ExecuteCommandLists(NumCommandLists, unwrapped));
for(UINT i = 0; i < NumCommandLists; i++)
{
WrappedID3D12GraphicsCommandList *wrapped =
(WrappedID3D12GraphicsCommandList *)(ppCommandLists[i]);
if(!wrapped->ExecuteAccStructPostBuilds())
{
RDCERR("Unable to execute post build for acc struct");
}
}
}
if(IsCaptureMode(m_State))
+9
View File
@@ -848,6 +848,15 @@ public:
WriteSerialiser &GetThreadSerialiser();
ID3D12Device *GetReal() { return m_pDevice; }
ID3D12Device1 *GetReal1() const { return m_pDevice1; }
ID3D12Device2 *GetReal2() const { return m_pDevice2; }
ID3D12Device3 *GetReal3() const { return m_pDevice3; }
ID3D12Device4 *GetReal4() const { return m_pDevice4; }
ID3D12Device5 *GetReal5() const { return m_pDevice5; }
ID3D12Device6 *GetReal6() const { return m_pDevice6; }
ID3D12Device7 *GetReal7() const { return m_pDevice7; }
ID3D12Device8 *GetReal8() const { return m_pDevice8; }
ID3D12Device9 *GetReal9() const { return m_pDevice9; }
static rdcstr GetChunkName(uint32_t idx);
D3D12ResourceManager *GetResourceManager() { return m_ResourceManager; }
D3D12ShaderCache *GetShaderCache() { return m_ShaderCache; }
+109 -2
View File
@@ -232,6 +232,47 @@ WriteSerialiser &WrappedID3D12Resource::GetThreadSerialiser()
return m_pDevice->GetThreadSerialiser();
}
size_t WrappedID3D12Resource::DeleteOverlappingAccStructsInRangeAtOffset(D3D12BufferOffset bufferOffset)
{
SCOPED_LOCK(m_accStructResourcesCS);
if(!m_accelerationStructMap.empty())
{
rdcarray<D3D12BufferOffset> toBeDeleted;
uint64_t accStructAtOffsetSize = m_accelerationStructMap[bufferOffset]->Size();
for(const rdcpair<D3D12BufferOffset, D3D12AccelerationStructure *> &accStructAtOffset :
m_accelerationStructMap)
{
if(accStructAtOffset.first == bufferOffset)
{
continue;
}
if(accStructAtOffset.first < bufferOffset &&
(accStructAtOffset.first + accStructAtOffset.second->Size()) > bufferOffset)
{
toBeDeleted.push_back(accStructAtOffset.first);
}
if(accStructAtOffset.first > bufferOffset &&
(bufferOffset + accStructAtOffsetSize) > accStructAtOffset.first)
{
toBeDeleted.push_back(accStructAtOffset.first);
}
}
for(D3D12BufferOffset deleting : toBeDeleted)
{
DeleteAccStructAtOffset(deleting);
}
return toBeDeleted.size();
}
return 0;
}
HRESULT STDMETHODCALLTYPE WrappedID3D12Resource::Map(UINT Subresource,
const D3D12_RANGE *pReadRange, void **ppData)
{
@@ -320,8 +361,8 @@ D3D12AccelerationStructure::D3D12AccelerationStructure(
D3D12BufferOffset bufferOffset,
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO &preBldInfo)
: WrappedDeviceChild12(NULL, wrappedDevice),
m_bufferRes(bufferRes),
m_bufferOffset(bufferOffset),
m_asbWrappedResource(bufferRes),
m_asbWrappedResourceBufferOffset(bufferOffset),
m_preBldInfo(preBldInfo)
{
}
@@ -330,6 +371,72 @@ D3D12AccelerationStructure::~D3D12AccelerationStructure()
{
Shutdown();
}
bool WrappedID3D12Resource::CreateAccStruct(
D3D12BufferOffset bufferOffset,
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO &preBldInfo,
D3D12AccelerationStructure **accStruct)
{
SCOPED_LOCK(m_accStructResourcesCS);
if(m_accelerationStructMap.find(bufferOffset) == m_accelerationStructMap.end())
{
m_accelerationStructMap[bufferOffset] =
new D3D12AccelerationStructure(m_pDevice, this, bufferOffset, preBldInfo);
if(accStruct)
{
*accStruct = m_accelerationStructMap[bufferOffset];
if(IsCaptureMode(m_pDevice->GetState()))
{
size_t deletedAccStructCount = DeleteOverlappingAccStructsInRangeAtOffset(bufferOffset);
RDCDEBUG("Acc structure created after deleting %u overlapping acc structure(s)",
deletedAccStructCount);
deletedAccStructCount;
}
}
return true;
}
return false;
}
bool WrappedID3D12Resource::GetAccStructIfExist(D3D12BufferOffset bufferOffset,
D3D12AccelerationStructure **accStruct)
{
SCOPED_LOCK(m_accStructResourcesCS);
bool found = false;
if(m_accelerationStructMap.find(bufferOffset) != m_accelerationStructMap.end())
{
found = true;
if(accStruct)
{
*accStruct = m_accelerationStructMap[bufferOffset];
}
}
return found;
}
bool WrappedID3D12Resource::DeleteAccStructAtOffset(D3D12BufferOffset bufferOffset)
{
SCOPED_LOCK(m_accStructResourcesCS);
D3D12AccelerationStructure *accStruct = NULL;
if(GetAccStructIfExist(bufferOffset, &accStruct))
{
if(m_accelerationStructMap[bufferOffset]->Release() == 0)
{
m_accelerationStructMap.erase(bufferOffset);
}
return true;
}
return false;
}
void WrappedID3D12Resource::RefBuffers(D3D12ResourceManager *rm)
{
// only buffers go into m_Addresses
+19 -2
View File
@@ -928,15 +928,20 @@ public:
virtual ~WrappedID3D12QueryHeap() { Shutdown(); }
};
class D3D12AccelerationStructure;
class WrappedID3D12Resource
: public WrappedDeviceChild12<ID3D12Resource, ID3D12Resource1, ID3D12Resource2>
{
static GPUAddressRangeTracker m_Addresses;
WriteSerialiser &GetThreadSerialiser();
size_t DeleteOverlappingAccStructsInRangeAtOffset(D3D12BufferOffset bufferOffset);
WrappedID3D12Heap *m_Heap = NULL;
Threading::CriticalSection m_accStructResourcesCS;
rdcflatmap<D3D12BufferOffset, D3D12AccelerationStructure *> m_accelerationStructMap;
bool m_isAccelerationStructureResource = false;
public:
@@ -963,6 +968,15 @@ public:
return this->GetResourceID();
}
bool CreateAccStruct(D3D12BufferOffset bufferOffset,
const D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO &preBldInfo,
D3D12AccelerationStructure **accStruct);
bool GetAccStructIfExist(D3D12BufferOffset bufferOffset,
D3D12AccelerationStructure **accStruct = NULL);
bool DeleteAccStructAtOffset(D3D12BufferOffset bufferOffset);
bool IsAccelerationStructureResource() const { return m_isAccelerationStructureResource; }
void MarkAsAccelerationStructureResource() { m_isAccelerationStructureResource = true; }
@@ -1281,9 +1295,12 @@ public:
~D3D12AccelerationStructure();
uint64_t Size() const { return m_preBldInfo.ResultDataMaxSizeInBytes; }
ResourceId GetBackingBufferResourceId() const { return m_asbWrappedResource->GetResourceID(); }
private:
WrappedID3D12Resource *m_bufferRes;
D3D12BufferOffset m_bufferOffset;
WrappedID3D12Resource *m_asbWrappedResource;
D3D12BufferOffset m_asbWrappedResourceBufferOffset;
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO m_preBldInfo;
};