From daa6a551f8461e001afaa0005cdd8c4cef6f93d1 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Tue, 25 Jun 2019 15:26:37 +0200 Subject: [PATCH] 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. --- src/Tests.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/vk_mem_alloc.h | 11 ++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) 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 @@ static void TestMapping() } } +// 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 @@ void Test() 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 @@ VkResult VmaAllocator_T::AllocateMemory( 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);