From 370ab184f8f553d181c854137ed1f5b4916cc551 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Thu, 8 Nov 2018 16:31:00 +0100 Subject: [PATCH] Changed functions to validate and return VK_ERROR_VALIDATION_FAILED_EXT when trying to allocate memory of size 0, create buffer with size 0, or image with one of the dimensions 0. That's because vkCreateBuffer returns VK_SUCCESS for buffer with size = 0, so VMA then proceeded to allocation of size 0, which is a critical error, checked by an assert, but apparently some users don't enable asserts in VMA. Added tests: function TestInvalidAllocations. --- src/Tests.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++ src/vk_mem_alloc.h | 18 ++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/Tests.cpp b/src/Tests.cpp index ebd7366..e339f9c 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp @@ -1195,6 +1195,56 @@ static void TestUserData() } } +static void TestInvalidAllocations() +{ + VkResult res; + + VmaAllocationCreateInfo allocCreateInfo = {}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; + + // Try to allocate 0 bytes. + { + VkMemoryRequirements memReq = {}; + memReq.size = 0; // !!! + memReq.alignment = 4; + memReq.memoryTypeBits = UINT32_MAX; + VmaAllocation alloc = VK_NULL_HANDLE; + res = vmaAllocateMemory(g_hAllocator, &memReq, &allocCreateInfo, &alloc, nullptr); + TEST(res == VK_ERROR_VALIDATION_FAILED_EXT && alloc == VK_NULL_HANDLE); + } + + // Try to create buffer with size = 0. + { + VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + bufCreateInfo.size = 0; // !!! + VkBuffer buf = VK_NULL_HANDLE; + VmaAllocation alloc = VK_NULL_HANDLE; + res = vmaCreateBuffer(g_hAllocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr); + TEST(res == VK_ERROR_VALIDATION_FAILED_EXT && buf == VK_NULL_HANDLE && alloc == VK_NULL_HANDLE); + } + + // Try to create image with one dimension = 0. + { + VkImageCreateInfo imageCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = VK_FORMAT_B8G8R8A8_UNORM; + imageCreateInfo.extent.width = 128; + imageCreateInfo.extent.height = 0; // !!! + imageCreateInfo.extent.depth = 1; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR; + imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; + VkImage image = VK_NULL_HANDLE; + VmaAllocation alloc = VK_NULL_HANDLE; + res = vmaCreateImage(g_hAllocator, &imageCreateInfo, &allocCreateInfo, &image, &alloc, nullptr); + TEST(res == VK_ERROR_VALIDATION_FAILED_EXT && image == VK_NULL_HANDLE && alloc == VK_NULL_HANDLE); + } +} + static void TestMemoryRequirements() { VkResult res; @@ -1299,6 +1349,8 @@ static void TestBasics() } TestUserData(); + + TestInvalidAllocations(); } void TestHeapSizeLimit() diff --git a/src/vk_mem_alloc.h b/src/vk_mem_alloc.h index 10dc416..9deadfb 100644 --- a/src/vk_mem_alloc.h +++ b/src/vk_mem_alloc.h @@ -12301,6 +12301,10 @@ VkResult VmaAllocator_T::AllocateMemory( { VMA_ASSERT(VmaIsPow2(vkMemReq.alignment)); + if(vkMemReq.size == 0) + { + return VK_ERROR_VALIDATION_FAILED_EXT; + } if((createInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 && (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0) { @@ -14095,6 +14099,11 @@ VkResult vmaCreateBuffer( VmaAllocationInfo* pAllocationInfo) { VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && pBuffer && pAllocation); + + if(pBufferCreateInfo->size == 0) + { + return VK_ERROR_VALIDATION_FAILED_EXT; + } VMA_DEBUG_LOG("vmaCreateBuffer"); @@ -14234,6 +14243,15 @@ VkResult vmaCreateImage( { VMA_ASSERT(allocator && pImageCreateInfo && pAllocationCreateInfo && pImage && pAllocation); + if(pImageCreateInfo->extent.width == 0 || + pImageCreateInfo->extent.height == 0 || + pImageCreateInfo->extent.depth == 0 || + pImageCreateInfo->mipLevels == 0 || + pImageCreateInfo->arrayLayers == 0) + { + return VK_ERROR_VALIDATION_FAILED_EXT; + } + VMA_DEBUG_LOG("vmaCreateImage"); VMA_DEBUG_GLOBAL_MUTEX_LOCK