Fixed VmaDeviceMemoryBlock::Map for mapping hysteresis to work correctly when the mapping fails

Also added test for it.
Fixes #407 - thanks @matusfedorko
This commit is contained in:
Adam Sawicki 2024-02-22 13:44:49 +01:00
parent 2f4a2d24cf
commit e833b3ec95
2 changed files with 36 additions and 3 deletions

View File

@ -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;
}

View File

@ -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()