Fixed VmaDeviceMemoryBlock::Map for mapping hysteresis to work correctly when the mapping fails
Also added test for it.
Fixes #407 - thanks @matusfedorko
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 @@
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 @@
&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 @@
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()