Added flag VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT

This commit is contained in:
Adam Sawicki 2021-12-06 12:14:13 +01:00
parent e5c03604c9
commit 4cd813a8c6
2 changed files with 105 additions and 17 deletions

View File

@ -961,6 +961,12 @@ typedef enum VmaAllocationCreateFlagBits {
memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`. memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
*/ */
VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100, VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
/** \brief Set this flag if the allocated memory will have aliasing resources.
*
Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.
Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
*/
VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200,
/** Allocation strategy that chooses smallest possible free range for the /** Allocation strategy that chooses smallest possible free range for the
allocation. allocation.
@ -6877,6 +6883,7 @@ private:
bool withinBudget, bool withinBudget,
bool map, bool map,
bool isUserDataString, bool isUserDataString,
bool canAliasMemory,
void* pUserData, void* pUserData,
float priority, float priority,
VkBuffer dedicatedBuffer, VkBuffer dedicatedBuffer,
@ -15152,6 +15159,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,
finalCreateInfo.pUserData, finalCreateInfo.pUserData,
finalCreateInfo.priority, finalCreateInfo.priority,
dedicatedBuffer, dedicatedBuffer,
@ -15197,6 +15205,7 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0, (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,
finalCreateInfo.pUserData, finalCreateInfo.pUserData,
finalCreateInfo.priority, finalCreateInfo.priority,
dedicatedBuffer, dedicatedBuffer,
@ -15226,6 +15235,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
bool withinBudget, bool withinBudget,
bool map, bool map,
bool isUserDataString, bool isUserDataString,
bool canAliasMemory,
void* pUserData, void* pUserData,
float priority, float priority,
VkBuffer dedicatedBuffer, VkBuffer dedicatedBuffer,
@ -15252,19 +15262,22 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
allocInfo.allocationSize = size; allocInfo.allocationSize = size;
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR }; if(!canAliasMemory)
if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
if(dedicatedBuffer != VK_NULL_HANDLE) VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{ {
VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE); if(dedicatedBuffer != VK_NULL_HANDLE)
dedicatedAllocInfo.buffer = dedicatedBuffer; {
VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);
} dedicatedAllocInfo.buffer = dedicatedBuffer;
else if(dedicatedImage != VK_NULL_HANDLE) VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
{ }
dedicatedAllocInfo.image = dedicatedImage; else if(dedicatedImage != VK_NULL_HANDLE)
VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo); {
dedicatedAllocInfo.image = dedicatedImage;
VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
}
} }
} }
#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000 #endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000

View File

@ -5627,6 +5627,77 @@ static void TestAliasing()
vkDestroyImage(g_hDevice, img1, g_Allocs); vkDestroyImage(g_hDevice, img1, g_Allocs);
} }
static void TestAllocationAliasing()
{
wprintf(L"Testing allocation aliasing...\n");
/*
* Test whether using VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT suppress validation layer error
* by don't supplying VkMemoryDedicatedAllocateInfoKHR to creation of dedicated memory
* that will be used to alias with some other textures.
*/
VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
imageInfo.extent.depth = 1;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
VmaAllocationCreateInfo allocationCreateInfo = {};
allocationCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
// Bind 2 textures together into same memory without VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT and then with flag set
/*
{
VkImage originalImage;
VmaAllocation allocation;
imageInfo.extent.width = 640;
imageInfo.extent.height = 480;
VkResult res = vmaCreateImage(g_hAllocator, &imageInfo, &allocationCreateInfo, &originalImage, &allocation, nullptr);
TEST(res == VK_SUCCESS);
VkImage aliasingImage;
imageInfo.extent.width = 480;
imageInfo.extent.height = 256;
res = vkCreateImage(g_hDevice, &imageInfo, nullptr, &aliasingImage);
TEST(res == VK_SUCCESS);
// After binding there should be inevitable validation layer error VUID-vkBindImageMemory-memory-01509
res = vmaBindImageMemory(g_hAllocator, allocation, aliasingImage);
TEST(res == VK_SUCCESS);
vkDestroyImage(g_hDevice, aliasingImage, nullptr);
vmaDestroyImage(g_hAllocator, originalImage, allocation);
}
*/
allocationCreateInfo.flags |= VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT;
{
VkImage originalImage;
VmaAllocation allocation;
imageInfo.extent.width = 640;
imageInfo.extent.height = 480;
VkResult res = vmaCreateImage(g_hAllocator, &imageInfo, &allocationCreateInfo, &originalImage, &allocation, nullptr);
TEST(res == VK_SUCCESS);
VkImage aliasingImage;
imageInfo.extent.width = 480;
imageInfo.extent.height = 256;
res = vkCreateImage(g_hDevice, &imageInfo, nullptr, &aliasingImage);
TEST(res == VK_SUCCESS);
// Now with VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT flag validation error is no more
res = vmaBindImageMemory(g_hAllocator, allocation, aliasingImage);
TEST(res == VK_SUCCESS);
vkDestroyImage(g_hDevice, aliasingImage, nullptr);
vmaDestroyImage(g_hAllocator, originalImage, allocation);
}
}
static void TestMapping() static void TestMapping()
{ {
wprintf(L"Testing mapping...\n"); wprintf(L"Testing mapping...\n");
@ -6885,6 +6956,7 @@ void Test()
TestDeviceCoherentMemory(); TestDeviceCoherentMemory();
TestBudget(); TestBudget();
TestAliasing(); TestAliasing();
TestAllocationAliasing();
TestMapping(); TestMapping();
TestDeviceLocalMapped(); TestDeviceLocalMapped();
TestMappingMultithreaded(); TestMappingMultithreaded();
@ -6908,12 +6980,15 @@ void Test()
fclose(file); fclose(file);
} }
TestDefragmentationSimple(); if(ConfigType >= CONFIG_TYPE_AVERAGE)
TestDefragmentationFull(); {
TestDefragmentationWholePool(); TestDefragmentationSimple();
TestDefragmentationGpu(); TestDefragmentationFull();
TestDefragmentationIncrementalBasic(); TestDefragmentationWholePool();
TestDefragmentationIncrementalComplex(); TestDefragmentationGpu();
TestDefragmentationIncrementalBasic();
TestDefragmentationIncrementalComplex();
}
// # Detailed tests // # Detailed tests
FILE* file; FILE* file;