Browse Source

Merge pull request #48439 from BastiaanOlij/cleanup_vulkan_checks

Cleanup vulkan capabilities check and add multiview check
Rémi Verschelde 4 years ago
parent
commit
a5a0fe65df

+ 4 - 0
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;

+ 77 - 17
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;

+ 8 - 0
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();

+ 4 - 0
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<uint8_t> (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);