From e833b3ec951b39a8110bb78c2336a9e9bb869d9d Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Thu, 22 Feb 2024 13:44:49 +0100 Subject: [PATCH] Fixed VmaDeviceMemoryBlock::Map for mapping hysteresis to work correctly when the mapping fails Also added test for it. Fixes #407 - thanks @matusfedorko --- include/vk_mem_alloc.h | 8 +++++--- src/Tests.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/include/vk_mem_alloc.h b/include/vk_mem_alloc.h index 43f87c2..f6cafb3 100644 --- a/include/vk_mem_alloc.h +++ b/include/vk_mem_alloc.h @@ -10443,11 +10443,11 @@ VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex); const uint32_t oldTotalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping(); - m_MappingHysteresis.PostMap(); if (oldTotalMapCount != 0) { - m_MapCount += count; VMA_ASSERT(m_pMappedData != VMA_NULL); + m_MappingHysteresis.PostMap(); + m_MapCount += count; if (ppData != VMA_NULL) { *ppData = m_pMappedData; @@ -10465,11 +10465,13 @@ VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void &m_pMappedData); if (result == VK_SUCCESS) { + VMA_ASSERT(m_pMappedData != VMA_NULL); + m_MappingHysteresis.PostMap(); + m_MapCount = count; if (ppData != VMA_NULL) { *ppData = m_pMappedData; } - m_MapCount = count; } return result; } diff --git a/src/Tests.cpp b/src/Tests.cpp index 061c85c..61fbd72 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp @@ -8079,6 +8079,37 @@ static void TestMappingHysteresis() vmaDestroyPool(g_hAllocator, pool); } + + // Test hysteresis working currectly in case the mapping fails. See issue #407. + { + VkBufferCreateInfo bufCreateInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO}; + bufCreateInfo.size = 1 * MEGABYTE; + bufCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + + VmaAllocationCreateInfo allocCreateInfo = {}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO; + + VkBuffer buf; + VmaAllocation alloc; + TEST(vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, + &buf, &alloc, nullptr) == VK_SUCCESS); + + VkMemoryPropertyFlags memProps = 0; + vmaGetAllocationMemoryProperties(g_hAllocator, alloc, &memProps); + + // It makes sense to test only if this buffer ended up in a non-HOST_VISIBLE memory, + // which may not be the case on some integrated graphics. + if((memProps & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0) + { + void* ptr; + for (size_t i = 0; i < 10; ++i) + { + TEST(vmaMapMemory(g_hAllocator, alloc, &ptr) == VK_ERROR_MEMORY_MAP_FAILED); + } + } + + vmaDestroyBuffer(g_hAllocator, buf, alloc); + } } void Test()