Added ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED, POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED Code by @medranSolus
diff --git a/include/D3D12MemAlloc.h b/include/D3D12MemAlloc.h index a9d2612..95c5cc2 100644 --- a/include/D3D12MemAlloc.h +++ b/include/D3D12MemAlloc.h
@@ -836,6 +836,14 @@ */ POOL_FLAG_ALGORITHM_LINEAR = 0x1, + /** \brief Optimization, allocate MSAA textures as committed resources always. + + Specify this flag to create MSAA textures with implicit heaps, as if they were created + with flag ALLOCATION_FLAG_COMMITTED. Usage of this flags enables pool to create its heaps + on smaller alignment not suitable for MSAA textures. + */ + POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x2, + // Bit mask to extract only `ALGORITHM` bits from entire set of flags. POOL_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_LINEAR }; @@ -1007,6 +1015,14 @@ Only avaiable if `ID3D12Device8` is present. Otherwise, the flag is ignored. */ ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED = 0x4, + + /** \brief Optimization, allocate MSAA textures as committed resources always. + + Specify this flag to create MSAA textures with implicit heaps, as if they were created + with flag ALLOCATION_FLAG_COMMITTED. Usage of this flags enables all default pools + to create its heaps on smaller alignment not suitable for MSAA textures. + */ + ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x8, }; /// \brief Parameters of created Allocator object. To be used with CreateAllocator().
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp index b2b8b1c..5281201 100644 --- a/src/D3D12MemAlloc.cpp +++ b/src/D3D12MemAlloc.cpp
@@ -446,7 +446,7 @@ return (D3D12_HEAP_TYPE)(heapTypeIndex + 1); } -static UINT64 HeapFlagsToAlignment(D3D12_HEAP_FLAGS flags) +static UINT64 HeapFlagsToAlignment(D3D12_HEAP_FLAGS flags, bool denyMsaaTextures) { /* Documentation of D3D12_HEAP_DESC structure says: @@ -459,6 +459,9 @@ https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_heap_desc */ + if (denyMsaaTextures) + return D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; + const D3D12_HEAP_FLAGS denyAllTexturesFlags = D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES; const bool canContainAnyTextures = @@ -5791,7 +5794,7 @@ const UINT64 m_Size; const UINT m_Id; - HRESULT Init(ID3D12ProtectedResourceSession* pProtectedSession); + HRESULT Init(ID3D12ProtectedResourceSession* pProtectedSession, bool denyMsaaTextures); private: ID3D12Heap* m_Heap = NULL; @@ -5823,7 +5826,7 @@ BlockVector* GetBlockVector() const { return m_BlockVector; } // 'algorithm' should be one of the *_ALGORITHM_* flags in enums POOL_FLAGS or VIRTUAL_BLOCK_FLAGS - HRESULT Init(UINT32 algorithm, ID3D12ProtectedResourceSession* pProtectedSession); + HRESULT Init(UINT32 algorithm, ID3D12ProtectedResourceSession* pProtectedSession, bool denyMsaaTextures); // Validates all data structures inside this object. If not valid, returns false. bool Validate() const; @@ -5934,6 +5937,7 @@ bool explicitBlockSize, UINT64 minAllocationAlignment, UINT32 algorithm, + bool denyMsaaTextures, ID3D12ProtectedResourceSession* pProtectedSession); ~BlockVector(); @@ -5941,6 +5945,7 @@ D3D12_HEAP_FLAGS GetHeapFlags() const { return m_HeapFlags; } UINT64 GetPreferredBlockSize() const { return m_PreferredBlockSize; } UINT32 GetAlgorithm() const { return m_Algorithm; } + bool DeniesMsaaTextures() const { return m_DenyMsaaTextures; } // To be used only while the m_Mutex is locked. Used during defragmentation. size_t GetBlockCount() const { return m_Blocks.size(); } // To be used only while the m_Mutex is locked. Used during defragmentation. @@ -5998,6 +6003,7 @@ const bool m_ExplicitBlockSize; const UINT64 m_MinAllocationAlignment; const UINT32 m_Algorithm; + const bool m_DenyMsaaTextures; ID3D12ProtectedResourceSession* const m_ProtectedSession; /* There can be at most one allocation that is completely empty - a hysteresis to avoid pessimistic case of alternating creation and destruction @@ -6420,6 +6426,7 @@ const bool m_UseMutex; const bool m_AlwaysCommitted; + const bool m_MsaaAlwaysCommitted; ID3D12Device* m_Device; // AddRef #ifdef __ID3D12Device4_INTERFACE_DEFINED__ ID3D12Device4* m_Device4 = NULL; // AddRef, optional @@ -6511,6 +6518,7 @@ AllocatorPimpl::AllocatorPimpl(const ALLOCATION_CALLBACKS& allocationCallbacks, const ALLOCATOR_DESC& desc) : m_UseMutex((desc.Flags & ALLOCATOR_FLAG_SINGLETHREADED) == 0), m_AlwaysCommitted((desc.Flags & ALLOCATOR_FLAG_ALWAYS_COMMITTED) != 0), + m_MsaaAlwaysCommitted((desc.Flags & ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED) != 0), m_Device(desc.pDevice), m_Adapter(desc.pAdapter), m_PreferredBlockSize(desc.PreferredBlockSize != 0 ? desc.PreferredBlockSize : D3D12MA_DEFAULT_BLOCK_SIZE), @@ -6594,7 +6602,8 @@ SIZE_MAX, // maxBlockCount false, // explicitBlockSize D3D12MA_DEBUG_ALIGNMENT, // minAllocationAlignment - 0, // Default algorithm + 0, // Default algorithm, + m_MsaaAlwaysCommitted, NULL); // pProtectedSession // No need to call m_pBlockVectors[i]->CreateMinBlocks here, becase minBlockCount is 0. } @@ -7493,7 +7502,7 @@ { D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {}; heapAllocInfo.SizeInBytes = resourceSize; - heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags); + heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags, m_MsaaAlwaysCommitted); hr = AllocateHeap(committedAllocParams, heapAllocInfo, withinBudget, pPrivateData, ppAllocation); if (SUCCEEDED(hr)) { @@ -7608,7 +7617,7 @@ { D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {}; heapAllocInfo.SizeInBytes = resourceSize; - heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags); + heapAllocInfo.Alignment = HeapFlagsToAlignment(committedAllocParams.m_HeapFlags, m_MsaaAlwaysCommitted); hr = AllocateHeap(committedAllocParams, heapAllocInfo, withinBudget, pPrivateData, ppAllocation); if (SUCCEEDED(hr)) { @@ -7732,10 +7741,12 @@ outCommittedAllocationParams = CommittedAllocationParameters(); outPreferCommitted = false; + bool msaaAlwaysCommitted; if (allocDesc.CustomPool != NULL) { PoolPimpl* const pool = allocDesc.CustomPool->m_Pimpl; + msaaAlwaysCommitted = pool->GetBlockVector()->DeniesMsaaTextures(); outBlockVector = pool->GetBlockVector(); outCommittedAllocationParams.m_ProtectedSession = pool->GetDesc().pProtectedSession; @@ -7749,6 +7760,7 @@ { return E_INVALIDARG; } + msaaAlwaysCommitted = m_MsaaAlwaysCommitted; outCommittedAllocationParams.m_HeapProperties = StandardHeapTypeToHeapProperties(allocDesc.HeapType); outCommittedAllocationParams.m_HeapFlags = allocDesc.ExtraHeapFlags; @@ -7790,9 +7802,12 @@ } outCommittedAllocationParams.m_CanAlias = allocDesc.Flags & ALLOCATION_FLAG_CAN_ALIAS; - if (resDesc != NULL && !outPreferCommitted && PrefersCommittedAllocation(*resDesc)) + if (resDesc != NULL) { - outPreferCommitted = true; + if (resDesc->SampleDesc.Count > 1 && msaaAlwaysCommitted) + outBlockVector = NULL; + if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc)) + outPreferCommitted = true; } return (outBlockVector != NULL || outCommittedAllocationParams.m_List != NULL) ? S_OK : E_INVALIDARG; @@ -8045,14 +8060,14 @@ } } -HRESULT MemoryBlock::Init(ID3D12ProtectedResourceSession* pProtectedSession) +HRESULT MemoryBlock::Init(ID3D12ProtectedResourceSession* pProtectedSession, bool denyMsaaTextures) { D3D12MA_ASSERT(m_Heap == NULL && m_Size > 0); D3D12_HEAP_DESC heapDesc = {}; heapDesc.SizeInBytes = m_Size; heapDesc.Properties = m_HeapProps; - heapDesc.Alignment = HeapFlagsToAlignment(m_HeapFlags); + heapDesc.Alignment = HeapFlagsToAlignment(m_HeapFlags, denyMsaaTextures); heapDesc.Flags = m_HeapFlags; HRESULT hr; @@ -8102,9 +8117,9 @@ } } -HRESULT NormalBlock::Init(UINT32 algorithm, ID3D12ProtectedResourceSession* pProtectedSession) +HRESULT NormalBlock::Init(UINT32 algorithm, ID3D12ProtectedResourceSession* pProtectedSession, bool denyMsaaTextures) { - HRESULT hr = MemoryBlock::Init(pProtectedSession); + HRESULT hr = MemoryBlock::Init(pProtectedSession, denyMsaaTextures); if (FAILED(hr)) { return hr; @@ -8226,6 +8241,7 @@ bool explicitBlockSize, UINT64 minAllocationAlignment, UINT32 algorithm, + bool denyMsaaTextures, ID3D12ProtectedResourceSession* pProtectedSession) : m_hAllocator(hAllocator), m_HeapProps(heapProps), @@ -8236,6 +8252,7 @@ m_ExplicitBlockSize(explicitBlockSize), m_MinAllocationAlignment(minAllocationAlignment), m_Algorithm(algorithm), + m_DenyMsaaTextures(denyMsaaTextures), m_ProtectedSession(pProtectedSession), m_HasEmptyBlock(false), m_Blocks(hAllocator->GetAllocs()), @@ -8765,7 +8782,7 @@ m_HeapFlags, blockSize, m_NextBlockId++); - HRESULT hr = pBlock->Init(m_Algorithm, m_ProtectedSession); + HRESULT hr = pBlock->Init(m_Algorithm, m_ProtectedSession, m_DenyMsaaTextures); if (FAILED(hr)) { D3D12MA_DELETE(m_hAllocator->GetAllocs(), pBlock); @@ -9433,6 +9450,7 @@ explicitBlockSize, D3D12MA_MAX(desc.MinAllocationAlignment, (UINT64)D3D12MA_DEBUG_ALIGNMENT), desc.Flags & POOL_FLAG_ALGORITHM_MASK, + desc.Flags & POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED, desc.pProtectedSession); }
diff --git a/src/Tests.cpp b/src/Tests.cpp index 1423b5a..d57bd75 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp
@@ -1486,6 +1486,39 @@ CHECK_BOOL(aliasingRes != NULL); } +static void TestPoolMsaaTextureAsCommitted(const TestContext& ctx) +{ + wprintf(L"Test MSAA texture always as committed in pool\n"); + + D3D12MA::POOL_DESC poolDesc = {}; + poolDesc.HeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES; + poolDesc.HeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT; + poolDesc.Flags = D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED; + + ComPtr<D3D12MA::Pool> pool; + CHECK_HR(ctx.allocator->CreatePool(&poolDesc, &pool)); + + D3D12MA::ALLOCATION_DESC allocDesc = {}; + allocDesc.CustomPool = pool.Get(); + + D3D12_RESOURCE_DESC resDesc = {}; + resDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resDesc.Width = 1024; + resDesc.Height = 512; + resDesc.DepthOrArraySize = 1; + resDesc.MipLevels = 1; + resDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + resDesc.SampleDesc.Count = 2; + resDesc.SampleDesc.Quality = 0; + resDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + + ComPtr<D3D12MA::Allocation> alloc; + CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc, D3D12_RESOURCE_STATE_RENDER_TARGET, nullptr, &alloc, IID_NULL, nullptr)); + // Committed allocation should not have explicit heap + CHECK_BOOL(alloc->GetHeap() == nullptr); +} + static void TestMapping(const TestContext& ctx) { wprintf(L"Test mapping\n"); @@ -4024,6 +4057,7 @@ TestStandardCustomCommittedPlaced(ctx); TestAliasingMemory(ctx); TestAliasingImplicitCommitted(ctx); + TestPoolMsaaTextureAsCommitted(ctx); TestMapping(ctx); TestStats(ctx); TestTransfer(ctx);