Add Allocation::CreateAliasingResource
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index 7e8b2a4..cbe5d24 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -2456,6 +2456,15 @@
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation);
+ HRESULT CreateAliasingResource(
+ Allocation* pAllocation,
+ UINT64 AllocationLocalOffset,
+ const D3D12_RESOURCE_DESC* pResourceDesc,
+ D3D12_RESOURCE_STATES InitialResourceState,
+ const D3D12_CLEAR_VALUE *pOptimizedClearValue,
+ REFIID riidResource,
+ void** ppvResource);
+
// Unregisters allocation from the collection of dedicated allocations.
// Allocation object must be deleted externally afterwards.
void FreeCommittedMemory(Allocation* allocation);
@@ -3742,6 +3751,12 @@
REFIID riidResource,
void** ppvResource)
{
+ *ppAllocation = NULL;
+ if(ppvResource)
+ {
+ *ppvResource = NULL;
+ }
+
if(pAllocDesc->HeapType != D3D12_HEAP_TYPE_DEFAULT &&
pAllocDesc->HeapType != D3D12_HEAP_TYPE_UPLOAD &&
pAllocDesc->HeapType != D3D12_HEAP_TYPE_READBACK)
@@ -3751,11 +3766,6 @@
ALLOCATION_DESC finalAllocDesc = *pAllocDesc;
- if(ppvResource)
- {
- *ppvResource = NULL;
- }
-
D3D12_RESOURCE_DESC resourceDesc2 = *pResourceDesc;
D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = GetResourceAllocationInfo(resourceDesc2);
resAllocInfo.Alignment = D3D12MA_MAX<UINT64>(resAllocInfo.Alignment, D3D12MA_DEBUG_ALIGNMENT);
@@ -3857,6 +3867,8 @@
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation)
{
+ *ppAllocation = NULL;
+
if(pAllocDesc->HeapType != D3D12_HEAP_TYPE_DEFAULT &&
pAllocDesc->HeapType != D3D12_HEAP_TYPE_UPLOAD &&
pAllocDesc->HeapType != D3D12_HEAP_TYPE_READBACK)
@@ -3908,6 +3920,44 @@
}
}
+HRESULT AllocatorPimpl::CreateAliasingResource(
+ Allocation* pAllocation,
+ UINT64 AllocationLocalOffset,
+ const D3D12_RESOURCE_DESC* pResourceDesc,
+ D3D12_RESOURCE_STATES InitialResourceState,
+ const D3D12_CLEAR_VALUE *pOptimizedClearValue,
+ REFIID riidResource,
+ void** ppvResource)
+{
+ *ppvResource = NULL;
+
+ D3D12_RESOURCE_DESC resourceDesc2 = *pResourceDesc;
+ D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = GetResourceAllocationInfo(resourceDesc2);
+ resAllocInfo.Alignment = D3D12MA_MAX<UINT64>(resAllocInfo.Alignment, D3D12MA_DEBUG_ALIGNMENT);
+ D3D12MA_ASSERT(IsPow2(resAllocInfo.Alignment));
+ D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);
+
+ ID3D12Heap* const existingHeap = pAllocation->GetHeap();
+ const UINT64 existingOffset = pAllocation->GetOffset();
+ const UINT64 existingSize = pAllocation->GetSize();
+ const UINT64 newOffset = existingOffset + AllocationLocalOffset;
+
+ if(AllocationLocalOffset + resAllocInfo.SizeInBytes > existingSize ||
+ newOffset % resAllocInfo.Alignment != 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ return m_Device->CreatePlacedResource(
+ existingHeap,
+ newOffset,
+ &resourceDesc2,
+ InitialResourceState,
+ pOptimizedClearValue,
+ riidResource,
+ ppvResource);
+}
+
bool AllocatorPimpl::PrefersCommittedAllocation(const D3D12_RESOURCE_DESC& resourceDesc)
{
// Intentional. It may change in the future.
@@ -4879,6 +4929,24 @@
return m_Pimpl->AllocateMemory(pAllocDesc, pAllocInfo, ppAllocation);
}
+HRESULT Allocator::CreateAliasingResource(
+ Allocation* pAllocation,
+ UINT64 AllocationLocalOffset,
+ const D3D12_RESOURCE_DESC* pResourceDesc,
+ D3D12_RESOURCE_STATES InitialResourceState,
+ const D3D12_CLEAR_VALUE *pOptimizedClearValue,
+ REFIID riidResource,
+ void** ppvResource)
+{
+ if(!pAllocation || !pResourceDesc || riidResource == IID_NULL || !ppvResource)
+ {
+ D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::CreateAliasingResource.");
+ return E_INVALIDARG;
+ }
+ D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
+ return m_Pimpl->CreateAliasingResource(pAllocation, AllocationLocalOffset, pResourceDesc, InitialResourceState, pOptimizedClearValue, riidResource, ppvResource);
+}
+
void Allocator::SetCurrentFrameIndex(UINT frameIndex)
{
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
diff --git a/src/D3D12MemAlloc.h b/src/D3D12MemAlloc.h
index c440e3f..9bdcd5d 100644
--- a/src/D3D12MemAlloc.h
+++ b/src/D3D12MemAlloc.h
@@ -833,6 +833,37 @@
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation);
+ /** \brief Creates a new resource in place of an existing allocation. This is useful for memory aliasing.
+
+ \param pAllocation Existing allocation indicating the memory where the new resource should be created.
+ It can be created using D3D12MA::Allocator::CreateResource and already have a resource bound to it,
+ or can be a raw memory allocated with D3D12MA::Allocator::AllocateMemory.
+ It must not be created as committed so that `ID3D12Heap` is available and not implicit.
+ \param AllocationLocalOffset Additional offset in bytes to be applied when allocating the resource.
+ Local from the start of `pAllocation`, not the beginning of the whole `ID3D12Heap`!
+ If the new resource should start from the beginning of the `pAllocation` it should be 0.
+ \param pResourceDesc Description of the new resource to be created.
+ \param InitialResourceState
+ \param pOptimizedClearValue
+ \param riidResource
+ \param[out] ppvResource Returns pointer to the new resource.
+ The resource is not bound with `pAllocation`.
+ This pointer must not be null - you must get the resource pointer and `Release` it when no longer needed.
+
+ Memory requirements of the new resource are checked for validation.
+ If its size exceeds the end of `pAllocation` or required alignment is not fulfilled
+ considering `pAllocation->GetOffset() + AllocationLocalOffset`, the function
+ returns `E_INVALIDARG`.
+ */
+ HRESULT CreateAliasingResource(
+ Allocation* pAllocation,
+ UINT64 AllocationLocalOffset,
+ const D3D12_RESOURCE_DESC* pResourceDesc,
+ D3D12_RESOURCE_STATES InitialResourceState,
+ const D3D12_CLEAR_VALUE *pOptimizedClearValue,
+ REFIID riidResource,
+ void** ppvResource);
+
/** \brief Sets the index of the current frame.
This function is used to set the frame index in the allocator when a new game frame begins.
@@ -858,6 +889,7 @@
/// Builds and returns statistics as a string in JSON format.
/** @param[out] ppStatsString Must be freed using Allocator::FreeStatsString.
+ @param DetailedMap `TRUE` to include full list of allocations (can make the string quite long), `FALSE` to only return statistics.
*/
void BuildStatsString(WCHAR** ppStatsString, BOOL DetailedMap);
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 2c1bfb3..954caed 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -449,9 +449,9 @@
CHECK_BOOL(allocPtr != NULL && allocPtr->GetHeap() != NULL);
ID3D12Resource* resPtr = NULL;
- CHECK_HR( ctx.device->CreatePlacedResource(
- alloc->GetHeap(),
- alloc->GetOffset(),
+ CHECK_HR( ctx.allocator->CreateAliasingResource(
+ alloc.get(),
+ 0, // AllocationLocalOffset
&resourceDesc1,
D3D12_RESOURCE_STATE_COMMON,
NULL, // pOptimizedClearValue
@@ -459,9 +459,9 @@
CComPtr<ID3D12Resource> res1(resPtr);
CHECK_BOOL(resPtr != NULL);
- CHECK_HR( ctx.device->CreatePlacedResource(
- alloc->GetHeap(),
- alloc->GetOffset(),
+ CHECK_HR( ctx.allocator->CreateAliasingResource(
+ alloc.get(),
+ 0, // AllocationLocalOffset
&resourceDesc2,
D3D12_RESOURCE_STATE_COMMON,
NULL, // pOptimizedClearValue