mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git
synced 2024-11-24 21:10:11 +00:00
Fix for case when a large allocation is made with ALLOCATION_FLAG_CAN_ALIAS
Code by @medranSolus
This commit is contained in:
parent
98218850d6
commit
10bff5ec74
@ -635,7 +635,7 @@ private:
|
||||
AllocHandle GetAllocHandle() const;
|
||||
NormalBlock* GetBlock();
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
void SetResource(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc);
|
||||
void SetResourcePointer(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc);
|
||||
void FreeName();
|
||||
|
||||
D3D12MA_CLASS_NO_COPY(Allocation)
|
||||
|
@ -5906,6 +5906,7 @@ struct CommittedAllocationParameters
|
||||
D3D12_HEAP_PROPERTIES m_HeapProperties = {};
|
||||
D3D12_HEAP_FLAGS m_HeapFlags = D3D12_HEAP_FLAG_NONE;
|
||||
ID3D12ProtectedResourceSession* m_ProtectedSession = NULL;
|
||||
bool m_CanAlias = false;
|
||||
|
||||
bool IsValid() const { return m_List != NULL; }
|
||||
};
|
||||
@ -7485,13 +7486,42 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
|
||||
{
|
||||
D3D12MA_ASSERT(committedAllocParams.IsValid());
|
||||
|
||||
HRESULT hr;
|
||||
ID3D12Resource* res = NULL;
|
||||
// Allocate aliasing memory with explicit heap
|
||||
if (committedAllocParams.m_CanAlias)
|
||||
{
|
||||
D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {};
|
||||
heapAllocInfo.SizeInBytes = resourceSize;
|
||||
heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags);
|
||||
hr = AllocateHeap(committedAllocParams, heapAllocInfo, withinBudget, pPrivateData, ppAllocation);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_Device->CreatePlacedResource((*ppAllocation)->GetHeap(), 0,
|
||||
pResourceDesc, InitialResourceState,
|
||||
pOptimizedClearValue, D3D12MA_IID_PPV_ARGS(&res));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (ppvResource != NULL)
|
||||
hr = res->QueryInterface(riidResource, ppvResource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(*ppAllocation)->SetResourcePointer(res, pResourceDesc);
|
||||
return hr;
|
||||
}
|
||||
res->Release();
|
||||
}
|
||||
FreeHeapMemory(*ppAllocation);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (withinBudget &&
|
||||
!NewAllocationWithinBudget(committedAllocParams.m_HeapProperties.Type, resourceSize))
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
ID3D12Resource* res = NULL;
|
||||
/* D3D12 ERROR:
|
||||
* ID3D12Device::CreateCommittedResource:
|
||||
* When creating a committed resource, D3D12_HEAP_FLAGS must not have either
|
||||
@ -7502,7 +7532,6 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
|
||||
*
|
||||
* [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]
|
||||
*/
|
||||
HRESULT hr;
|
||||
#ifdef __ID3D12Device4_INTERFACE_DEFINED__
|
||||
if (m_Device4)
|
||||
{
|
||||
@ -7538,7 +7567,7 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
|
||||
const BOOL wasZeroInitialized = TRUE;
|
||||
Allocation* alloc = m_AllocationObjectAllocator.Allocate(this, resourceSize, pResourceDesc->Alignment, wasZeroInitialized);
|
||||
alloc->InitCommitted(committedAllocParams.m_List);
|
||||
alloc->SetResource(res, pResourceDesc);
|
||||
alloc->SetResourcePointer(res, pResourceDesc);
|
||||
alloc->SetPrivateData(pPrivateData);
|
||||
|
||||
*ppAllocation = alloc;
|
||||
@ -7572,14 +7601,43 @@ HRESULT AllocatorPimpl::AllocateCommittedResource2(
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
ID3D12Resource* res = NULL;
|
||||
// Allocate aliasing memory with explicit heap
|
||||
if (committedAllocParams.m_CanAlias)
|
||||
{
|
||||
D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {};
|
||||
heapAllocInfo.SizeInBytes = resourceSize;
|
||||
heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags);
|
||||
hr = AllocateHeap(committedAllocParams, heapAllocInfo, withinBudget, pPrivateData, ppAllocation);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = m_Device8->CreatePlacedResource1((*ppAllocation)->GetHeap(), 0,
|
||||
pResourceDesc, InitialResourceState,
|
||||
pOptimizedClearValue, D3D12MA_IID_PPV_ARGS(&res));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (ppvResource != NULL)
|
||||
hr = res->QueryInterface(riidResource, ppvResource);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(*ppAllocation)->SetResourcePointer(res, pResourceDesc);
|
||||
return hr;
|
||||
}
|
||||
res->Release();
|
||||
}
|
||||
FreeHeapMemory(*ppAllocation);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (withinBudget &&
|
||||
!NewAllocationWithinBudget(committedAllocParams.m_HeapProperties.Type, resourceSize))
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
ID3D12Resource* res = NULL;
|
||||
HRESULT hr = m_Device8->CreateCommittedResource2(
|
||||
hr = m_Device8->CreateCommittedResource2(
|
||||
&committedAllocParams.m_HeapProperties,
|
||||
committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, // D3D12 ERROR: ID3D12Device::CreateCommittedResource: When creating a committed resource, D3D12_HEAP_FLAGS must not have either D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES, nor D3D12_HEAP_FLAG_DENY_BUFFERS set. These flags will be set automatically to correspond with the committed resource type. [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]
|
||||
pResourceDesc, InitialResourceState,
|
||||
@ -7595,7 +7653,7 @@ HRESULT AllocatorPimpl::AllocateCommittedResource2(
|
||||
const BOOL wasZeroInitialized = TRUE;
|
||||
Allocation* alloc = m_AllocationObjectAllocator.Allocate(this, resourceSize, pResourceDesc->Alignment, wasZeroInitialized);
|
||||
alloc->InitCommitted(committedAllocParams.m_List);
|
||||
alloc->SetResource(res, pResourceDesc);
|
||||
alloc->SetResourcePointer(res, pResourceDesc);
|
||||
alloc->SetPrivateData(pPrivateData);
|
||||
|
||||
*ppAllocation = alloc;
|
||||
@ -7726,10 +7784,11 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
{
|
||||
outBlockVector = NULL;
|
||||
}
|
||||
if ((allocDesc.Flags & (ALLOCATION_FLAG_NEVER_ALLOCATE | ALLOCATION_FLAG_CAN_ALIAS)) != 0)
|
||||
if ((allocDesc.Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)
|
||||
{
|
||||
outCommittedAllocationParams.m_List = NULL;
|
||||
}
|
||||
outCommittedAllocationParams.m_CanAlias = allocDesc.Flags & ALLOCATION_FLAG_CAN_ALIAS;
|
||||
|
||||
if (resDesc != NULL && !outPreferCommitted && PrefersCommittedAllocation(*resDesc))
|
||||
{
|
||||
@ -8340,7 +8399,7 @@ HRESULT BlockVector::CreateResource(
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(*ppAllocation)->SetResource(res, &resourceDesc);
|
||||
(*ppAllocation)->SetResourcePointer(res, &resourceDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -8393,7 +8452,7 @@ HRESULT BlockVector::CreateResource2(
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
(*ppAllocation)->SetResource(res, &resourceDesc);
|
||||
(*ppAllocation)->SetResourcePointer(res, &resourceDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -9701,7 +9760,7 @@ NormalBlock* Allocation::GetBlock()
|
||||
}
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
void Allocation::SetResource(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc)
|
||||
void Allocation::SetResourcePointer(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc)
|
||||
{
|
||||
D3D12MA_ASSERT(m_Resource == NULL && pResourceDesc);
|
||||
m_Resource = resource;
|
||||
|
@ -1457,6 +1457,35 @@ static void TestAliasingMemory(const TestContext& ctx)
|
||||
// You can use res1 and res2, but not at the same time!
|
||||
}
|
||||
|
||||
static void TestAliasingImplicitCommitted(const TestContext& ctx)
|
||||
{
|
||||
wprintf(L"Test aliasing implicit dedicated\n");
|
||||
|
||||
// The buffer will be large enough to be allocated as committed.
|
||||
// We still need it to have an explicit heap to be able to alias.
|
||||
|
||||
D3D12_RESOURCE_DESC resDesc = {};
|
||||
FillResourceDescForBuffer(resDesc, 300 * MEGABYTE);
|
||||
|
||||
D3D12MA::ALLOCATION_DESC allocDesc = {};
|
||||
allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
|
||||
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_CAN_ALIAS;
|
||||
|
||||
ComPtr<D3D12MA::Allocation> alloc;
|
||||
CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
|
||||
&alloc, IID_NULL, NULL));
|
||||
CHECK_BOOL(alloc != NULL && alloc->GetHeap() != NULL);
|
||||
|
||||
resDesc.Width = 200 * MEGABYTE;
|
||||
ComPtr<ID3D12Resource> aliasingRes;
|
||||
CHECK_HR(ctx.allocator->CreateAliasingResource(alloc.Get(),
|
||||
0, // AllocationLocalOffset
|
||||
&resDesc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&aliasingRes)));
|
||||
CHECK_BOOL(aliasingRes != NULL);
|
||||
}
|
||||
|
||||
static void TestMapping(const TestContext& ctx)
|
||||
{
|
||||
wprintf(L"Test mapping\n");
|
||||
@ -3994,6 +4023,7 @@ static void TestGroupBasics(const TestContext& ctx)
|
||||
TestCustomHeaps(ctx);
|
||||
TestStandardCustomCommittedPlaced(ctx);
|
||||
TestAliasingMemory(ctx);
|
||||
TestAliasingImplicitCommitted(ctx);
|
||||
TestMapping(ctx);
|
||||
TestStats(ctx);
|
||||
TestTransfer(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user