Fix VmaAllocator_T::AllocateMemory for case when VMA_ALLOCATION_CREATE_MAPPED_BIT is used with custom memory pool created in memory type that is not VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT

Also add test for it - function TestDeviceLocalMapped.
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 4d6ed51..8e9b66b 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -4107,6 +4107,51 @@
     }

 }

 

+// Test CREATE_MAPPED with required DEVICE_LOCAL. There was a bug with it.

+static void TestDeviceLocalMapped()

+{

+    VkResult res;

+

+    for(uint32_t testIndex = 0; testIndex < 3; ++testIndex)

+    {

+        VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };

+        bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;

+        bufCreateInfo.size = 4096;

+

+        VmaPool pool = VK_NULL_HANDLE;

+        VmaAllocationCreateInfo allocCreateInfo = {};

+        allocCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

+        allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;

+        if(testIndex == 2)

+        {

+            VmaPoolCreateInfo poolCreateInfo = {};

+            res = vmaFindMemoryTypeIndexForBufferInfo(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &poolCreateInfo.memoryTypeIndex);

+            TEST(res == VK_SUCCESS);

+            res = vmaCreatePool(g_hAllocator, &poolCreateInfo, &pool);

+            TEST(res == VK_SUCCESS);

+            allocCreateInfo.pool = pool;

+        }

+        else if(testIndex == 1)

+        {

+            allocCreateInfo.flags |= VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;

+        }

+

+        VkBuffer buf = VK_NULL_HANDLE;

+        VmaAllocation alloc = VK_NULL_HANDLE;

+        VmaAllocationInfo allocInfo = {};

+        res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);

+        TEST(res == VK_SUCCESS && alloc);

+

+        VkMemoryPropertyFlags memTypeFlags = 0;

+        vmaGetMemoryTypeProperties(g_hAllocator, allocInfo.memoryType, &memTypeFlags);

+        const bool shouldBeMapped = (memTypeFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;

+        TEST((allocInfo.pMappedData != nullptr) == shouldBeMapped);

+

+        vmaDestroyBuffer(g_hAllocator, buf, alloc);

+        vmaDestroyPool(g_hAllocator, pool);

+    }

+}

+

 static void TestMappingMultithreaded()

 {

     wprintf(L"Testing mapping multithreaded...\n");

@@ -5206,6 +5251,7 @@
     TestAllocationsInitialization();

 #endif

     TestMapping();

+    TestDeviceLocalMapped();

     TestMappingMultithreaded();

     TestLinearAllocator();

     ManuallyTestLinearAllocator();

diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h
index 66b5c07..204f002 100644
--- a/src/vk_mem_alloc.h
+++ b/src/vk_mem_alloc.h
@@ -14812,11 +14812,20 @@
         const VkDeviceSize alignmentForPool = VMA_MAX(

             vkMemReq.alignment,

             GetMemoryTypeMinAlignment(createInfo.pool->m_BlockVector.GetMemoryTypeIndex()));

+

+        VmaAllocationCreateInfo createInfoForPool = createInfo;

+        // If memory type is not HOST_VISIBLE, disable MAPPED.

+        if((createInfoForPool.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&

+            (m_MemProps.memoryTypes[createInfo.pool->m_BlockVector.GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)

+        {

+            createInfoForPool.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;

+        }

+

         return createInfo.pool->m_BlockVector.Allocate(

             m_CurrentFrameIndex.load(),

             vkMemReq.size,

             alignmentForPool,

-            createInfo,

+            createInfoForPool,

             suballocType,

             allocationCount,

             pAllocations);