Add support for VK_AMD_device_coherent_memory extension

- Added VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT.
- Fixed bug generating validation layers error when the extension is not enabled.
- Updated date in copyright header comments to year 2020.
This commit is contained in:
Adam Sawicki 2020-02-07 16:51:31 +01:00
parent 82ec4439c7
commit 508825012c
24 changed files with 343 additions and 117 deletions

View file

@ -1,5 +1,5 @@
//
// Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved.
// Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@ -46,12 +46,13 @@ VmaAllocator g_hAllocator;
VkInstance g_hVulkanInstance;
bool g_MemoryAliasingWarningEnabled = true;
static bool g_EnableValidationLayer = true;
static bool VK_KHR_get_memory_requirements2_enabled = false;
static bool VK_KHR_get_physical_device_properties2_enabled = false;
static bool VK_KHR_dedicated_allocation_enabled = false;
static bool VK_KHR_bind_memory2_enabled = false;
static bool VK_EXT_memory_budget_enabled = false;
bool g_EnableValidationLayer = true;
bool VK_KHR_get_memory_requirements2_enabled = false;
bool VK_KHR_get_physical_device_properties2_enabled = false;
bool VK_KHR_dedicated_allocation_enabled = false;
bool VK_KHR_bind_memory2_enabled = false;
bool VK_EXT_memory_budget_enabled = false;
bool VK_AMD_device_coherent_memory_enabled = false;
bool g_SparseBindingEnabled = false;
static HINSTANCE g_hAppInstance;
@ -1115,6 +1116,60 @@ static void DestroySwapchain(bool destroyActualSwapchain)
}
}
static constexpr uint32_t GetVulkanApiVersion()
{
return VMA_VULKAN_VERSION == 1001000 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0;
}
void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo)
{
outInfo = {};
outInfo.physicalDevice = g_hPhysicalDevice;
outInfo.device = g_hDevice;
outInfo.instance = g_hVulkanInstance;
outInfo.vulkanApiVersion = GetVulkanApiVersion();
if(VK_KHR_dedicated_allocation_enabled)
{
outInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
}
if(VK_KHR_bind_memory2_enabled)
{
outInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
}
#if !defined(VMA_MEMORY_BUDGET) || VMA_MEMORY_BUDGET == 1
if(VK_EXT_memory_budget_enabled && VK_KHR_get_physical_device_properties2_enabled)
{
outInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
}
#endif
if(VK_AMD_device_coherent_memory_enabled)
{
outInfo.flags |= VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT;
}
if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
{
outInfo.pAllocationCallbacks = &g_CpuAllocationCallbacks;
}
// Uncomment to enable recording to CSV file.
/*
static VmaRecordSettings recordSettings = {};
recordSettings.pFilePath = "VulkanSample.csv";
outInfo.pRecordSettings = &recordSettings;
*/
// Uncomment to enable HeapSizeLimit.
/*
static std::array<VkDeviceSize, VK_MAX_MEMORY_HEAPS> heapSizeLimit;
std::fill(heapSizeLimit.begin(), heapSizeLimit.end(), VK_WHOLE_SIZE);
heapSizeLimit[0] = 512ull * 1024 * 1024;
outInfo.pHeapSizeLimit = heapSizeLimit.data();
*/
}
static void InitializeApplication()
{
if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
@ -1172,7 +1227,7 @@ static void InitializeApplication()
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "Adam Sawicki Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VMA_VULKAN_VERSION == 1001000 ? VK_API_VERSION_1_1 : VK_API_VERSION_1_0;
appInfo.apiVersion = GetVulkanApiVersion();
VkInstanceCreateInfo instInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
instInfo.pApplicationInfo = &appInfo;
@ -1204,15 +1259,53 @@ static void InitializeApplication()
g_hPhysicalDevice = physicalDevices[0];
// Query for extensions
uint32_t physicalDeviceExtensionPropertyCount = 0;
ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &physicalDeviceExtensionPropertyCount, nullptr) );
std::vector<VkExtensionProperties> physicalDeviceExtensionProperties{physicalDeviceExtensionPropertyCount};
if(physicalDeviceExtensionPropertyCount)
{
ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(
g_hPhysicalDevice,
nullptr,
&physicalDeviceExtensionPropertyCount,
physicalDeviceExtensionProperties.data()) );
}
for(uint32_t i = 0; i < physicalDeviceExtensionPropertyCount; ++i)
{
if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
VK_KHR_get_memory_requirements2_enabled = true;
else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
VK_KHR_dedicated_allocation_enabled = true;
else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME) == 0)
VK_KHR_bind_memory2_enabled = true;
else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
VK_EXT_memory_budget_enabled = true;
else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME) == 0)
VK_AMD_device_coherent_memory_enabled = true;
}
// Query for features
VkPhysicalDeviceProperties physicalDeviceProperties = {};
vkGetPhysicalDeviceProperties(g_hPhysicalDevice, &physicalDeviceProperties);
VkPhysicalDeviceFeatures physicalDeviceFeatures = {};
vkGetPhysicalDeviceFeatures(g_hPhysicalDevice, &physicalDeviceFeatures);
VkPhysicalDeviceFeatures2 physicalDeviceFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
VkPhysicalDeviceCoherentMemoryFeaturesAMD physicalDeviceCoherentMemoryFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COHERENT_MEMORY_FEATURES_AMD };
if(VK_AMD_device_coherent_memory_enabled)
{
physicalDeviceCoherentMemoryFeatures.pNext = physicalDeviceFeatures.pNext;
physicalDeviceFeatures.pNext = &physicalDeviceCoherentMemoryFeatures;
}
vkGetPhysicalDeviceFeatures2(g_hPhysicalDevice, &physicalDeviceFeatures);
g_SparseBindingEnabled = physicalDeviceFeatures.sparseBinding != 0;
g_SparseBindingEnabled = physicalDeviceFeatures.features.sparseBinding != 0;
// The extension is supported as fake with no real support for this feature? Don't use it.
if(VK_AMD_device_coherent_memory_enabled && !physicalDeviceCoherentMemoryFeatures.deviceCoherentMemory)
VK_AMD_device_coherent_memory_enabled = false;
// Find queue family index
@ -1289,105 +1382,45 @@ static void InitializeApplication()
++queueCount;
}
VkPhysicalDeviceFeatures deviceFeatures = {};
//deviceFeatures.fillModeNonSolid = VK_TRUE;
deviceFeatures.samplerAnisotropy = VK_TRUE;
deviceFeatures.sparseBinding = g_SparseBindingEnabled ? VK_TRUE : VK_FALSE;
// Determine list of device extensions to enable.
std::vector<const char*> enabledDeviceExtensions;
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
if(VK_KHR_get_memory_requirements2_enabled)
enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
if(VK_KHR_dedicated_allocation_enabled)
enabledDeviceExtensions.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
if(VK_KHR_bind_memory2_enabled)
enabledDeviceExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
if(VK_EXT_memory_budget_enabled)
enabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
if(VK_AMD_device_coherent_memory_enabled)
enabledDeviceExtensions.push_back(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME);
VkPhysicalDeviceFeatures2 deviceFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
deviceFeatures.features.samplerAnisotropy = VK_TRUE;
deviceFeatures.features.sparseBinding = g_SparseBindingEnabled ? VK_TRUE : VK_FALSE;
if(VK_AMD_device_coherent_memory_enabled)
{
uint32_t propertyCount = 0;
ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &propertyCount, nullptr) );
if(propertyCount)
{
std::vector<VkExtensionProperties> properties{propertyCount};
ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &propertyCount, properties.data()) );
for(uint32_t i = 0; i < propertyCount; ++i)
{
if(strcmp(properties[i].extensionName, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME) == 0)
{
enabledDeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
VK_KHR_get_memory_requirements2_enabled = true;
}
else if(strcmp(properties[i].extensionName, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) == 0)
{
enabledDeviceExtensions.push_back(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
VK_KHR_dedicated_allocation_enabled = true;
}
else if(strcmp(properties[i].extensionName, VK_KHR_BIND_MEMORY_2_EXTENSION_NAME) == 0)
{
enabledDeviceExtensions.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
VK_KHR_bind_memory2_enabled = true;
}
else if(strcmp(properties[i].extensionName, VK_EXT_MEMORY_BUDGET_EXTENSION_NAME) == 0)
{
enabledDeviceExtensions.push_back(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME);
VK_EXT_memory_budget_enabled = true;
}
}
}
physicalDeviceCoherentMemoryFeatures.pNext = deviceFeatures.pNext;
deviceFeatures.pNext = &physicalDeviceCoherentMemoryFeatures;
physicalDeviceCoherentMemoryFeatures.deviceCoherentMemory = VK_TRUE;
}
VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
deviceCreateInfo.pNext = &deviceFeatures;
deviceCreateInfo.enabledLayerCount = 0;
deviceCreateInfo.ppEnabledLayerNames = nullptr;
deviceCreateInfo.enabledExtensionCount = (uint32_t)enabledDeviceExtensions.size();
deviceCreateInfo.ppEnabledExtensionNames = !enabledDeviceExtensions.empty() ? enabledDeviceExtensions.data() : nullptr;
deviceCreateInfo.queueCreateInfoCount = queueCount;
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
// Create memory allocator
VmaAllocatorCreateInfo allocatorInfo = {};
allocatorInfo.physicalDevice = g_hPhysicalDevice;
allocatorInfo.device = g_hDevice;
allocatorInfo.instance = g_hVulkanInstance;
allocatorInfo.vulkanApiVersion = appInfo.apiVersion;
if(VK_KHR_dedicated_allocation_enabled)
{
allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
}
if(VK_KHR_bind_memory2_enabled)
{
allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
}
#if !defined(VMA_MEMORY_BUDGET) || VMA_MEMORY_BUDGET == 1
if(VK_EXT_memory_budget_enabled && VK_KHR_get_physical_device_properties2_enabled)
{
allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
}
#endif
if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
{
allocatorInfo.pAllocationCallbacks = &g_CpuAllocationCallbacks;
}
// Uncomment to enable recording to CSV file.
/*
{
VmaRecordSettings recordSettings = {};
recordSettings.pFilePath = "VulkanSample.csv";
allocatorInfo.pRecordSettings = &recordSettings;
}
*/
// Uncomment to enable HeapSizeLimit.
/*
std::array<VkDeviceSize, VK_MAX_MEMORY_HEAPS> heapSizeLimit;
std::fill(heapSizeLimit.begin(), heapSizeLimit.end(), VK_WHOLE_SIZE);
heapSizeLimit[0] = 512ull * 1024 * 1024;
allocatorInfo.pHeapSizeLimit = heapSizeLimit.data();
*/
SetAllocatorCreateInfo(allocatorInfo);
ERR_GUARD_VULKAN( vmaCreateAllocator(&allocatorInfo, &g_hAllocator) );
// Retrieve queues (don't need to be destroyed).