From bf1732904ff5b6a3b886f12374077be23469751a Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 5 Jun 2022 23:24:00 +0200 Subject: [PATCH] Enable vulkan 1.2 and ray tracing extensions, if available --- .../rendering/vulkan/system/vk_device.cpp | 80 ++++++++++++++----- .../rendering/vulkan/system/vk_device.h | 16 +++- .../rendering/vulkan/system/vk_objects.h | 47 +++++++++++ 3 files changed, 121 insertions(+), 22 deletions(-) diff --git a/src/common/rendering/vulkan/system/vk_device.cpp b/src/common/rendering/vulkan/system/vk_device.cpp index 5aa229cb1..75ecad00f 100644 --- a/src/common/rendering/vulkan/system/vk_device.cpp +++ b/src/common/rendering/vulkan/system/vk_device.cpp @@ -217,7 +217,9 @@ void VulkanDevice::CreateAllocator() { VmaAllocatorCreateInfo allocinfo = {}; if (SupportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) - allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; + if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) + allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; allocinfo.physicalDevice = PhysicalDevice.Device; allocinfo.device = device; allocinfo.instance = instance; @@ -245,14 +247,47 @@ void VulkanDevice::CreateDevice() queueCreateInfos.push_back(queueCreateInfo); } - VkDeviceCreateInfo deviceCreateInfo = {}; - deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO }; + VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 }; + VkPhysicalDeviceBufferDeviceAddressFeatures deviceAddressFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES }; + VkPhysicalDeviceAccelerationStructureFeaturesKHR deviceAccelFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_FEATURES_KHR }; + VkPhysicalDeviceRayQueryFeaturesKHR rayQueryFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_QUERY_FEATURES_KHR }; + deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size(); deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data(); - deviceCreateInfo.pEnabledFeatures = &UsedDeviceFeatures; deviceCreateInfo.enabledExtensionCount = (uint32_t)EnabledDeviceExtensions.size(); deviceCreateInfo.ppEnabledExtensionNames = EnabledDeviceExtensions.data(); deviceCreateInfo.enabledLayerCount = 0; + deviceFeatures2.features = UsedDeviceFeatures; + deviceAddressFeatures.bufferDeviceAddress = true; + deviceAccelFeatures.accelerationStructure = true; + rayQueryFeatures.rayQuery = true; + + void** next = const_cast(&deviceCreateInfo.pNext); + if (SupportsDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) + { + *next = &deviceFeatures2; + void** next = &deviceFeatures2.pNext; + } + else // vulkan 1.0 specified features in a different way + { + deviceCreateInfo.pEnabledFeatures = &deviceFeatures2.features; + } + if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME)) + { + *next = &deviceAddressFeatures; + next = &deviceAddressFeatures.pNext; + } + if (SupportsDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME)) + { + *next = &deviceAccelFeatures; + next = &deviceAccelFeatures.pNext; + } + if (SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) + { + *next = &rayQueryFeatures; + next = &rayQueryFeatures.pNext; + } VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device); CheckVulkanError(result, "Could not create vulkan device"); @@ -306,23 +341,30 @@ void VulkanDevice::CreateInstance() } } - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "GZDoom"; - appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION); - appInfo.pEngineName = "GZDoom"; - appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION); - appInfo.apiVersion = VK_API_VERSION_1_0; + // Try get the highest vulkan version we can get + VkResult result = VK_ERROR_INITIALIZATION_FAILED; + for (int apiVersion : { VK_API_VERSION_1_2, VK_API_VERSION_1_1, VK_API_VERSION_1_0 }) + { + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "GZDoom"; + appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION); + appInfo.pEngineName = "GZDoom"; + appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION); + appInfo.apiVersion = apiVersion; - VkInstanceCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size(); - createInfo.enabledLayerCount = (uint32_t)EnabledValidationLayers.size(); - createInfo.ppEnabledLayerNames = EnabledValidationLayers.data(); - createInfo.ppEnabledExtensionNames = EnabledExtensions.data(); + VkInstanceCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size(); + createInfo.enabledLayerCount = (uint32_t)EnabledValidationLayers.size(); + createInfo.ppEnabledLayerNames = EnabledValidationLayers.data(); + createInfo.ppEnabledExtensionNames = EnabledExtensions.data(); - VkResult result = vkCreateInstance(&createInfo, nullptr, &instance); + result = vkCreateInstance(&createInfo, nullptr, &instance); + if (result >= VK_SUCCESS) + break; + } CheckVulkanError(result, "Could not create vulkan instance"); volkLoadInstance(instance); diff --git a/src/common/rendering/vulkan/system/vk_device.h b/src/common/rendering/vulkan/system/vk_device.h index 435ffc187..57f0096cf 100644 --- a/src/common/rendering/vulkan/system/vk_device.h +++ b/src/common/rendering/vulkan/system/vk_device.h @@ -64,7 +64,17 @@ public: // Device setup VkPhysicalDeviceFeatures UsedDeviceFeatures = {}; std::vector EnabledDeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - std::vector OptionalDeviceExtensions = { VK_EXT_HDR_METADATA_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME }; + std::vector OptionalDeviceExtensions = + { + VK_EXT_HDR_METADATA_EXTENSION_NAME, + VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, + VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, + VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, + VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, + VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, + VK_KHR_RAY_QUERY_EXTENSION_NAME + }; VulkanPhysicalDevice PhysicalDevice; bool DebugLayerActive = false; @@ -80,6 +90,8 @@ public: int presentFamily = -1; bool graphicsTimeQueries = false; + bool SupportsDeviceExtension(const char* ext) const; + private: void CreateInstance(); void CreateSurface(); @@ -89,8 +101,6 @@ private: void CreateAllocator(); void ReleaseResources(); - bool SupportsDeviceExtension(const char *ext) const; - static bool CheckRequiredFeatures(const VkPhysicalDeviceFeatures &f); VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE; diff --git a/src/common/rendering/vulkan/system/vk_objects.h b/src/common/rendering/vulkan/system/vk_objects.h index 7735a508d..13f286d4c 100644 --- a/src/common/rendering/vulkan/system/vk_objects.h +++ b/src/common/rendering/vulkan/system/vk_objects.h @@ -222,6 +222,22 @@ private: VulkanQueryPool &operator=(const VulkanQueryPool &) = delete; }; +class VulkanAccelerationStructure +{ +public: + VulkanAccelerationStructure(VulkanDevice* device, VkAccelerationStructureKHR accelstruct); + ~VulkanAccelerationStructure(); + + void SetDebugName(const char* name) { device->SetDebugObjectName(name, (uint64_t)accelstruct, VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR); } + + VulkanDevice* device; + VkAccelerationStructureKHR accelstruct; + +private: + VulkanAccelerationStructure(const VulkanAccelerationStructure&) = delete; + VulkanAccelerationStructure& operator=(const VulkanAccelerationStructure&) = delete; +}; + class VulkanPipeline { public: @@ -355,6 +371,10 @@ public: void endRenderPass(); void executeCommands(uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers); + void buildAccelerationStructures(uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos); + void traceRays(const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth); + void writeAccelerationStructuresProperties(uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery); + void debugFullPipelineBarrier(); VkCommandBuffer buffer = nullptr; @@ -879,6 +899,21 @@ inline void VulkanCommandBuffer::executeCommands(uint32_t commandBufferCount, co vkCmdExecuteCommands(buffer, commandBufferCount, pCommandBuffers); } +inline void VulkanCommandBuffer::buildAccelerationStructures(uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos, const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos) +{ + vkCmdBuildAccelerationStructuresKHR(buffer, infoCount, pInfos, ppBuildRangeInfos); +} + +inline void VulkanCommandBuffer::traceRays(const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable, const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width, uint32_t height, uint32_t depth) +{ + vkCmdTraceRaysKHR(buffer, pRaygenShaderBindingTable, pMissShaderBindingTable, pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth); +} + +inline void VulkanCommandBuffer::writeAccelerationStructuresProperties(uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures, VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery) +{ + vkCmdWriteAccelerationStructuresPropertiesKHR(buffer, accelerationStructureCount, pAccelerationStructures, queryType, queryPool, firstQuery); +} + inline void VulkanCommandBuffer::SetDebugName(const char *name) { pool->device->SetDebugObjectName(name, (uint64_t)buffer, VK_OBJECT_TYPE_COMMAND_BUFFER); @@ -1035,6 +1070,18 @@ inline VulkanSampler::~VulkanSampler() ///////////////////////////////////////////////////////////////////////////// +inline VulkanAccelerationStructure::VulkanAccelerationStructure(VulkanDevice* device, VkAccelerationStructureKHR accelstruct) + : device(device), accelstruct(accelstruct) +{ +} + +inline VulkanAccelerationStructure::~VulkanAccelerationStructure() +{ + vkDestroyAccelerationStructureKHR(device->device, accelstruct, nullptr); +} + +///////////////////////////////////////////////////////////////////////////// + inline VulkanPipeline::VulkanPipeline(VulkanDevice *device, VkPipeline pipeline) : device(device), pipeline(pipeline) { }