Serialise D3D12 buffer initial contents less memory-intensivesly

This commit is contained in:
baldurk
2025-09-29 16:37:45 +01:00
parent 41e9f3c426
commit dadf4a14d5
8 changed files with 263 additions and 72 deletions
@@ -102,6 +102,10 @@ void STDMETHODCALLTYPE WrappedID3D12CommandQueue::UpdateTileMappings(
// register this heap as having been used for sparse binding
m_pDevice->AddSparseHeap(GetResID(pHeap));
// mark the heap as dirty if this is a buffer resource
if(pResource->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
GetResourceManager()->MarkDirtyResource(GetResID(pHeap));
// define macros to help provide the defaults for NULL arrays
#define REGION_START(i) \
(pResourceRegionStartCoordinates ? pResourceRegionStartCoordinates[i] \
+4
View File
@@ -537,6 +537,10 @@ bool D3D12InitParams::IsSupportedVersion(uint64_t ver)
if(ver == 0x12)
return true;
// 0x13 -> 0x14 - Reserved/placed buffers are serialised via their heaps not per-buffer
if(ver == 0x13)
return true;
return false;
}
+1 -1
View File
@@ -64,7 +64,7 @@ struct D3D12InitParams
UINT SDKVersion = 0;
// check if a frame capture section version is supported
static const uint64_t CurrentVersion = 0x13;
static const uint64_t CurrentVersion = 0x14;
static bool IsSupportedVersion(uint64_t ver);
};
@@ -257,6 +257,7 @@ bool WrappedID3D12Device::Serialise_CreateResource(
case D3D12Chunk::Device_CreateReservedResource2:
APIProps.SparseResources = true;
m_SparseResources.insert(GetResID(ret));
m_ModResources.insert(GetResID(ret));
default: break;
}
@@ -601,7 +602,20 @@ HRESULT WrappedID3D12Device::CreateResource(
if(pHeap)
record->AddParent(GetRecord(pHeap));
// all resources are marked dirty here, but we will skip the bytes of initial contents for
// sparse buffers (only the sparse tables get serialised) and initial contents entirely for
// placed buffer resources. It would be slightly better to never mark placed buffer resources
// dirty but the logic for dirtying resources with write references is generic and it's not much
// cost to skip them at initial contents prepare time.
GetResourceManager()->MarkDirtyResource(wrapped->GetResourceID());
// for placed buffers resources, the resource itself is not going to be serialised but the heap
// underlying is. Sparse resources mark the heap dirty when first bound to pages
if(desc0.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && pHeap)
{
GetResourceManager()->MarkDirtyResource(GetResID(pHeap));
GetResourceManager()->AddPlacedResource(wrapped->GetResourceID(), GetResID(pHeap));
}
}
else
{
+156 -66
View File
@@ -102,37 +102,65 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
SetInitialContents(heap->GetResourceID(), initContents);
return true;
}
else if(type == Resource_Resource)
else if(type == Resource_Resource || type == Resource_Heap)
{
WrappedID3D12Resource *r = (WrappedID3D12Resource *)res;
ID3D12Pageable *unwrappedPageable = r->UnwrappedResidencyPageable();
WrappedID3D12Resource *wrappedResource = (WrappedID3D12Resource *)res;
ID3D12Resource *unwrappedResource = NULL;
ID3D12Pageable *unwrappedPageable = NULL;
bool nonresident = false;
if(!r->IsResident())
nonresident = true;
if(type == Resource_Heap)
{
wrappedResource = NULL;
unwrappedResource = ((WrappedID3D12Heap *)res)->GetUnwrappedWholeMemBuffer();
}
else
{
unwrappedResource = wrappedResource->GetReal();
unwrappedPageable = wrappedResource->UnwrappedResidencyPageable();
D3D12_RESOURCE_DESC desc = r->GetDesc();
if(!wrappedResource->IsResident())
nonresident = true;
}
D3D12_RESOURCE_DESC desc = unwrappedResource->GetDesc();
D3D12InitialContents initContents;
Sparse::PageTable *sparseTable = NULL;
if(GetRecord(r)->sparseTable)
sparseTable = new Sparse::PageTable(*GetRecord(r)->sparseTable);
if(wrappedResource && GetRecord(wrappedResource)->sparseTable)
sparseTable = new Sparse::PageTable(*GetRecord(wrappedResource)->sparseTable);
if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
if(r->IsAccelerationStructureResource())
if(type == Resource_Resource && wrappedResource->IsAccelerationStructureResource())
{
initContents = D3D12InitialContents(D3D12InitialContents::AccelerationStructure, NULL);
SetInitialContents(GetResID(r), initContents);
SetInitialContents(GetResID(res), initContents);
return true;
}
// if this is a sparse buffer, we don't serialise its contents so just save the sparse table itself
if(sparseTable)
{
initContents = D3D12InitialContents(D3D12InitialContents::SparseOnly, NULL);
initContents.sparseTable = sparseTable;
SetInitialContents(GetResID(res), initContents);
return true;
}
// placed buffer resources do not serialise initial contents
if(type == Resource_Resource && wrappedResource->GetHeap())
{
return true;
}
D3D12_HEAP_PROPERTIES heapProps = {};
if(sparseTable == NULL)
r->GetHeapProperties(&heapProps, NULL);
unwrappedResource->GetHeapProperties(&heapProps, NULL);
HRESULT hr = S_OK;
@@ -144,21 +172,21 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
byte *buffer = AllocAlignedBuffer(RDCMAX(desc.Width, 64ULL));
byte *bufData = NULL;
hr = r->GetReal()->Map(0, NULL, (void **)&bufData);
hr = unwrappedResource->Map(0, NULL, (void **)&bufData);
if(SUCCEEDED(hr))
{
memcpy(buffer, bufData, size);
D3D12_RANGE range = {};
r->GetReal()->Unmap(0, &range);
unwrappedResource->Unmap(0, &range);
}
else
{
RDCERR("Couldn't map directly readback buffer: HRESULT: %s", ToStr(hr).c_str());
}
SetInitialContents(GetResID(r), D3D12InitialContents(buffer, size));
SetInitialContents(GetResID(res), D3D12InitialContents(buffer, size));
return true;
}
@@ -172,20 +200,23 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
if(nonresident)
m_Device->GetReal()->MakeResident(1, &unwrappedPageable);
const SubresourceStateVector &states = m_Device->GetSubresourceStates(GetResID(res));
RDCASSERT(states.size() == 1);
const SubresourceStateVector empty;
const SubresourceStateVector &states =
type == Resource_Heap ? empty : m_Device->GetSubresourceStates(GetResID(res));
RDCASSERT(type == Resource_Heap || states.size() == 1);
D3D12_RESOURCE_BARRIER barrier;
// upload heap resources can't be transitioned, and any resources in the new layouts don't
// need to either since each submit does a big flush
const bool needsTransition = !isUploadHeap && states[0].IsStates() &&
const bool needsTransition = type == Resource_Resource && !isUploadHeap &&
states[0].IsStates() &&
(states[0].ToStates() & D3D12_RESOURCE_STATE_COPY_SOURCE) == 0;
if(needsTransition)
{
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = r->GetReal();
barrier.Transition.pResource = unwrappedResource;
barrier.Transition.Subresource = (UINT)0;
barrier.Transition.StateBefore = states[0].ToStates();
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE;
@@ -199,7 +230,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
if(SUCCEEDED(hr))
{
list->CopyResource(copyDst, r->GetReal());
list->CopyResource(copyDst, unwrappedResource);
}
else
{
@@ -238,7 +269,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
ID3D12Resource *arrayTexture = NULL;
BarrierSet::AccessType accessType = BarrierSet::CopySourceAccess;
ID3D12Resource *unwrappedCopySource = r->GetReal();
ID3D12Resource *unwrappedCopySource = unwrappedResource;
bool isDepth =
IsDepthFormat(desc.Format) || (desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) != 0;
@@ -279,7 +310,8 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
BarrierSet barriers;
barriers.Configure(r, m_Device->GetSubresourceStates(GetResID(r)), accessType);
barriers.Configure(wrappedResource, m_Device->GetSubresourceStates(GetResID(wrappedResource)),
accessType);
barriers.Apply(list);
if(arrayTexture)
@@ -291,7 +323,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
m_Device->FlushLists();
// expand multisamples out to array
m_Device->GetDebugManager()->CopyTex2DMSToArray(NULL, arrayTexture, r->GetReal());
m_Device->GetDebugManager()->CopyTex2DMSToArray(NULL, arrayTexture, unwrappedResource);
// open the initial state list again for the remainder of the work
list = m_Device->GetInitialStateList();
@@ -431,7 +463,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
initContents.sparseTable = sparseTable;
SetInitialContents(GetResID(r), initContents);
SetInitialContents(GetResID(res), initContents);
return true;
}
else if(type == Resource_AccelerationStructure)
@@ -857,7 +889,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
SetInitialContents(id, D3D12InitialContents(copyheap));
}
}
else if(type == Resource_Resource)
else if(type == Resource_Resource || type == Resource_Heap)
{
byte *ResourceContents = NULL;
uint64_t ContentsLength = 0;
@@ -868,7 +900,10 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
if(IsReplayingAndReading())
{
liveRes = (ID3D12Resource *)GetLiveResource(id);
ID3D12DeviceChild *live = GetLiveResource(id);
liveRes = (ID3D12Resource *)live;
if(type == Resource_Heap)
liveRes = ((WrappedID3D12Heap *)live)->GetUnwrappedWholeMemBuffer();
}
SparseBinds *sparseBinds = NULL;
@@ -906,7 +941,8 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
mappedBuffer = (ID3D12Resource *)initial->resource;
if(initial->tag == D3D12InitialContents::AccelerationStructure)
if(initial->tag == D3D12InitialContents::AccelerationStructure ||
initial->tag == D3D12InitialContents::SparseOnly)
{
mappedBuffer = NULL;
}
@@ -943,7 +979,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
D3D12_RESOURCE_DESC resDesc = liveRes->GetDesc();
D3D12_HEAP_PROPERTIES heapProps = {};
if(!m_Device->IsSparseResource(GetResID(liveRes)))
if(!m_Device->IsSparseResource(GetLiveID(id)))
liveRes->GetHeapProperties(&heapProps, NULL);
const bool isCPUCopyHeap =
@@ -952,13 +988,25 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
heapProps.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE) &&
heapProps.MemoryPoolPreference == D3D12_MEMORY_POOL_L0;
if(((WrappedID3D12Resource *)liveRes)->IsAccelerationStructureResource())
if(type == Resource_Resource &&
((WrappedID3D12Resource *)liveRes)->IsAccelerationStructureResource())
{
mappedBuffer = NULL;
D3D12InitialContents initContents(D3D12InitialContents::AccelerationStructure, NULL);
SetInitialContents(id, initContents);
}
// from verison 0x14 onwards we don't serialise the contents of sparse resources
else if(type == Resource_Resource && sparseBinds && ser.VersionAtLeast(0x14) &&
ContentsLength == 0)
{
mappedBuffer = NULL;
D3D12InitialContents initContents(D3D12InitialContents::SparseOnly, NULL);
initContents.sparseBinds = sparseBinds;
SetInitialContents(id, initContents);
}
else if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD || isCPUCopyHeap)
{
// if destination is on the upload heap, it's impossible to copy via the device,
@@ -968,7 +1016,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
D3D12InitialContents initContents(D3D12InitialContents::Copy, type);
ResourceContents = initContents.srcData = AllocAlignedBuffer(RDCMAX(ContentsLength, 64ULL));
initContents.resourceType = Resource_Resource;
initContents.resourceType = type;
SetInitialContents(id, initContents);
}
else
@@ -1044,7 +1092,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
if(IsReplayingAndReading() && mappedBuffer)
{
D3D12InitialContents initContents(D3D12InitialContents::Copy, type);
initContents.resourceType = Resource_Resource;
initContents.resourceType = type;
initContents.resource = mappedBuffer;
initContents.sparseBinds = sparseBinds;
@@ -1066,7 +1114,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
else
{
D3D12_HEAP_PROPERTIES heapProps = {};
if(!m_Device->IsSparseResource(GetResID(liveRes)))
if(!m_Device->IsSparseResource(GetLiveID(id)))
liveRes->GetHeapProperties(&heapProps, NULL);
// if the resource is sparse, create on default heap
@@ -1657,24 +1705,39 @@ void D3D12ResourceManager::Create_InitialState(ResourceId id, ID3D12DeviceChild
// it all entirely undefined.
SetInitialContents(id, D3D12InitialContents((ID3D12DescriptorHeap *)NULL));
}
else if(type == Resource_Resource)
else if(type == Resource_Resource || type == Resource_Heap)
{
ID3D12Resource *res = ((ID3D12Resource *)live);
WrappedID3D12Resource *wrappedResource = (WrappedID3D12Resource *)res;
if(wrappedResource->IsAccelerationStructureResource())
D3D12_HEAP_PROPERTIES heapProps = {};
D3D12_RESOURCE_DESC resDesc = {};
if(type == Resource_Heap)
{
wrappedResource = NULL;
res = NULL;
resDesc = ((WrappedID3D12Heap *)live)->GetUnwrappedWholeMemBuffer()->GetDesc();
heapProps = ((WrappedID3D12Heap *)live)->GetDesc().Properties;
}
else if(wrappedResource->IsAccelerationStructureResource())
{
SetInitialContents(id, D3D12InitialContents(D3D12InitialContents::AccelerationStructure,
(ID3D12Resource *)NULL));
return;
}
else if(wrappedResource->GetHeap())
{
// don't create initial states for placed resources
return;
}
else
{
resDesc = res->GetDesc();
D3D12_RESOURCE_DESC resDesc = res->GetDesc();
D3D12_HEAP_PROPERTIES heapProps = {};
if(!m_Device->IsSparseResource(GetResID(live)))
res->GetHeapProperties(&heapProps, NULL);
if(!m_Device->IsSparseResource(GetResID(live)))
res->GetHeapProperties(&heapProps, NULL);
}
const bool isCPUCopyHeap = heapProps.Type == D3D12_HEAP_TYPE_CUSTOM &&
(heapProps.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK ||
@@ -1727,7 +1790,7 @@ void D3D12ResourceManager::Create_InitialState(ResourceId id, ID3D12DeviceChild
else
{
D3D12InitialContents initContents(D3D12InitialContents::ForceCopy, type);
initContents.resourceType = Resource_Resource;
initContents.resourceType = type;
initContents.resource = copy;
if(m_Device->IsSparseResource(GetResID(live)))
@@ -1768,7 +1831,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
srcheap->GetCPUDescriptorHandleForHeapStart(), srcheap->GetDesc().Type);
}
}
else if(type == Resource_Resource)
else if(type == Resource_Resource || type == Resource_Heap)
{
if(data.tag == D3D12InitialContents::AccelerationStructure)
return;
@@ -1778,13 +1841,32 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
if(IsActiveReplaying(m_State) && m_Device->IsReadOnlyResource(id))
{
}
else if(data.tag == D3D12InitialContents::SparseOnly)
{
if(IsLoading(m_State) || m_Device->GetQueue()->IsSparseUpdatedResource(GetResID(live)))
data.sparseBinds->Apply(m_Device, (ID3D12Resource *)live);
if(m_Device->HasFatalError())
return;
}
else if(data.tag == D3D12InitialContents::Copy || data.tag == D3D12InitialContents::ForceCopy)
{
ID3D12Resource *copyDst = (ID3D12Resource *)live;
ID3D12Resource *wrappedCopyDst = NULL;
ID3D12Resource *unwrappedCopyDst = NULL;
if(!copyDst)
if(type == Resource_Heap)
{
RDCERR("Missing copy destination in initial state apply (%p)", copyDst);
unwrappedCopyDst = ((WrappedID3D12Heap *)live)->GetUnwrappedWholeMemBuffer();
}
else
{
wrappedCopyDst = (ID3D12Resource *)live;
unwrappedCopyDst = Unwrap(wrappedCopyDst);
}
if(!unwrappedCopyDst)
{
RDCERR("Missing copy destination in initial state apply (%p)", unwrappedCopyDst);
return;
}
@@ -1799,7 +1881,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
}
else
{
copyDst->GetHeapProperties(&heapProps, NULL);
unwrappedCopyDst->GetHeapProperties(&heapProps, NULL);
}
const bool isCPUCopyHeap =
@@ -1823,11 +1905,11 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
HRESULT hr = S_OK;
D3D12_RESOURCE_DESC desc = copyDst->GetDesc();
D3D12_RESOURCE_DESC desc = unwrappedCopyDst->GetDesc();
if(desc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
hr = Unwrap(copyDst)->Map(0, NULL, (void **)&dst);
hr = unwrappedCopyDst->Map(0, NULL, (void **)&dst);
CHECK_HR(m_Device, hr);
if(FAILED(hr))
@@ -1837,10 +1919,10 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
}
if(src && dst)
memcpy(dst, src, (size_t)copyDst->GetDesc().Width);
memcpy(dst, src, (size_t)unwrappedCopyDst->GetDesc().Width);
if(dst)
Unwrap(copyDst)->Unmap(0, NULL);
unwrappedCopyDst->Unmap(0, NULL);
}
else
{
@@ -1859,9 +1941,9 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
for(UINT i = 0; i < numSubresources; i++)
{
if(desc.Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN)
hr = Unwrap(copyDst)->Map(i, NULL, NULL);
hr = unwrappedCopyDst->Map(i, NULL, NULL);
else
hr = Unwrap(copyDst)->Map(i, NULL, (void **)&dst);
hr = unwrappedCopyDst->Map(i, NULL, (void **)&dst);
CHECK_HR(m_Device, hr);
if(FAILED(hr))
@@ -1889,8 +1971,8 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
if(texPtr)
memcpy(bufPtr, texPtr, (size_t)rowsizes[i]);
else
copyDst->WriteToSubresource(i, &box, bufPtr, (UINT)rowsizes[i],
(UINT)rowsizes[i]);
unwrappedCopyDst->WriteToSubresource(i, &box, bufPtr, (UINT)rowsizes[i],
(UINT)rowsizes[i]);
bufPtr += layouts[i].Footprint.RowPitch;
if(texPtr)
@@ -1906,7 +1988,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
}
if(dst)
Unwrap(copyDst)->Unmap(i, NULL);
unwrappedCopyDst->Unmap(i, NULL);
}
delete[] layouts;
@@ -1931,26 +2013,31 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
BarrierSet barriers;
barriers.Configure(copyDst, m_Device->GetSubresourceStates(GetResID(live)),
BarrierSet::CopyDestAccess);
barriers.Apply(list);
if(type != Resource_Heap)
{
barriers.Configure(wrappedCopyDst, m_Device->GetSubresourceStates(GetResID(live)),
BarrierSet::CopyDestAccess);
barriers.Apply(list);
}
if(copyDst->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
if(unwrappedCopyDst->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
D3D12_RESOURCE_DESC srcDesc = copySrc->GetDesc();
D3D12_RESOURCE_DESC dstDesc = copyDst->GetDesc();
D3D12_RESOURCE_DESC dstDesc = unwrappedCopyDst->GetDesc();
list->CopyBufferRegion(copyDst, 0, copySrc, 0, RDCMIN(srcDesc.Width, dstDesc.Width));
Unwrap(list)->CopyBufferRegion(unwrappedCopyDst, 0, Unwrap(copySrc), 0,
RDCMIN(srcDesc.Width, dstDesc.Width));
}
else if(copyDst->GetDesc().SampleDesc.Count > 1 || data.tag == D3D12InitialContents::ForceCopy)
else if(unwrappedCopyDst->GetDesc().SampleDesc.Count > 1 ||
data.tag == D3D12InitialContents::ForceCopy)
{
// MSAA texture was pre-uploaded and decoded, just copy the texture.
// Similarly for created initial states
list->CopyResource(copyDst, copySrc);
Unwrap(list)->CopyResource(unwrappedCopyDst, Unwrap(copySrc));
}
else
{
D3D12_RESOURCE_DESC desc = copyDst->GetDesc();
D3D12_RESOURCE_DESC desc = unwrappedCopyDst->GetDesc();
UINT numSubresources = desc.MipLevels;
if(desc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D)
@@ -1995,11 +2082,11 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
D3D12_TEXTURE_COPY_LOCATION dst, src;
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dst.pResource = copyDst;
dst.pResource = unwrappedCopyDst;
dst.SubresourceIndex = i;
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
src.pResource = copySrc;
src.pResource = Unwrap(copySrc);
m_Device->GetCopyableFootprints(&desc, i, 1, offset, &src.PlacedFootprint, NULL, NULL,
&subSize);
@@ -2010,7 +2097,7 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
continue;
}
list->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
Unwrap(list)->CopyTextureRegion(&dst, 0, 0, 0, &src, NULL);
offset += subSize;
offset = AlignUp<UINT64>(offset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
@@ -2025,7 +2112,10 @@ void D3D12ResourceManager::Apply_InitialState(ID3D12DeviceChild *live, D3D12Init
}
}
barriers.Unapply(list);
if(type != Resource_Heap)
{
barriers.Unapply(list);
}
if(D3D12_Debug_SingleSubmitFlushing())
{
+44 -1
View File
@@ -717,7 +717,9 @@ struct D3D12InitialContents
// for created initial states we always have an identical resource
ForceCopy,
// for handling acceleration structures
AccelerationStructure
AccelerationStructure,
// for sparse buffers with no contents
SparseOnly,
};
D3D12InitialContents(D3D12Descriptor *d, uint32_t n) : D3D12InitialContents()
{
@@ -1486,6 +1488,44 @@ public:
D3D12GpuBufferAllocator &GetGPUBufferAllocator() { return m_GPUBufferAllocator; }
void AddPlacedResource(ResourceId resId, ResourceId heapId)
{
SCOPED_LOCK(m_PlacedLock);
m_PlacedHeapForResource[resId] = heapId;
}
void RemovePlacedResource(ResourceId resId)
{
SCOPED_LOCK(m_PlacedLock);
m_PlacedHeapForResource.erase(resId);
}
ResourceId GetPlacedHeapForResource(ResourceId resId)
{
SCOPED_LOCK(m_PlacedLock);
auto it = m_PlacedHeapForResource.find(resId);
if(it == m_PlacedHeapForResource.end())
return ResourceId();
return it->second;
}
template <typename Compose>
void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType, Compose comp)
{
ResourceManager::MarkResourceFrameReferenced(id, refType, comp);
ResourceId id2 = GetPlacedHeapForResource(id);
if(id2 != ResourceId())
ResourceManager::MarkResourceFrameReferenced(id2, refType, comp);
}
inline void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType)
{
ResourceManager::MarkResourceFrameReferenced(id, refType);
ResourceId id2 = GetPlacedHeapForResource(id);
if(id2 != ResourceId())
ResourceManager::MarkResourceFrameReferenced(id2, refType);
}
template <typename SerialiserType>
void SerialiseResourceStates(SerialiserType &ser, BarrierSet &barriers,
std::map<ResourceId, SubresourceStateVector> &states,
@@ -1517,6 +1557,9 @@ private:
D3D12RTManager *m_RTManager;
D3D12GpuBufferAllocator m_GPUBufferAllocator;
Threading::CriticalSection m_PlacedLock;
std::unordered_map<ResourceId, ResourceId> m_PlacedHeapForResource;
// dummy handle to use - starting from near highest valid pointer to minimise risk of overlap with real handles
static const uint64_t FirstDummyHandle = UINTPTR_MAX - 1024;
uint64_t m_DummyHandle = FirstDummyHandle;
@@ -159,6 +159,38 @@ D3D12AccelerationStructure::~D3D12AccelerationStructure()
Shutdown();
}
WrappedID3D12Heap::WrappedID3D12Heap(ID3D12Heap *real, WrappedID3D12Device *device)
: WrappedDeviceChild12(real, device)
{
D3D12_HEAP_DESC desc = GetDesc();
if((desc.Flags & D3D12_HEAP_FLAG_DENY_BUFFERS) == 0)
{
D3D12_RESOURCE_DESC resDesc = {};
resDesc.Width = GetDesc().SizeInBytes;
resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
resDesc.Height = 1;
resDesc.DepthOrArraySize = 1;
resDesc.MipLevels = 1;
resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resDesc.SampleDesc.Count = 1;
if(desc.Flags & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER)
resDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COMMON;
if(desc.Properties.Type == D3D12_HEAP_TYPE_UPLOAD)
state = D3D12_RESOURCE_STATE_GENERIC_READ;
else if(desc.Properties.Type == D3D12_HEAP_TYPE_READBACK)
state = D3D12_RESOURCE_STATE_COPY_DEST;
HRESULT hr =
device->GetReal()->CreatePlacedResource(real, 0, &resDesc, D3D12_RESOURCE_STATE_COMMON, NULL,
__uuidof(ID3D12Resource), (void **)&m_WholeMem);
RDCASSERT(SUCCEEDED(hr));
}
}
bool WrappedID3D12Resource::CreateAccStruct(D3D12BufferOffset bufferOffset,
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE type,
UINT64 byteSize, ResourceId id,
@@ -216,6 +248,8 @@ WrappedID3D12Resource::~WrappedID3D12Resource()
SAFE_RELEASE(it->second);
}
m_pDevice->GetResourceManager()->RemovePlacedResource(GetResourceID());
if(IsReplayMode(m_pDevice->GetState()))
m_pDevice->RemoveReplayResource(GetResourceID());
+6 -4
View File
@@ -721,6 +721,8 @@ class WrappedID3D12Heap : public WrappedDeviceChild12<ID3D12Heap, ID3D12Heap1>,
public ID3D12PageableTools
{
ID3D12PageableTools *m_Pageable = NULL;
ID3D12Resource *m_WholeMem = NULL;
public:
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12Heap);
@@ -729,12 +731,12 @@ public:
TypeEnum = Resource_Heap,
};
WrappedID3D12Heap(ID3D12Heap *real, WrappedID3D12Device *device)
: WrappedDeviceChild12(real, device)
{
}
ID3D12Resource *GetUnwrappedWholeMemBuffer() { return m_WholeMem; }
WrappedID3D12Heap(ID3D12Heap *real, WrappedID3D12Device *device);
virtual ~WrappedID3D12Heap()
{
SAFE_RELEASE(m_WholeMem);
SAFE_RELEASE(m_Pageable);
Shutdown();
}