diff --git a/include/D3D12MemAlloc.h b/include/D3D12MemAlloc.h index 6e3ecf7..a9d2612 100644 --- a/include/D3D12MemAlloc.h +++ b/include/D3D12MemAlloc.h @@ -635,7 +635,7 @@ private: AllocHandle GetAllocHandle() const; NormalBlock* GetBlock(); template - 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) diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp index 6939696..82b824b 100644 --- a/src/D3D12MemAlloc.cpp +++ b/src/D3D12MemAlloc.cpp @@ -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,15 +7532,14 @@ HRESULT AllocatorPimpl::AllocateCommittedResource( * * [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS] */ - HRESULT hr; #ifdef __ID3D12Device4_INTERFACE_DEFINED__ if (m_Device4) { - hr = m_Device4->CreateCommittedResource1( - &committedAllocParams.m_HeapProperties, - committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, - pResourceDesc, InitialResourceState, - pOptimizedClearValue, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&res)); + hr = m_Device4->CreateCommittedResource1( + &committedAllocParams.m_HeapProperties, + committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, + pResourceDesc, InitialResourceState, + pOptimizedClearValue, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&res)); } else #endif @@ -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 -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; diff --git a/src/Tests.cpp b/src/Tests.cpp index 9d8755a..1423b5a 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp @@ -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 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 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);