Add support for buffer device address, together with documentation and tests

Added VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT.
This commit is contained in:
Adam Sawicki 2020-03-20 18:05:42 +01:00
parent 39aeff7a43
commit e73e988daf
72 changed files with 16279 additions and 15850 deletions

View file

@ -53,7 +53,13 @@ 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 VK_EXT_buffer_device_address_enabled = false;
bool VK_KHR_buffer_device_address_enabled = false;
bool g_SparseBindingEnabled = false;
bool g_BufferDeviceAddressEnabled = false;
// # Pointers to functions from extensions
PFN_vkGetBufferDeviceAddressEXT g_vkGetBufferDeviceAddressEXT;
static HINSTANCE g_hAppInstance;
static HWND g_hWnd;
@ -594,16 +600,13 @@ static void RegisterDebugCallbacks()
assert(g_pvkDebugReportMessageEXT);
assert(g_pvkDestroyDebugReportCallbackEXT);
VkDebugReportCallbackCreateInfoEXT callbackCreateInfo;
callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
callbackCreateInfo.pNext = nullptr;
VkDebugReportCallbackCreateInfoEXT callbackCreateInfo = { VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT };
callbackCreateInfo.flags = //VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
VK_DEBUG_REPORT_ERROR_BIT_EXT |
VK_DEBUG_REPORT_WARNING_BIT_EXT |
VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT /*|
VK_DEBUG_REPORT_DEBUG_BIT_EXT*/;
callbackCreateInfo.pfnCallback = &MyDebugReportCallback;
callbackCreateInfo.pUserData = nullptr;
ERR_GUARD_VULKAN( g_pvkCreateDebugReportCallbackEXT(g_hVulkanInstance, &callbackCreateInfo, g_Allocs, &g_hCallback) );
}
@ -1134,6 +1137,7 @@ static void PrintEnabledFeatures()
{
wprintf(L"Validation layer: %d\n", g_EnableValidationLayer ? 1 : 0);
wprintf(L"Sparse binding: %d\n", g_SparseBindingEnabled ? 1 : 0);
wprintf(L"Buffer device address: %d\n", g_BufferDeviceAddressEnabled ? 1 : 0);
if(GetVulkanApiVersion() == VK_API_VERSION_1_0)
{
wprintf(L"VK_KHR_get_memory_requirements2: %d\n", VK_KHR_get_memory_requirements2_enabled ? 1 : 0);
@ -1143,6 +1147,8 @@ static void PrintEnabledFeatures()
}
wprintf(L"VK_EXT_memory_budget: %d\n", VK_EXT_memory_budget_enabled ? 1 : 0);
wprintf(L"VK_AMD_device_coherent_memory: %d\n", VK_AMD_device_coherent_memory_enabled ? 1 : 0);
wprintf(L"VK_KHR_buffer_device_address: %d\n", VK_KHR_buffer_device_address_enabled ? 1 : 0);
wprintf(L"VK_EXT_buffer_device_address: %d\n", VK_EXT_buffer_device_address_enabled ? 1 : 0);
}
void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo)
@ -1173,6 +1179,10 @@ void SetAllocatorCreateInfo(VmaAllocatorCreateInfo& outInfo)
{
outInfo.flags |= VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT;
}
if(g_BufferDeviceAddressEnabled)
{
outInfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
}
if(USE_CUSTOM_CPU_ALLOCATION_CALLBACKS)
{
@ -1306,7 +1316,7 @@ static void InitializeApplication()
g_hPhysicalDevice = physicalDevices[0];
// Query for extensions
// Query for device extensions
uint32_t physicalDeviceExtensionPropertyCount = 0;
ERR_GUARD_VULKAN( vkEnumerateDeviceExtensionProperties(g_hPhysicalDevice, nullptr, &physicalDeviceExtensionPropertyCount, nullptr) );
@ -1347,8 +1357,25 @@ static void InitializeApplication()
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;
else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0)
{
if(GetVulkanApiVersion() < VK_API_VERSION_1_2)
{
VK_KHR_buffer_device_address_enabled = true;
}
}
else if(strcmp(physicalDeviceExtensionProperties[i].extensionName, VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME) == 0)
{
if(GetVulkanApiVersion() < VK_API_VERSION_1_2)
{
VK_EXT_buffer_device_address_enabled = true;
}
}
}
if(VK_EXT_buffer_device_address_enabled && VK_KHR_buffer_device_address_enabled)
VK_EXT_buffer_device_address_enabled = false;
// Query for features
VkPhysicalDeviceProperties physicalDeviceProperties = {};
@ -1357,12 +1384,19 @@ static void InitializeApplication()
PrintPhysicalDeviceProperties(physicalDeviceProperties);
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;
PnextChainPushFront(&physicalDeviceFeatures, &physicalDeviceCoherentMemoryFeatures);
}
VkPhysicalDeviceBufferDeviceAddressFeaturesEXT physicalDeviceBufferDeviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT };
if(VK_KHR_buffer_device_address_enabled || VK_EXT_buffer_device_address_enabled || GetVulkanApiVersion() >= VK_API_VERSION_1_2)
{
PnextChainPushFront(&physicalDeviceFeatures, &physicalDeviceBufferDeviceAddressFeatures);
}
vkGetPhysicalDeviceFeatures2(g_hPhysicalDevice, &physicalDeviceFeatures);
g_SparseBindingEnabled = physicalDeviceFeatures.features.sparseBinding != 0;
@ -1370,6 +1404,8 @@ static void InitializeApplication()
// 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;
if(VK_KHR_buffer_device_address_enabled || VK_EXT_buffer_device_address_enabled || GetVulkanApiVersion() >= VK_API_VERSION_1_2)
g_BufferDeviceAddressEnabled = physicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress != VK_FALSE;
// Find queue family index
@ -1458,6 +1494,10 @@ static void InitializeApplication()
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);
if(VK_KHR_buffer_device_address_enabled)
enabledDeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
if(VK_EXT_buffer_device_address_enabled)
enabledDeviceExtensions.push_back(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
VkPhysicalDeviceFeatures2 deviceFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
deviceFeatures.features.samplerAnisotropy = VK_TRUE;
@ -1465,9 +1505,14 @@ static void InitializeApplication()
if(VK_AMD_device_coherent_memory_enabled)
{
physicalDeviceCoherentMemoryFeatures.pNext = deviceFeatures.pNext;
deviceFeatures.pNext = &physicalDeviceCoherentMemoryFeatures;
physicalDeviceCoherentMemoryFeatures.deviceCoherentMemory = VK_TRUE;
PnextChainPushBack(&deviceFeatures, &physicalDeviceCoherentMemoryFeatures);
}
if(g_BufferDeviceAddressEnabled)
{
physicalDeviceBufferDeviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_EXT };
physicalDeviceBufferDeviceAddressFeatures.bufferDeviceAddress = VK_TRUE;
PnextChainPushBack(&deviceFeatures, &physicalDeviceBufferDeviceAddressFeatures);
}
VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
@ -1481,6 +1526,51 @@ static void InitializeApplication()
ERR_GUARD_VULKAN( vkCreateDevice(g_hPhysicalDevice, &deviceCreateInfo, g_Allocs, &g_hDevice) );
// Fetch pointers to extension functions
if(g_BufferDeviceAddressEnabled)
{
if(GetVulkanApiVersion() >= VK_API_VERSION_1_2)
{
g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddress");
//assert(g_vkGetBufferDeviceAddressEXT != nullptr);
/*
For some reason this doesn't work, the pointer is NULL :( None of the below methods help.
Validation layers also report following error:
[ VUID-VkMemoryAllocateInfo-flags-03331 ] Object: VK_NULL_HANDLE (Type = 0) | If VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR is set, bufferDeviceAddress must be enabled. The Vulkan spec states: If VkMemoryAllocateFlagsInfo::flags includes VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT, the bufferDeviceAddress feature must be enabled (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkMemoryAllocateInfo-flags-03331)
Despite I'm posting VkPhysicalDeviceBufferDeviceAddressFeaturesEXT::bufferDeviceAddress = VK_TRUE in VkDeviceCreateInfo::pNext chain.
if(g_vkGetBufferDeviceAddressEXT == nullptr)
{
g_vkGetBufferDeviceAddressEXT = &vkGetBufferDeviceAddress; // Doesn't run, cannot find entry point...
}
if(g_vkGetBufferDeviceAddressEXT == nullptr)
{
g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetInstanceProcAddr(g_hVulkanInstance, "vkGetBufferDeviceAddress");
}
if(g_vkGetBufferDeviceAddressEXT == nullptr)
{
g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressKHR");
}
if(g_vkGetBufferDeviceAddressEXT == nullptr)
{
g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressEXT");
}
*/
}
else if(VK_KHR_buffer_device_address_enabled)
{
g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressKHR");
assert(g_vkGetBufferDeviceAddressEXT != nullptr);
}
else if(VK_EXT_buffer_device_address_enabled)
{
g_vkGetBufferDeviceAddressEXT = (PFN_vkGetBufferDeviceAddressEXT)vkGetDeviceProcAddr(g_hDevice, "vkGetBufferDeviceAddressEXT");
assert(g_vkGetBufferDeviceAddressEXT != nullptr);
}
}
// Create memory allocator
VmaAllocatorCreateInfo allocatorInfo = {};