VmaBlockMetadata_Buddy: Added respecting of allocation alignment.
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 9286c5c..9f9a6da 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -4168,6 +4168,23 @@
     assert(res == VK_SUCCESS);

     bufInfo.push_back(newBufInfo);

 

+    // Test some small allocation with alignment requirement.

+    {

+        VkMemoryRequirements memReq;

+        memReq.alignment = 256;

+        memReq.memoryTypeBits = UINT32_MAX;

+        memReq.size = 32;

+

+        newBufInfo.Buffer = VK_NULL_HANDLE;

+        res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo,

+            &newBufInfo.Allocation, &allocInfo);

+        assert(res == VK_SUCCESS);

+        assert(allocInfo.offset % memReq.alignment == 0);

+        bufInfo.push_back(newBufInfo);

+    }

+

+    //SaveAllocatorStatsToFile(L"TEST.json");

+

     VmaPoolStats stats = {};

     vmaGetPoolStats(g_hAllocator, pool, &stats);

     int DBG = 0; // Set breakpoint here to inspect `stats`.

diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h
index 41a5a92..a11e654 100644
--- a/src/vk_mem_alloc.h
+++ b/src/vk_mem_alloc.h
@@ -9400,14 +9400,19 @@
     const uint32_t targetLevel = AllocSizeToLevel(allocSize);

     for(uint32_t level = targetLevel + 1; level--; )

     {

-        if(m_FreeList[level].front != VMA_NULL)

+        for(Node* freeNode = m_FreeList[level].front;

+            freeNode != VMA_NULL;

+            freeNode = freeNode->free.next)

         {

-            pAllocationRequest->offset = m_FreeList[level].front->offset;

-            pAllocationRequest->sumFreeSize = LevelToNodeSize(level);

-            pAllocationRequest->sumItemSize = 0;

-            pAllocationRequest->itemsToMakeLostCount = 0;

-            pAllocationRequest->customData = (void*)(uintptr_t)level;

-            return true;

+            if(freeNode->offset % allocAlignment == 0)

+            {

+                pAllocationRequest->offset = freeNode->offset;

+                pAllocationRequest->sumFreeSize = LevelToNodeSize(level);

+                pAllocationRequest->sumItemSize = 0;

+                pAllocationRequest->itemsToMakeLostCount = 0;

+                pAllocationRequest->customData = (void*)(uintptr_t)level;

+                return true;

+            }

         }

     }

 

@@ -9444,10 +9449,14 @@
 {

     const uint32_t targetLevel = AllocSizeToLevel(allocSize);

     uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;

-    VMA_ASSERT(m_FreeList[currLevel].front != VMA_NULL);

+    

     Node* currNode = m_FreeList[currLevel].front;

-    VMA_ASSERT(currNode->type == Node::TYPE_FREE);

-    VMA_ASSERT(currNode->offset == request.offset);

+    VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);

+    while(currNode->offset != request.offset)

+    {

+        currNode = currNode->free.next;

+        VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);

+    }

     

     // Go down, splitting free nodes.

     while(currLevel < targetLevel)

@@ -9484,10 +9493,17 @@
         //m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.

         ++currLevel;

         currNode = m_FreeList[currLevel].front;

+

+        /*

+        We can be sure that currNode, as left child of node previously split,

+        also fullfills the alignment requirement.

+        */

     }

 

     // Remove from free list.

-    VMA_ASSERT(currLevel == targetLevel && currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);

+    VMA_ASSERT(currLevel == targetLevel &&

+        currNode != VMA_NULL &&

+        currNode->type == Node::TYPE_FREE);

     RemoveFromFreeList(currLevel, currNode);

 

     // Convert to allocation node.