Skip to content

Commit 10bff5e

Browse files
Fix for case when a large allocation is made with ALLOCATION_FLAG_CAN_ALIAS
Code by @medranSolus
1 parent 9821885 commit 10bff5e

3 files changed

Lines changed: 105 additions & 16 deletions

File tree

include/D3D12MemAlloc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ class D3D12MA_API Allocation : public IUnknownImpl
635635
AllocHandle GetAllocHandle() const;
636636
NormalBlock* GetBlock();
637637
template<typename D3D12_RESOURCE_DESC_T>
638-
void SetResource(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc);
638+
void SetResourcePointer(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc);
639639
void FreeName();
640640

641641
D3D12MA_CLASS_NO_COPY(Allocation)

src/D3D12MemAlloc.cpp

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5906,6 +5906,7 @@ struct CommittedAllocationParameters
59065906
D3D12_HEAP_PROPERTIES m_HeapProperties = {};
59075907
D3D12_HEAP_FLAGS m_HeapFlags = D3D12_HEAP_FLAG_NONE;
59085908
ID3D12ProtectedResourceSession* m_ProtectedSession = NULL;
5909+
bool m_CanAlias = false;
59095910

59105911
bool IsValid() const { return m_List != NULL; }
59115912
};
@@ -7485,13 +7486,42 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
74857486
{
74867487
D3D12MA_ASSERT(committedAllocParams.IsValid());
74877488

7489+
HRESULT hr;
7490+
ID3D12Resource* res = NULL;
7491+
// Allocate aliasing memory with explicit heap
7492+
if (committedAllocParams.m_CanAlias)
7493+
{
7494+
D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {};
7495+
heapAllocInfo.SizeInBytes = resourceSize;
7496+
heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags);
7497+
hr = AllocateHeap(committedAllocParams, heapAllocInfo, withinBudget, pPrivateData, ppAllocation);
7498+
if (SUCCEEDED(hr))
7499+
{
7500+
hr = m_Device->CreatePlacedResource((*ppAllocation)->GetHeap(), 0,
7501+
pResourceDesc, InitialResourceState,
7502+
pOptimizedClearValue, D3D12MA_IID_PPV_ARGS(&res));
7503+
if (SUCCEEDED(hr))
7504+
{
7505+
if (ppvResource != NULL)
7506+
hr = res->QueryInterface(riidResource, ppvResource);
7507+
if (SUCCEEDED(hr))
7508+
{
7509+
(*ppAllocation)->SetResourcePointer(res, pResourceDesc);
7510+
return hr;
7511+
}
7512+
res->Release();
7513+
}
7514+
FreeHeapMemory(*ppAllocation);
7515+
}
7516+
return hr;
7517+
}
7518+
74887519
if (withinBudget &&
74897520
!NewAllocationWithinBudget(committedAllocParams.m_HeapProperties.Type, resourceSize))
74907521
{
74917522
return E_OUTOFMEMORY;
74927523
}
74937524

7494-
ID3D12Resource* res = NULL;
74957525
/* D3D12 ERROR:
74967526
* ID3D12Device::CreateCommittedResource:
74977527
* When creating a committed resource, D3D12_HEAP_FLAGS must not have either
@@ -7502,15 +7532,14 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
75027532
*
75037533
* [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]
75047534
*/
7505-
HRESULT hr;
75067535
#ifdef __ID3D12Device4_INTERFACE_DEFINED__
75077536
if (m_Device4)
75087537
{
7509-
hr = m_Device4->CreateCommittedResource1(
7510-
&committedAllocParams.m_HeapProperties,
7511-
committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS,
7512-
pResourceDesc, InitialResourceState,
7513-
pOptimizedClearValue, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&res));
7538+
hr = m_Device4->CreateCommittedResource1(
7539+
&committedAllocParams.m_HeapProperties,
7540+
committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS,
7541+
pResourceDesc, InitialResourceState,
7542+
pOptimizedClearValue, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&res));
75147543
}
75157544
else
75167545
#endif
@@ -7538,7 +7567,7 @@ HRESULT AllocatorPimpl::AllocateCommittedResource(
75387567
const BOOL wasZeroInitialized = TRUE;
75397568
Allocation* alloc = m_AllocationObjectAllocator.Allocate(this, resourceSize, pResourceDesc->Alignment, wasZeroInitialized);
75407569
alloc->InitCommitted(committedAllocParams.m_List);
7541-
alloc->SetResource(res, pResourceDesc);
7570+
alloc->SetResourcePointer(res, pResourceDesc);
75427571
alloc->SetPrivateData(pPrivateData);
75437572

75447573
*ppAllocation = alloc;
@@ -7572,14 +7601,43 @@ HRESULT AllocatorPimpl::AllocateCommittedResource2(
75727601
return E_NOINTERFACE;
75737602
}
75747603

7604+
HRESULT hr;
7605+
ID3D12Resource* res = NULL;
7606+
// Allocate aliasing memory with explicit heap
7607+
if (committedAllocParams.m_CanAlias)
7608+
{
7609+
D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {};
7610+
heapAllocInfo.SizeInBytes = resourceSize;
7611+
heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags);
7612+
hr = AllocateHeap(committedAllocParams, heapAllocInfo, withinBudget, pPrivateData, ppAllocation);
7613+
if (SUCCEEDED(hr))
7614+
{
7615+
hr = m_Device8->CreatePlacedResource1((*ppAllocation)->GetHeap(), 0,
7616+
pResourceDesc, InitialResourceState,
7617+
pOptimizedClearValue, D3D12MA_IID_PPV_ARGS(&res));
7618+
if (SUCCEEDED(hr))
7619+
{
7620+
if (ppvResource != NULL)
7621+
hr = res->QueryInterface(riidResource, ppvResource);
7622+
if (SUCCEEDED(hr))
7623+
{
7624+
(*ppAllocation)->SetResourcePointer(res, pResourceDesc);
7625+
return hr;
7626+
}
7627+
res->Release();
7628+
}
7629+
FreeHeapMemory(*ppAllocation);
7630+
}
7631+
return hr;
7632+
}
7633+
75757634
if (withinBudget &&
75767635
!NewAllocationWithinBudget(committedAllocParams.m_HeapProperties.Type, resourceSize))
75777636
{
75787637
return E_OUTOFMEMORY;
75797638
}
75807639

7581-
ID3D12Resource* res = NULL;
7582-
HRESULT hr = m_Device8->CreateCommittedResource2(
7640+
hr = m_Device8->CreateCommittedResource2(
75837641
&committedAllocParams.m_HeapProperties,
75847642
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]
75857643
pResourceDesc, InitialResourceState,
@@ -7595,7 +7653,7 @@ HRESULT AllocatorPimpl::AllocateCommittedResource2(
75957653
const BOOL wasZeroInitialized = TRUE;
75967654
Allocation* alloc = m_AllocationObjectAllocator.Allocate(this, resourceSize, pResourceDesc->Alignment, wasZeroInitialized);
75977655
alloc->InitCommitted(committedAllocParams.m_List);
7598-
alloc->SetResource(res, pResourceDesc);
7656+
alloc->SetResourcePointer(res, pResourceDesc);
75997657
alloc->SetPrivateData(pPrivateData);
76007658

76017659
*ppAllocation = alloc;
@@ -7726,10 +7784,11 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
77267784
{
77277785
outBlockVector = NULL;
77287786
}
7729-
if ((allocDesc.Flags & (ALLOCATION_FLAG_NEVER_ALLOCATE | ALLOCATION_FLAG_CAN_ALIAS)) != 0)
7787+
if ((allocDesc.Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)
77307788
{
77317789
outCommittedAllocationParams.m_List = NULL;
77327790
}
7791+
outCommittedAllocationParams.m_CanAlias = allocDesc.Flags & ALLOCATION_FLAG_CAN_ALIAS;
77337792

77347793
if (resDesc != NULL && !outPreferCommitted && PrefersCommittedAllocation(*resDesc))
77357794
{
@@ -8340,7 +8399,7 @@ HRESULT BlockVector::CreateResource(
83408399
}
83418400
if (SUCCEEDED(hr))
83428401
{
8343-
(*ppAllocation)->SetResource(res, &resourceDesc);
8402+
(*ppAllocation)->SetResourcePointer(res, &resourceDesc);
83448403
}
83458404
else
83468405
{
@@ -8393,7 +8452,7 @@ HRESULT BlockVector::CreateResource2(
83938452
}
83948453
if (SUCCEEDED(hr))
83958454
{
8396-
(*ppAllocation)->SetResource(res, &resourceDesc);
8455+
(*ppAllocation)->SetResourcePointer(res, &resourceDesc);
83978456
}
83988457
else
83998458
{
@@ -9701,7 +9760,7 @@ NormalBlock* Allocation::GetBlock()
97019760
}
97029761

97039762
template<typename D3D12_RESOURCE_DESC_T>
9704-
void Allocation::SetResource(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc)
9763+
void Allocation::SetResourcePointer(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc)
97059764
{
97069765
D3D12MA_ASSERT(m_Resource == NULL && pResourceDesc);
97079766
m_Resource = resource;

src/Tests.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,35 @@ static void TestAliasingMemory(const TestContext& ctx)
14571457
// You can use res1 and res2, but not at the same time!
14581458
}
14591459

1460+
static void TestAliasingImplicitCommitted(const TestContext& ctx)
1461+
{
1462+
wprintf(L"Test aliasing implicit dedicated\n");
1463+
1464+
// The buffer will be large enough to be allocated as committed.
1465+
// We still need it to have an explicit heap to be able to alias.
1466+
1467+
D3D12_RESOURCE_DESC resDesc = {};
1468+
FillResourceDescForBuffer(resDesc, 300 * MEGABYTE);
1469+
1470+
D3D12MA::ALLOCATION_DESC allocDesc = {};
1471+
allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
1472+
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_CAN_ALIAS;
1473+
1474+
ComPtr<D3D12MA::Allocation> alloc;
1475+
CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc,
1476+
D3D12_RESOURCE_STATE_GENERIC_READ, NULL,
1477+
&alloc, IID_NULL, NULL));
1478+
CHECK_BOOL(alloc != NULL && alloc->GetHeap() != NULL);
1479+
1480+
resDesc.Width = 200 * MEGABYTE;
1481+
ComPtr<ID3D12Resource> aliasingRes;
1482+
CHECK_HR(ctx.allocator->CreateAliasingResource(alloc.Get(),
1483+
0, // AllocationLocalOffset
1484+
&resDesc,
1485+
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&aliasingRes)));
1486+
CHECK_BOOL(aliasingRes != NULL);
1487+
}
1488+
14601489
static void TestMapping(const TestContext& ctx)
14611490
{
14621491
wprintf(L"Test mapping\n");
@@ -3994,6 +4023,7 @@ static void TestGroupBasics(const TestContext& ctx)
39944023
TestCustomHeaps(ctx);
39954024
TestStandardCustomCommittedPlaced(ctx);
39964025
TestAliasingMemory(ctx);
4026+
TestAliasingImplicitCommitted(ctx);
39974027
TestMapping(ctx);
39984028
TestStats(ctx);
39994029
TestTransfer(ctx);

0 commit comments

Comments
 (0)