Add Allocation::CreateAliasingResource

This commit is contained in:
Adam Sawicki 2020-03-25 17:41:35 +01:00
parent 329246a969
commit 11f5b8471e
3 changed files with 111 additions and 11 deletions

View File

@ -2456,6 +2456,15 @@ public:
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 @@ HRESULT AllocatorPimpl::CreateResource(
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 @@ HRESULT AllocatorPimpl::CreateResource(
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 @@ HRESULT AllocatorPimpl::AllocateMemory(
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::AllocateMemory(
}
}
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 @@ HRESULT Allocator::AllocateMemory(
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

View File

@ -833,6 +833,37 @@ public:
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 @@ public:
/// 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);

View File

@ -449,9 +449,9 @@ static void TestAliasingMemory(const TestContext& ctx)
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 @@ static void TestAliasingMemory(const TestContext& ctx)
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