From fa745a58b22d021760653005fded1e5dc3581747 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Sat, 6 Jun 2026 13:56:42 +0100 Subject: [PATCH] 3rdparty: Update D3D12MA to v3.2.0 --- .../d3d12memalloc/include/D3D12MemAlloc.h | 15 +- 3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp | 306 ++++++++++++++---- 2 files changed, 261 insertions(+), 60 deletions(-) diff --git a/3rdparty/d3d12memalloc/include/D3D12MemAlloc.h b/3rdparty/d3d12memalloc/include/D3D12MemAlloc.h index 32fe908c24..a6b1a1e50b 100644 --- a/3rdparty/d3d12memalloc/include/D3D12MemAlloc.h +++ b/3rdparty/d3d12memalloc/include/D3D12MemAlloc.h @@ -24,7 +24,7 @@ /** \mainpage D3D12 Memory Allocator -Version 3.1.0 (2026-02-23) +Version 3.2.0 (2026-06-05) Copyright (c) 2019-2026 Advanced Micro Devices, Inc. All rights reserved. \n License: MIT @@ -889,10 +889,17 @@ enum POOL_FLAGS */ POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x2, /** Every allocation made in this pool will be created as a committed resource - will have its own memory block. - + There is also an equivalent flag for the entire allocator: D3D12MA::ALLOCATOR_FLAG_ALWAYS_COMMITTED. */ POOL_FLAG_ALWAYS_COMMITTED = 0x4, + /** Disables tight resource alignment for all resources created from this pool. + + When tight alignment is supported and enabled for the allocator, resources created from custom pools + normally use it automatically. Specify this flag to restore pre-tight-alignment behavior for this pool: + tight alignment won't be requested and small buffers may again be preferred as committed resources. + */ + POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT = 0x8, // Bit mask to extract only `ALGORITHM` bits from entire set of flags. POOL_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_LINEAR @@ -1114,7 +1121,8 @@ enum ALLOCATOR_FLAGS It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME. If the tight resource alignment feature is used by the library (which happens automatically whenever supported, - unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), then small buffers are not preferred as committed. + unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT or + #POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT on a custom pool), then small buffers are not preferred as committed. Long story short, you don't need to specify any of these flags. The library chooses the most optimal method automatically. */ @@ -2892,6 +2900,7 @@ as it is no longer needed. You can check if the tight alignment it is available in the current system by calling D3D12MA::Allocator::IsTightAlignmentSupported(). You can tell the library to not use it by specifying D3D12MA::ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT. +Custom pools can opt out independently by specifying D3D12MA::POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT. Typically, you don't need to do any of those. The library automatically aligns all buffers to at least 256 B, even when the system supports smaller alignment. diff --git a/3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp b/3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp index 6c90ae4990..18c7350d71 100644 --- a/3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp +++ b/3rdparty/d3d12memalloc/src/D3D12MemAlloc.cpp @@ -163,6 +163,14 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs. #endif #endif +#ifndef D3D12MA_OPTIONS4_SUPPORTED + #ifdef __ID3D12Device5_INTERFACE_DEFINED__ + #define D3D12MA_OPTIONS4_SUPPORTED 1 + #else + #define D3D12MA_OPTIONS4_SUPPORTED 0 + #endif +#endif + #ifndef D3D12MA_DEBUG_LOG #define D3D12MA_DEBUG_LOG(format, ...) /* @@ -703,6 +711,13 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format) case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: case DXGI_FORMAT_X24_TYPELESS_G8_UINT: return 32; + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return 32; case DXGI_FORMAT_R8G8_TYPELESS: case DXGI_FORMAT_R8G8_UNORM: case DXGI_FORMAT_R8G8_UINT: @@ -717,6 +732,9 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format) case DXGI_FORMAT_R16_SNORM: case DXGI_FORMAT_R16_SINT: return 16; + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + return 16; case DXGI_FORMAT_R8_TYPELESS: case DXGI_FORMAT_R8_UNORM: case DXGI_FORMAT_R8_UINT: @@ -767,46 +785,175 @@ static ResourceClass ResourceDescToResourceClass(const D3D12_RESOURCE_DESC_T& re (resDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0; return isRenderTargetOrDepthStencil ? ResourceClass::RT_DS_Texture : ResourceClass::Non_RT_DS_Texture; } + +static bool ResourceDimensionIsTexture(D3D12_RESOURCE_DIMENSION dimension) +{ + return dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D || + dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D || + dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D; +} + +static bool ResourceFlagsContainRenderTargetOrDepthStencil(D3D12_RESOURCE_FLAGS flags) +{ + return (flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0; +} -// This algorithm is overly conservative. +struct SmallAlignmentTileShape +{ + UINT Width; + UINT Height; + UINT Depth; +}; + +static bool GetSmallAlignmentTileShape( + D3D12_RESOURCE_DIMENSION dimension, + bool isMsaa, + UINT bitsPerUnit, + SmallAlignmentTileShape& outTileShape) +{ + if (isMsaa) + { + if (dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D) + return false; + + switch (bitsPerUnit) + { + case 8: outTileShape = { 256, 256, 1 }; return true; + case 16: outTileShape = { 256, 128, 1 }; return true; + case 32: outTileShape = { 128, 128, 1 }; return true; + case 64: outTileShape = { 128, 64, 1 }; return true; + case 128: outTileShape = { 64, 64, 1 }; return true; + case 256: outTileShape = { 64, 32, 1 }; return true; + case 512: outTileShape = { 32, 32, 1 }; return true; + case 1024: outTileShape = { 32, 16, 1 }; return true; + case 2048: outTileShape = { 16, 16, 1 }; return true; + default: return false; + } + } + + switch (dimension) + { + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + switch (bitsPerUnit) + { + case 8: outTileShape = { 4096, 1, 1 }; return true; + case 16: outTileShape = { 2048, 1, 1 }; return true; + case 32: outTileShape = { 1024, 1, 1 }; return true; + case 64: outTileShape = { 512, 1, 1 }; return true; + case 128: outTileShape = { 256, 1, 1 }; return true; + default: return false; + } + + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + switch (bitsPerUnit) + { + case 8: outTileShape = { 64, 64, 1 }; return true; + case 16: outTileShape = { 64, 32, 1 }; return true; + case 32: outTileShape = { 32, 32, 1 }; return true; + case 64: outTileShape = { 32, 16, 1 }; return true; + case 128: outTileShape = { 16, 16, 1 }; return true; + default: return false; + } + + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + // 4 KB counterparts of the documented 64 KB volume-tile shapes. + switch (bitsPerUnit) + { + case 8: outTileShape = { 16, 16, 16 }; return true; + case 16: outTileShape = { 16, 16, 8 }; return true; + case 32: outTileShape = { 16, 8, 8 }; return true; + case 64: outTileShape = { 8, 8, 8 }; return true; + case 128: outTileShape = { 8, 8, 4 }; return true; + default: return false; + } + + default: + return false; + } +} + +// This algorithm is overly conservative and applies only to the legacy small-alignment heuristic path. template static bool CanUseSmallAlignment(const D3D12_RESOURCE_DESC_T& resourceDesc) { - if (resourceDesc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D) + if (resourceDesc.SampleDesc.Count == 0 || + resourceDesc.Layout != D3D12_TEXTURE_LAYOUT_UNKNOWN || + resourceDesc.Width > UINT_MAX) + { return false; - if ((resourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0) + } + + const bool isMsaa = resourceDesc.SampleDesc.Count > 1; + const bool isRtDs = ResourceFlagsContainRenderTargetOrDepthStencil(resourceDesc.Flags); + if (isMsaa && !isRtDs) + { return false; - if (resourceDesc.SampleDesc.Count > 1) - return false; - if (resourceDesc.DepthOrArraySize != 1) + } + if (!isMsaa && + isRtDs) + { return false; + } UINT sizeX = (UINT)resourceDesc.Width; - UINT sizeY = resourceDesc.Height; - UINT bitsPerPixel = GetBitsPerPixel(resourceDesc.Format); - if (bitsPerPixel == 0) + UINT sizeY = 1; + UINT sizeZ = 1; + UINT bitsPerUnit = GetBitsPerPixel(resourceDesc.Format); + if (bitsPerUnit == 0) return false; - if (IsFormatCompressed(resourceDesc.Format)) + switch (resourceDesc.Dimension) { - sizeX = DivideRoundingUp(sizeX, 4u); - sizeY = DivideRoundingUp(sizeY, 4u); - bitsPerPixel *= 16; + case D3D12_RESOURCE_DIMENSION_TEXTURE1D: + if (isMsaa) + return false; + // For 1D arrays, small-alignment eligibility depends on the mip0 slice size, not array size. + if (IsFormatCompressed(resourceDesc.Format)) + return false; + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE2D: + // For 2D arrays, small-alignment eligibility depends on mip0 width/height, not array size. + sizeY = resourceDesc.Height; + if (isMsaa && IsFormatCompressed(resourceDesc.Format)) + return false; + if (IsFormatCompressed(resourceDesc.Format)) + { + sizeX = DivideRoundingUp(sizeX, 4u); + sizeY = DivideRoundingUp(sizeY, 4u); + bitsPerUnit *= 16; + } + break; + + case D3D12_RESOURCE_DIMENSION_TEXTURE3D: + if (isMsaa) + return false; + sizeY = resourceDesc.Height; + sizeZ = resourceDesc.DepthOrArraySize; + if (IsFormatCompressed(resourceDesc.Format)) + { + sizeX = DivideRoundingUp(sizeX, 4u); + sizeY = DivideRoundingUp(sizeY, 4u); + bitsPerUnit *= 16; + } + break; + + default: + return false; } - UINT tileSizeX = 0, tileSizeY = 0; - switch (bitsPerPixel) - { - case 8: tileSizeX = 64; tileSizeY = 64; break; - case 16: tileSizeX = 64; tileSizeY = 32; break; - case 32: tileSizeX = 32; tileSizeY = 32; break; - case 64: tileSizeX = 32; tileSizeY = 16; break; - case 128: tileSizeX = 16; tileSizeY = 16; break; - default: return false; - } + bitsPerUnit *= resourceDesc.SampleDesc.Count; - const UINT tileCount = DivideRoundingUp(sizeX, tileSizeX) * DivideRoundingUp(sizeY, tileSizeY); - return tileCount <= 16; + SmallAlignmentTileShape tileShape = {}; + if (!GetSmallAlignmentTileShape(resourceDesc.Dimension, isMsaa, bitsPerUnit, tileShape)) + return false; + + const UINT64 tileCount = + UINT64(DivideRoundingUp(sizeX, tileShape.Width)) * + UINT64(DivideRoundingUp(sizeY, tileShape.Height)) * + UINT64(DivideRoundingUp(sizeZ, tileShape.Depth)); + // Non-MSAA compares 64 KB against 4 KB tiles => 16 pages. MSAA compares 4 MB against 64 KB tiles => 64 pages. + return tileCount <= (isMsaa ? 64 : 16); } static bool ValidateAllocateMemoryParameters( @@ -5988,6 +6135,7 @@ public: BOOL IsCacheCoherentUMA() const { return m_D3D12Architecture.CacheCoherentUMA; } bool SupportsResourceHeapTier2() const { return m_D3D12Options.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; } bool IsGPUUploadHeapSupported() const { return m_GPUUploadHeapSupported != FALSE; } + bool IsMsaa64KBAlignedTextureSupported() const { return m_MSAA64KBAlignedTextureSupported != FALSE; } bool IsTightAlignmentSupported() const { return m_TightAlignmentSupported != FALSE; } bool IsTightAlignmentEnabled() const { return IsTightAlignmentSupported() && m_UseTightAlignment; } bool UseMutex() const { return m_UseMutex; } @@ -6076,7 +6224,7 @@ private: const bool m_UseMutex; const bool m_AlwaysCommitted; const bool m_MsaaAlwaysCommitted; - bool m_PreferSmallBuffersCommitted; + const bool m_PreferSmallBuffersCommitted; const bool m_UseTightAlignment; bool m_DefaultPoolsNotZeroed = false; ID3D12Device* m_Device; // AddRef @@ -6105,6 +6253,7 @@ private: DXGI_ADAPTER_DESC m_AdapterDesc; D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options; BOOL m_GPUUploadHeapSupported = FALSE; + BOOL m_MSAA64KBAlignedTextureSupported = FALSE; BOOL m_TightAlignmentSupported = FALSE; D3D12_FEATURE_DATA_ARCHITECTURE m_D3D12Architecture; AllocationObjectAllocator m_AllocationObjectAllocator; @@ -6121,7 +6270,7 @@ private: */ template bool PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc, - ALLOCATION_FLAGS strategy); + ALLOCATION_FLAGS strategy, bool useTightAlignment) const; // Allocates and registers new committed resource with implicit heap, as dedicated allocation. // Creates and returns Allocation object and optionally D3D12 resource. @@ -6141,6 +6290,7 @@ private: template HRESULT CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize, const D3D12_RESOURCE_DESC_T* resDesc, // Optional + bool useTightAlignment, BlockVector*& outBlockVector, CommittedAllocationParameters& outCommittedAllocationParams, bool& outPreferCommitted); // Returns UINT32_MAX if index cannot be calculcated. @@ -6174,7 +6324,10 @@ private: template HRESULT GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc, UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats, - D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const; + D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo, + bool useTightAlignment) const; + + bool IsTightAlignmentEnabled(const ALLOCATION_DESC& allocDesc) const; bool NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size); @@ -6277,6 +6430,17 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) } #endif // #if D3D12MA_OPTIONS16_SUPPORTED +#if D3D12MA_OPTIONS4_SUPPORTED + { + D3D12_FEATURE_DATA_D3D12_OPTIONS4 options4 = {}; + hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4, &options4, sizeof(options4)); + if (SUCCEEDED(hr)) + { + m_MSAA64KBAlignedTextureSupported = options4.MSAA64KBAlignedTextureSupported; + } + } +#endif // #if D3D12MA_OPTIONS4_SUPPORTED + #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED { D3D12_FEATURE_DATA_TIGHT_ALIGNMENT tightAlignment = {}; @@ -6285,13 +6449,6 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) { m_TightAlignmentSupported = tightAlignment.SupportTier >= D3D12_TIGHT_ALIGNMENT_TIER_1; - // If tight alignment is supported (checked by the code above) and wasn't disabled by the developer - // (with ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), disable the preference for creating small buffers as committed, - // as if ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED was specified. - if (IsTightAlignmentEnabled()) - { - m_PreferSmallBuffersCommitted = false; - } } } #endif // #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED @@ -6490,6 +6647,7 @@ HRESULT AllocatorPimpl::CreateResource( } HRESULT hr = E_NOINTERFACE; + const bool useTightAlignment = IsTightAlignmentEnabled(*pAllocDesc); CREATE_RESOURCE_PARAMS finalCreateParams = createParams; D3D12_RESOURCE_DESC finalResourceDesc; #ifdef __ID3D12Device8_INTERFACE_DEFINED__ @@ -6500,7 +6658,7 @@ HRESULT AllocatorPimpl::CreateResource( { finalResourceDesc = *createParams.GetResourceDesc(); finalCreateParams.AccessResourceDesc() = &finalResourceDesc; - hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo); + hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo, useTightAlignment); } #ifdef __ID3D12Device8_INTERFACE_DEFINED__ else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1) @@ -6509,7 +6667,7 @@ HRESULT AllocatorPimpl::CreateResource( { finalResourceDesc1 = *createParams.GetResourceDesc1(); finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1; - hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo); + hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo, useTightAlignment); } } #endif @@ -6521,7 +6679,7 @@ HRESULT AllocatorPimpl::CreateResource( finalResourceDesc1 = *createParams.GetResourceDesc1(); finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1; hr = GetResourceAllocationInfo(finalResourceDesc1, - createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo); + createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo, useTightAlignment); } } #endif @@ -6547,14 +6705,14 @@ HRESULT AllocatorPimpl::CreateResource( if (createParams.Variant >= CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1) { hr = CalcAllocationParams(*pAllocDesc, resAllocInfo.SizeInBytes, - createParams.GetResourceDesc1(), + createParams.GetResourceDesc1(), useTightAlignment, blockVector, committedAllocationParams, preferCommitted); } else #endif { hr = CalcAllocationParams(*pAllocDesc, resAllocInfo.SizeInBytes, - createParams.GetResourceDesc(), + createParams.GetResourceDesc(), useTightAlignment, blockVector, committedAllocationParams, preferCommitted); } if (FAILED(hr)) @@ -6601,6 +6759,7 @@ HRESULT AllocatorPimpl::AllocateMemory( bool preferCommitted = false; HRESULT hr = CalcAllocationParams(*pAllocDesc, pAllocInfo->SizeInBytes, NULL, // pResDesc + false, // useTightAlignment - irrelevant for AllocateMemory blockVector, committedAllocationParams, preferCommitted); if (FAILED(hr)) return hr; @@ -6649,7 +6808,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource( { finalResourceDesc = *createParams.GetResourceDesc(); finalCreateParams.AccessResourceDesc() = &finalResourceDesc; - hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo); + hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo, IsTightAlignmentEnabled()); } #ifdef __ID3D12Device8_INTERFACE_DEFINED__ else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1) @@ -6658,7 +6817,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource( { finalResourceDesc1 = *createParams.GetResourceDesc1(); finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1; - hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo); + hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo, IsTightAlignmentEnabled()); } } #endif @@ -6670,7 +6829,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource( finalResourceDesc1 = *createParams.GetResourceDesc1(); finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1; hr = GetResourceAllocationInfo(finalResourceDesc1, - createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo); + createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo, IsTightAlignmentEnabled()); } } #endif @@ -7305,13 +7464,14 @@ void AllocatorPimpl::FreeStatsString(WCHAR* pStatsString) template bool AllocatorPimpl::PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc, - ALLOCATION_FLAGS strategy) + ALLOCATION_FLAGS strategy, bool useTightAlignment) const { // Prefer creating small buffers <= 32 KB as committed, because drivers pack them better, // while placed buffers require 64 KB alignment. if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && resourceDesc.Width <= D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT / 2 && strategy != ALLOCATION_FLAG_STRATEGY_MIN_TIME && // Creating as committed would be slower. + !useTightAlignment && m_PreferSmallBuffersCommitted) { return true; @@ -7526,7 +7686,7 @@ HRESULT AllocatorPimpl::AllocateHeap( template HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize, - const D3D12_RESOURCE_DESC_T* resDesc, + const D3D12_RESOURCE_DESC_T* resDesc, bool useTightAlignment, BlockVector*& outBlockVector, CommittedAllocationParameters& outCommittedAllocationParams, bool& outPreferCommitted) { outBlockVector = NULL; @@ -7599,7 +7759,7 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U { if (resDesc->SampleDesc.Count > 1 && msaaAlwaysCommitted) outBlockVector = NULL; - if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc, allocDesc.Flags & ALLOCATION_FLAG_STRATEGY_MASK)) + if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc, allocDesc.Flags & ALLOCATION_FLAG_STRATEGY_MASK, useTightAlignment)) outPreferCommitted = true; } @@ -7810,12 +7970,13 @@ template HRESULT AllocatorPimpl::GetResourceAllocationInfo( D3D12_RESOURCE_DESC_T& inOutResourceDesc, UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats, - D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const + D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo, + bool useTightAlignment) const { #ifdef __ID3D12Device1_INTERFACE_DEFINED__ #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED - if (IsTightAlignmentEnabled()) + if (useTightAlignment) { // Don't allow USE_TIGHT_ALIGNMENT together with ALLOW_CROSS_ADAPTER as there is a D3D Debug Layer error: // D3D12 ERROR: ID3D12Device::GetResourceAllocationInfo: D3D12_RESOURCE_DESC::Flag D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT will be ignored since D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER is set. [ STATE_CREATION ERROR #599: CREATERESOURCE_INVALIDMISCFLAGS] @@ -7839,7 +8000,7 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo( */ if (inOutResourceDesc.Alignment == 0 && inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && - !IsTightAlignmentEnabled()) + !useTightAlignment) { outAllocInfo = { AlignUp(inOutResourceDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT), // SizeInBytes @@ -7852,16 +8013,33 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo( HRESULT hr = S_OK; #if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT - if (inOutResourceDesc.Alignment == 0 && - (inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) == 0 && - (inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D || - inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D || - inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) && - (inOutResourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) == 0 + bool trySmallAlignment = false; + + if (inOutResourceDesc.Alignment == 0 + && (inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) == 0 + && inOutResourceDesc.Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN + && ResourceDimensionIsTexture(inOutResourceDesc.Dimension)) + { + // MSAA texture. + if(inOutResourceDesc.SampleDesc.Count > 1) + { + trySmallAlignment = IsMsaa64KBAlignedTextureSupported() + && ResourceFlagsContainRenderTargetOrDepthStencil(inOutResourceDesc.Flags) + && inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D; + } + // Non-MSAA texture. + else + { + trySmallAlignment = !ResourceFlagsContainRenderTargetOrDepthStencil(inOutResourceDesc.Flags); + } + } + #if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT == 1 - && CanUseSmallAlignment(inOutResourceDesc) + if(trySmallAlignment) + trySmallAlignment = CanUseSmallAlignment(inOutResourceDesc); #endif - ) + + if (trySmallAlignment) { /* The algorithm here is based on Microsoft sample: "Small Resources Sample" @@ -7886,6 +8064,20 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo( inOutResourceDesc, NumCastableFormats, pCastableFormats, outAllocInfo); } +bool AllocatorPimpl::IsTightAlignmentEnabled(const ALLOCATION_DESC& allocDesc) const +{ + if (!IsTightAlignmentEnabled()) + return false; + + if (allocDesc.CustomPool != NULL && + (allocDesc.CustomPool->m_Pimpl->GetDesc().Flags & POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT) != 0) + { + return false; + } + + return true; +} + bool AllocatorPimpl::NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size) { Budget budget = {};