@@ -3137,7 +3137,7 @@ remove them if not needed.
31373137*/
31383138#if !defined(VMA_CONFIGURATION_USER_INCLUDES_H)
31393139 #include <cassert> // for assert
3140- #include <algorithm> // for min, max, swap
3140+ #include <algorithm> // for min, max, swap, sort
31413141 #include <mutex>
31423142#else
31433143 #include VMA_CONFIGURATION_USER_INCLUDES_H
@@ -7178,6 +7178,14 @@ void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json)
71787178
71797179#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY
71807180// Before deleting object of this class remember to call 'Destroy()'
7181+ /*
7182+ Tracks block occupancy at VkPhysicalDeviceLimits::bufferImageGranularity page boundaries.
7183+ For each granularity-sized page in a memory block, m_RegionInfo stores:
7184+ - allocCount: how many allocations touch this page as their first or last page.
7185+ - allocType: the remembered VmaSuballocationType for that page while allocCount > 0.
7186+ Only boundary pages are tracked because buffer-image granularity conflicts matter when
7187+ adjacent allocations share the same granularity page at the start or end of an allocation.
7188+ */
71817189class VmaBlockBufferImageGranularity final
71827190{
71837191public:
@@ -7200,6 +7208,21 @@ class VmaBlockBufferImageGranularity final
72007208 VkDeviceSize& inOutAllocSize,
72017209 VkDeviceSize& inOutAllocAlignment) const;
72027210
7211+ /*
7212+ Checks whether an allocation placed in a free block would conflict with existing
7213+ allocations due to buffer-image granularity requirements and, if needed, aligns the
7214+ allocation start to the next granularity page.
7215+
7216+ Parameters:
7217+ - inOutAllocOffset: candidate allocation offset inside the block; may be increased.
7218+ - allocSize: size of the allocation being placed.
7219+ - blockOffset: start offset of the free block being considered.
7220+ - blockSize: size of the free block being considered.
7221+ - allocType: VmaSuballocationType of the allocation being placed.
7222+
7223+ Returns true when the placement conflicts or no longer fits in the free block after alignment.
7224+ Returns false when the placement is valid, possibly after updating inOutAllocOffset.
7225+ */
72037226 bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,
72047227 VkDeviceSize allocSize,
72057228 VkDeviceSize blockOffset,
@@ -7288,56 +7311,62 @@ bool VmaBlockBufferImageGranularity::CheckConflictAndAlignUp(VkDeviceSize& inOut
72887311 VkDeviceSize blockSize,
72897312 VmaSuballocationType allocType) const
72907313{
7291- if (IsEnabled())
7314+ if (!IsEnabled())
7315+ return false;
7316+
7317+ uint32_t startPage = GetStartPage(inOutAllocOffset);
7318+ if (m_RegionInfo[startPage].allocCount > 0 &&
7319+ VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
72927320 {
7293- uint32_t startPage = GetStartPage(inOutAllocOffset);
7321+ inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
7322+ if (blockSize < allocSize + inOutAllocOffset - blockOffset)
7323+ return true;
7324+ startPage = GetStartPage(inOutAllocOffset);
72947325 if (m_RegionInfo[startPage].allocCount > 0 &&
72957326 VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
7296- {
7297- inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
7298- if (blockSize < allocSize + inOutAllocOffset - blockOffset)
7299- return true;
7300- ++startPage;
7301- }
7302- uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
7303- if (endPage != startPage &&
7304- m_RegionInfo[endPage].allocCount > 0 &&
7305- VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
73067327 {
73077328 return true;
73087329 }
73097330 }
7331+ uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
7332+ if (endPage != startPage &&
7333+ m_RegionInfo[endPage].allocCount > 0 &&
7334+ VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
7335+ {
7336+ return true;
7337+ }
7338+
73107339 return false;
73117340}
73127341
73137342void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size)
73147343{
7315- if (IsEnabled())
7316- {
7317- uint32_t startPage = GetStartPage(offset);
7318- AllocPage(m_RegionInfo[startPage], allocType);
7344+ if (!IsEnabled())
7345+ return;
73197346
7320- uint32_t endPage = GetEndPage(offset, size);
7321- if (startPage != endPage)
7322- AllocPage(m_RegionInfo[endPage], allocType);
7323- }
7347+ uint32_t startPage = GetStartPage(offset);
7348+ AllocPage(m_RegionInfo[startPage], allocType);
7349+
7350+ uint32_t endPage = GetEndPage(offset, size);
7351+ if (startPage != endPage)
7352+ AllocPage(m_RegionInfo[endPage], allocType);
73247353}
73257354
73267355void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size)
73277356{
7328- if (IsEnabled())
7357+ if (!IsEnabled())
7358+ return;
7359+
7360+ uint32_t startPage = GetStartPage(offset);
7361+ --m_RegionInfo[startPage].allocCount;
7362+ if (m_RegionInfo[startPage].allocCount == 0)
7363+ m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
7364+ uint32_t endPage = GetEndPage(offset, size);
7365+ if (startPage != endPage)
73297366 {
7330- uint32_t startPage = GetStartPage(offset);
7331- --m_RegionInfo[startPage].allocCount;
7332- if (m_RegionInfo[startPage].allocCount == 0)
7333- m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
7334- uint32_t endPage = GetEndPage(offset, size);
7335- if (startPage != endPage)
7336- {
7337- --m_RegionInfo[endPage].allocCount;
7338- if (m_RegionInfo[endPage].allocCount == 0)
7339- m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
7340- }
7367+ --m_RegionInfo[endPage].allocCount;
7368+ if (m_RegionInfo[endPage].allocCount == 0)
7369+ m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
73417370 }
73427371}
73437372
@@ -7362,36 +7391,38 @@ VmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity
73627391bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx,
73637392 VkDeviceSize offset, VkDeviceSize size) const
73647393{
7365- if (IsEnabled())
7366- {
7367- uint32_t start = GetStartPage(offset);
7368- ++ctx.pageAllocs[start];
7369- VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
7394+ if (!IsEnabled())
7395+ return true;
73707396
7371- uint32_t end = GetEndPage(offset, size);
7372- if (start != end)
7373- {
7374- ++ctx.pageAllocs[end];
7375- VMA_VALIDATE(m_RegionInfo[end].allocCount > 0);
7376- }
7397+ uint32_t start = GetStartPage(offset);
7398+ ++ctx.pageAllocs[start];
7399+ VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
7400+
7401+ uint32_t end = GetEndPage(offset, size);
7402+ if (start != end)
7403+ {
7404+ ++ctx.pageAllocs[end];
7405+ VMA_VALIDATE(m_RegionInfo[end].allocCount > 0);
73777406 }
7407+
73787408 return true;
73797409}
73807410
73817411bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const
73827412{
7413+ if (!IsEnabled())
7414+ return true;
7415+
73837416 // Check proper page structure
7384- if (IsEnabled())
7385- {
7386- VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
7417+ VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
73877418
7388- for (uint32_t page = 0; page < m_RegionCount; ++page)
7389- {
7390- VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
7391- }
7392- vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount);
7393- ctx.pageAllocs = VMA_NULL;
7419+ for (uint32_t page = 0; page < m_RegionCount; ++page)
7420+ {
7421+ VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
73947422 }
7423+ vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount);
7424+ ctx.pageAllocs = VMA_NULL;
7425+
73957426 return true;
73967427}
73977428
0 commit comments