From 7a4ea17e4e5acf40361dffadf783f899ba4e2fa8 Mon Sep 17 00:00:00 2001 From: Amer Koleci Date: Tue, 21 Sep 2021 11:07:23 +0200 Subject: [PATCH] Vulkan improvements. (#316) * Vulkan: Cleanup core 1.2 feature checks. * Vulkan: Improve SwapChain creation logic and handle capabilities in better way. * Vulkan: VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME depends on VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME (which is Core 1.2) * VK_KHR_get_physical_device_properties2 is core in 1.1 and no need to enable on instance extension. * Vulkan: FIX checks with core 1.2 features. --- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 124 ++++++++++++++--------- 1 file changed, 74 insertions(+), 50 deletions(-) diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 14c96521c..1e870e242 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -905,9 +905,6 @@ namespace Vulkan_Internal RenderPass renderpass; VkSurfaceKHR surface = VK_NULL_HANDLE; - VkSurfaceCapabilitiesKHR swapchain_capabilities; - std::vector swapchain_formats; - std::vector swapchain_presentModes; uint32_t swapChainImageIndex = 0; VkSemaphore swapchainAcquireSemaphore = VK_NULL_HANDLE; @@ -2025,15 +2022,10 @@ using namespace Vulkan_Internal; enabled_deviceExtensions = required_deviceExtensions; - if (checkExtensionSupport(VK_KHR_SPIRV_1_4_EXTENSION_NAME, available_deviceExtensions)) - { - enabled_deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); - } - - if (checkExtensionSupport(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, available_deviceExtensions)) - { - enabled_deviceExtensions.push_back(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME); - } + // Core 1.2 + enabled_deviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); + enabled_deviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); + enabled_deviceExtensions.push_back(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME); if (checkExtensionSupport(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME, available_deviceExtensions)) { @@ -2070,6 +2062,8 @@ using namespace Vulkan_Internal; if (checkExtensionSupport(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, available_deviceExtensions)) { + assert(checkExtensionSupport(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME, available_deviceExtensions)); + enabled_deviceExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); enabled_deviceExtensions.push_back(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME); fragment_shading_rate_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR; *features_chain = &fragment_shading_rate_features; @@ -2120,6 +2114,8 @@ using namespace Vulkan_Internal; assert(features2.features.shaderClipDistance == VK_TRUE); assert(features2.features.textureCompressionBC == VK_TRUE); assert(features2.features.occlusionQueryPrecise == VK_TRUE); + assert(features_1_2.descriptorIndexing == VK_TRUE); + if (features2.features.tessellationShader == VK_TRUE) { capabilities |= GRAPHICSDEVICE_CAPABILITY_TESSELLATION; @@ -2137,8 +2133,7 @@ using namespace Vulkan_Internal; raytracing_features.rayTracingPipeline == VK_TRUE && raytracing_query_features.rayQuery == VK_TRUE && acceleration_structure_features.accelerationStructure == VK_TRUE && - features_1_2.bufferDeviceAddress == VK_TRUE - ) + features_1_2.bufferDeviceAddress == VK_TRUE) { capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING; SHADER_IDENTIFIER_SIZE = raytracing_properties.shaderGroupHandleSize; @@ -2157,8 +2152,6 @@ using namespace Vulkan_Internal; VARIABLE_RATE_SHADING_TILE_SIZE = std::min(fragment_shading_rate_properties.maxFragmentShadingRateAttachmentTexelSize.width, fragment_shading_rate_properties.maxFragmentShadingRateAttachmentTexelSize.height); } - assert(features_1_2.descriptorIndexing == VK_TRUE); - VkFormatProperties formatProperties = {}; vkGetPhysicalDeviceFormatProperties(physicalDevice, _ConvertFormat(FORMAT_R11G11B10_FLOAT), &formatProperties); if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) @@ -2513,30 +2506,31 @@ using namespace Vulkan_Internal; dynamicStateInfo.dynamicStateCount = (uint32_t)pso_dynamicStates.size(); dynamicStateInfo.pDynamicStates = pso_dynamicStates.data(); - if (features_1_2.descriptorBindingSampledImageUpdateAfterBind) + if (features_1_2.descriptorBindingSampledImageUpdateAfterBind == VK_TRUE) { allocationhandler->bindlessSampledImages.init(device, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, properties_1_2.maxDescriptorSetUpdateAfterBindSampledImages / 4); } - if (features_1_2.descriptorBindingUniformTexelBufferUpdateAfterBind) + if (features_1_2.descriptorBindingUniformTexelBufferUpdateAfterBind == VK_TRUE) { allocationhandler->bindlessUniformTexelBuffers.init(device, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, properties_1_2.maxDescriptorSetUpdateAfterBindSampledImages / 4); } - if (features_1_2.descriptorBindingStorageBufferUpdateAfterBind) + if (features_1_2.descriptorBindingStorageBufferUpdateAfterBind == VK_TRUE) { allocationhandler->bindlessStorageBuffers.init(device, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, properties_1_2.maxDescriptorSetUpdateAfterBindStorageBuffers / 4); } - if (features_1_2.descriptorBindingStorageImageUpdateAfterBind) + if (features_1_2.descriptorBindingStorageImageUpdateAfterBind == VK_TRUE) { allocationhandler->bindlessStorageImages.init(device, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, properties_1_2.maxDescriptorSetUpdateAfterBindStorageImages / 4); } - if (features_1_2.descriptorBindingStorageTexelBufferUpdateAfterBind) + if (features_1_2.descriptorBindingStorageTexelBufferUpdateAfterBind == VK_TRUE) { allocationhandler->bindlessStorageTexelBuffers.init(device, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, properties_1_2.maxDescriptorSetUpdateAfterBindStorageImages / 4); } - if (features_1_2.descriptorBindingSampledImageUpdateAfterBind) + if (features_1_2.descriptorBindingSampledImageUpdateAfterBind == VK_TRUE) { allocationhandler->bindlessSamplers.init(device, VK_DESCRIPTOR_TYPE_SAMPLER, 256); } + if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { allocationhandler->bindlessAccelerationStructures.init(device, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 32); @@ -2654,52 +2648,55 @@ using namespace Vulkan_Internal; #endif // _WIN32 } - int presentFamily = -1; - int familyIndex = 0; + uint32_t presentFamily = VK_QUEUE_FAMILY_IGNORED; + uint32_t familyIndex = 0; for (const auto& queueFamily : queueFamilies) { VkBool32 presentSupport = false; res = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, (uint32_t)familyIndex, internal_state->surface, &presentSupport); assert(res == VK_SUCCESS); - if (presentFamily < 0 && queueFamily.queueCount > 0 && presentSupport) + if (presentFamily == VK_QUEUE_FAMILY_IGNORED && queueFamily.queueCount > 0 && presentSupport) { presentFamily = familyIndex; + break; } familyIndex++; } - res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, internal_state->surface, &internal_state->swapchain_capabilities); + // Present family not found, we cannot create SwapChain + if (presentFamily == VK_QUEUE_FAMILY_IGNORED) + { + return false; + } + + VkSurfaceCapabilitiesKHR swapchain_capabilities; + res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, internal_state->surface, &swapchain_capabilities); assert(res == VK_SUCCESS); uint32_t formatCount; res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, nullptr); assert(res == VK_SUCCESS); - if (formatCount != 0) - { - internal_state->swapchain_formats.resize(formatCount); - res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, internal_state->swapchain_formats.data()); - assert(res == VK_SUCCESS); - } + std::vector swapchain_formats(formatCount); + res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, swapchain_formats.data()); + assert(res == VK_SUCCESS); uint32_t presentModeCount; res = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, internal_state->surface, &presentModeCount, nullptr); assert(res == VK_SUCCESS); - if (presentModeCount != 0) - { - internal_state->swapchain_presentModes.resize(presentModeCount); - res = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, internal_state->surface, &presentModeCount, internal_state->swapchain_presentModes.data()); - assert(res == VK_SUCCESS); - } + std::vector swapchain_presentModes(presentModeCount); + swapchain_presentModes.resize(presentModeCount); + res = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, internal_state->surface, &presentModeCount, swapchain_presentModes.data()); + assert(res == VK_SUCCESS); VkSurfaceFormatKHR surfaceFormat = {}; surfaceFormat.format = _ConvertFormat(pDesc->format); bool valid = false; - for (const auto& format : internal_state->swapchain_formats) + for (const auto& format : swapchain_formats) { if (format.format == surfaceFormat.format) { @@ -2714,11 +2711,14 @@ using namespace Vulkan_Internal; } internal_state->swapChainExtent = { pDesc->width, pDesc->height }; - internal_state->swapChainExtent.width = std::max(internal_state->swapchain_capabilities.minImageExtent.width, std::min(internal_state->swapchain_capabilities.maxImageExtent.width, internal_state->swapChainExtent.width)); - internal_state->swapChainExtent.height = std::max(internal_state->swapchain_capabilities.minImageExtent.height, std::min(internal_state->swapchain_capabilities.maxImageExtent.height, internal_state->swapChainExtent.height)); - + internal_state->swapChainExtent.width = std::max(swapchain_capabilities.minImageExtent.width, std::min(swapchain_capabilities.maxImageExtent.width, internal_state->swapChainExtent.width)); + internal_state->swapChainExtent.height = std::max(swapchain_capabilities.minImageExtent.height, std::min(swapchain_capabilities.maxImageExtent.height, internal_state->swapChainExtent.height)); uint32_t imageCount = pDesc->buffercount; + if ((swapchain_capabilities.maxImageCount > 0) && (imageCount > swapchain_capabilities.maxImageCount)) + { + imageCount = swapchain_capabilities.maxImageCount; + } VkSwapchainCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; @@ -2731,18 +2731,42 @@ using namespace Vulkan_Internal; createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.preTransform = internal_state->swapchain_capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + // Transform + if(swapchain_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) + createInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + else + createInfo.preTransform = swapchain_capabilities.currentTransform; + + // Composite alpha + std::vector compositeAlphaFlags = { + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, + VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, + }; + for (auto& compositeAlphaFlag : compositeAlphaFlags) + { + if (swapchain_capabilities.supportedCompositeAlpha & compositeAlphaFlag) + { + createInfo.compositeAlpha = compositeAlphaFlag; + break; + }; + } + createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; // The only one that is always supported if (!pDesc->vsync) { - // The immediate present mode is not necessarily supported: - for (auto& presentmode : internal_state->swapchain_presentModes) + // The mailbox/immediate present mode is not necessarily supported: + for (auto& presentMode : swapchain_presentModes) { - if (presentmode == VK_PRESENT_MODE_IMMEDIATE_KHR) + if (presentMode == VK_PRESENT_MODE_MAILBOX_KHR) + { + createInfo.presentMode = VK_PRESENT_MODE_MAILBOX_KHR; + break; + } + if (presentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) { createInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; - break; } } } @@ -2765,12 +2789,12 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); internal_state->swapChainImageFormat = surfaceFormat.format; - if (vkSetDebugUtilsObjectNameEXT != nullptr) + if (debugUtils) { VkDebugUtilsObjectNameInfoEXT info = {}; info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; - info.pObjectName = "SWAPCHAIN"; info.objectType = VK_OBJECT_TYPE_IMAGE; + info.pObjectName = "SWAPCHAIN"; for (auto& x : internal_state->swapChainImages) { info.objectHandle = (uint64_t)x;