diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 30cc01fd10..43b2a24172 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -7844,6 +7844,10 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de device_capabilities.subgroup_size = subgroup_capabilities.size; device_capabilities.subgroup_in_shaders = subgroup_capabilities.supported_stages_flags_rd(); device_capabilities.subgroup_operations = subgroup_capabilities.supported_operations_flags_rd(); + + // get info about further features + VulkanContext::MultiviewCapabilities multiview_capabilies = p_context->get_multiview_capabilities(); + device_capabilities.supports_multiview = multiview_capabilies.is_supported && multiview_capabilies.max_view_count > 1; } context = p_context; diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 0a8a5c746f..12a67c0e07 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -352,8 +352,6 @@ Error VulkanContext::_initialize_extensions() { return OK; } -typedef void(VKAPI_PTR *_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice, VkPhysicalDeviceProperties2 *); - uint32_t VulkanContext::SubgroupCapabilities::supported_stages_flags_rd() const { uint32_t flags = 0; @@ -496,20 +494,70 @@ String VulkanContext::SubgroupCapabilities::supported_operations_desc() const { } Error VulkanContext::_check_capabilities() { - // check subgroups + // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_KHR_multiview.html // https://www.khronos.org/blog/vulkan-subgroup-tutorial + // for Vulkan 1.0 vkGetPhysicalDeviceProperties2 is not available, including not in the loader we compile against on Android. - _vkGetPhysicalDeviceProperties2 func = (_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); - if (func != nullptr) { + + // so we check if the functions are accessible by getting their function pointers and skipping if not + // (note that the desktop loader does a better job here but the android loader doesn't) + + // assume not supported until proven otherwise + multiview_capabilities.is_supported = false; + multiview_capabilities.max_view_count = 0; + multiview_capabilities.max_instance_count = 0; + subgroup_capabilities.size = 0; + subgroup_capabilities.supportedStages = 0; + subgroup_capabilities.supportedOperations = 0; + subgroup_capabilities.quadOperationsInAllStages = false; + + // check for extended features + PFN_vkGetPhysicalDeviceFeatures2 device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2"); + if (device_features_func == nullptr) { + // In Vulkan 1.0 might be accessible under its original extension name + device_features_func = (PFN_vkGetPhysicalDeviceFeatures2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceFeatures2KHR"); + } + if (device_features_func != nullptr) { + // check our extended features + VkPhysicalDeviceMultiviewFeatures multiview_features; + multiview_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES; + multiview_features.pNext = NULL; + + VkPhysicalDeviceFeatures2 device_features; + device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + device_features.pNext = &multiview_features; + + device_features_func(gpu, &device_features); + multiview_capabilities.is_supported = multiview_features.multiview; + // For now we ignore if multiview is available in geometry and tesselation as we do not currently support those + } + + // check extended properties + PFN_vkGetPhysicalDeviceProperties2 device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2"); + if (device_properties_func == nullptr) { + // In Vulkan 1.0 might be accessible under its original extension name + device_properties_func = (PFN_vkGetPhysicalDeviceProperties2)vkGetInstanceProcAddr(inst, "vkGetPhysicalDeviceProperties2KHR"); + } + if (device_properties_func != nullptr) { + VkPhysicalDeviceMultiviewProperties multiviewProperties; VkPhysicalDeviceSubgroupProperties subgroupProperties; + VkPhysicalDeviceProperties2 physicalDeviceProperties; + subgroupProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES; subgroupProperties.pNext = nullptr; - VkPhysicalDeviceProperties2 physicalDeviceProperties; physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - physicalDeviceProperties.pNext = &subgroupProperties; - func(gpu, &physicalDeviceProperties); + if (multiview_capabilities.is_supported) { + multiviewProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES; + multiviewProperties.pNext = &subgroupProperties; + + physicalDeviceProperties.pNext = &multiviewProperties; + } else { + physicalDeviceProperties.pNext = &subgroupProperties; + } + + device_properties_func(gpu, &physicalDeviceProperties); subgroup_capabilities.size = subgroupProperties.subgroupSize; subgroup_capabilities.supportedStages = subgroupProperties.supportedStages; @@ -519,18 +567,30 @@ Error VulkanContext::_check_capabilities() { // - supportedOperations has VK_SUBGROUP_FEATURE_QUAD_BIT subgroup_capabilities.quadOperationsInAllStages = subgroupProperties.quadOperationsInAllStages; - // only output this when debugging? - print_line("- Vulkan subgroup size " + itos(subgroup_capabilities.size)); - print_line("- Vulkan subgroup stages " + subgroup_capabilities.supported_stages_desc()); - print_line("- Vulkan subgroup supported ops " + subgroup_capabilities.supported_operations_desc()); + if (multiview_capabilities.is_supported) { + multiview_capabilities.max_view_count = multiviewProperties.maxMultiviewViewCount; + multiview_capabilities.max_instance_count = multiviewProperties.maxMultiviewInstanceIndex; + +#ifdef DEBUG_ENABLED + print_line("- Vulkan multiview supported:"); + print_line(" max views: " + itos(multiview_capabilities.max_view_count)); + print_line(" max instances: " + itos(multiview_capabilities.max_instance_count)); + } else { + print_line("- Vulkan multiview not supported"); +#endif + } + +#ifdef DEBUG_ENABLED + print_line("- Vulkan subgroup:"); + print_line(" size: " + itos(subgroup_capabilities.size)); + print_line(" stages: " + subgroup_capabilities.supported_stages_desc()); + print_line(" supported ops: " + subgroup_capabilities.supported_operations_desc()); if (subgroup_capabilities.quadOperationsInAllStages) { - print_line("- Vulkan subgroup quad operations in all stages"); + print_line(" quad operations in all stages"); } } else { - subgroup_capabilities.size = 0; - subgroup_capabilities.supportedStages = 0; - subgroup_capabilities.supportedOperations = 0; - subgroup_capabilities.quadOperationsInAllStages = false; + print_line("- Couldn't call vkGetPhysicalDeviceProperties2"); +#endif } return OK; diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index 88e4f26bb1..3d9b295c5a 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/drivers/vulkan/vulkan_context.h @@ -54,6 +54,12 @@ public: String supported_operations_desc() const; }; + struct MultiviewCapabilities { + bool is_supported; + int32_t max_view_count; + int32_t max_instance_count; + }; + private: enum { MAX_EXTENSIONS = 128, @@ -75,6 +81,7 @@ private: uint32_t vulkan_major = 1; uint32_t vulkan_minor = 0; SubgroupCapabilities subgroup_capabilities; + MultiviewCapabilities multiview_capabilities; String device_vendor; String device_name; @@ -227,6 +234,7 @@ public: uint32_t get_vulkan_major() const { return vulkan_major; }; uint32_t get_vulkan_minor() const { return vulkan_minor; }; SubgroupCapabilities get_subgroup_capabilities() const { return subgroup_capabilities; }; + MultiviewCapabilities get_multiview_capabilities() const { return multiview_capabilities; }; VkDevice get_device(); VkPhysicalDevice get_physical_device(); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 2de0549e8d..d86c44a206 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -93,10 +93,14 @@ public: DeviceFamily device_family = DEVICE_UNKNOWN; uint32_t version_major = 1.0; uint32_t version_minor = 0.0; + // subgroup capabilities uint32_t subgroup_size = 0; uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc. uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations + + // features + bool supports_multiview = false; // If true this device supports multiview options }; typedef Vector (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);