Переглянути джерело

Validation layers on Android

Szymon Majewski 4 роки тому
батько
коміт
0a29322991

+ 52 - 59
drivers/vulkan/vulkan_context.cpp

@@ -41,6 +41,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <vector>
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 #define APP_SHORT_NAME "GodotEngine"
@@ -193,7 +194,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanContext::_debug_report_callback(
 	return VK_FALSE;
 }
 
-VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char **check_names, uint32_t layer_count, VkLayerProperties *layers) {
+VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char *const *check_names, uint32_t layer_count, VkLayerProperties *layers) {
 	for (uint32_t i = 0; i < check_count; i++) {
 		VkBool32 found = 0;
 		for (uint32_t j = 0; j < layer_count; j++) {
@@ -210,57 +211,55 @@ VkBool32 VulkanContext::_check_layers(uint32_t check_count, const char **check_n
 	return 1;
 }
 
-Error VulkanContext::_create_validation_layers() {
-	VkResult err;
-	const char *instance_validation_layers_alt1[] = { "VK_LAYER_KHRONOS_validation" };
-	const char *instance_validation_layers_alt2[] = { "VK_LAYER_LUNARG_standard_validation" };
-	const char *instance_validation_layers_alt3[] = { "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects" };
+Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const char *const **names) {
+	static const std::vector<std::vector<const char *>> instance_validation_layers_alt{
+		// Preferred set of validation layers
+		{ "VK_LAYER_KHRONOS_validation" },
 
-	uint32_t instance_layer_count = 0;
-	err = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr);
-	ERR_FAIL_COND_V(err, ERR_CANT_CREATE);
+		// Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers
+		{ "VK_LAYER_LUNARG_standard_validation" },
 
-	VkBool32 validation_found = 0;
-	uint32_t validation_layer_count = 0;
-	const char **instance_validation_layers = nullptr;
-	if (instance_layer_count > 0) {
-		VkLayerProperties *instance_layers = (VkLayerProperties *)malloc(sizeof(VkLayerProperties) * instance_layer_count);
-		err = vkEnumerateInstanceLayerProperties(&instance_layer_count, instance_layers);
-		if (err) {
-			free(instance_layers);
-			ERR_FAIL_V(ERR_CANT_CREATE);
-		}
+		// Alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers
+		{ "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", "VK_LAYER_GOOGLE_unique_objects" }
+	};
 
-		validation_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
-		instance_validation_layers = instance_validation_layers_alt1;
-		validation_found = _check_layers(validation_layer_count, instance_validation_layers, instance_layer_count, instance_layers);
+	// Clear out-arguments
+	*count = 0;
+	if (names != nullptr) {
+		*names = nullptr;
+	}
 
-		// use alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers
-		if (!validation_found) {
-			validation_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
-			instance_validation_layers = instance_validation_layers_alt2;
-			validation_found = _check_layers(validation_layer_count, instance_validation_layers, instance_layer_count, instance_layers);
-		}
+	VkResult err;
+	uint32_t instance_layer_count;
 
-		// use alternative (deprecated, removed in SDK 1.1.121.1) set of validation layers
-		if (!validation_found) {
-			validation_layer_count = ARRAY_SIZE(instance_validation_layers_alt3);
-			instance_validation_layers = instance_validation_layers_alt3;
-			validation_found = _check_layers(validation_layer_count, instance_validation_layers, instance_layer_count, instance_layers);
-		}
+	err = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr);
+	if (err) {
+		ERR_FAIL_V(ERR_CANT_CREATE);
+	}
+
+	if (instance_layer_count < 1) {
+		return OK;
+	}
 
+	VkLayerProperties *instance_layers = (VkLayerProperties *)malloc(sizeof(VkLayerProperties) * instance_layer_count);
+	err = vkEnumerateInstanceLayerProperties(&instance_layer_count, instance_layers);
+	if (err) {
 		free(instance_layers);
+		ERR_FAIL_V(ERR_CANT_CREATE);
 	}
 
-	if (validation_found) {
-		enabled_layer_count = validation_layer_count;
-		for (uint32_t i = 0; i < validation_layer_count; i++) {
-			enabled_layers[i] = instance_validation_layers[i];
+	for (uint32_t i = 0; i < instance_validation_layers_alt.size(); i++) {
+		if (_check_layers(instance_validation_layers_alt[i].size(), instance_validation_layers_alt[i].data(), instance_layer_count, instance_layers)) {
+			*count = instance_validation_layers_alt[i].size();
+			if (names != nullptr) {
+				*names = instance_validation_layers_alt[i].data();
+			}
+			break;
 		}
-	} else {
-		return ERR_CANT_CREATE;
 	}
 
+	free(instance_layers);
+
 	return OK;
 }
 
@@ -301,7 +300,6 @@ Error VulkanContext::_initialize_extensions() {
 	uint32_t instance_extension_count = 0;
 
 	enabled_extension_count = 0;
-	enabled_layer_count = 0;
 	enabled_debug_utils = false;
 	enabled_debug_report = false;
 	/* Look for instance extensions */
@@ -330,7 +328,7 @@ Error VulkanContext::_initialize_extensions() {
 				extension_names[enabled_extension_count++] = _get_platform_surface_extension();
 			}
 			if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) {
-				if (use_validation_layers) {
+				if (_use_validation_layers()) {
 					extension_names[enabled_extension_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
 					enabled_debug_report = true;
 				}
@@ -542,11 +540,6 @@ Error VulkanContext::_create_physical_device() {
 	/* obtain version */
 	_obtain_vulkan_version();
 
-	/* Look for validation layers */
-	if (use_validation_layers) {
-		_create_validation_layers();
-	}
-
 	/* initialise extensions */
 	{
 		Error err = _initialize_extensions();
@@ -567,16 +560,14 @@ Error VulkanContext::_create_physical_device() {
 		/*engineVersion*/ 0,
 		/*apiVersion*/ VK_MAKE_VERSION(vulkan_major, vulkan_minor, 0)
 	};
-	VkInstanceCreateInfo inst_info = {
-		/*sType*/ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
-		/*pNext*/ nullptr,
-		/*flags*/ 0,
-		/*pApplicationInfo*/ &app,
-		/*enabledLayerCount*/ enabled_layer_count,
-		/*ppEnabledLayerNames*/ (const char *const *)enabled_layers,
-		/*enabledExtensionCount*/ enabled_extension_count,
-		/*ppEnabledExtensionNames*/ (const char *const *)extension_names,
-	};
+	VkInstanceCreateInfo inst_info{};
+	inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+	inst_info.pApplicationInfo = &app;
+	inst_info.enabledExtensionCount = enabled_extension_count;
+	inst_info.ppEnabledExtensionNames = (const char *const *)extension_names;
+	if (_use_validation_layers()) {
+		_get_preferred_validation_layers(&inst_info.enabledLayerCount, &inst_info.ppEnabledLayerNames);
+	}
 
 	/*
 	   * This is info for a temp callback to use during CreateInstance.
@@ -1077,6 +1068,10 @@ Error VulkanContext::_create_semaphores() {
 	return OK;
 }
 
+bool VulkanContext::_use_validation_layers() {
+	return Engine::get_singleton()->is_validation_layers_enabled();
+}
+
 Error VulkanContext::_window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height) {
 	ERR_FAIL_COND_V(windows.has(p_window_id), ERR_INVALID_PARAMETER);
 
@@ -2008,8 +2003,6 @@ String VulkanContext::get_device_pipeline_cache_uuid() const {
 }
 
 VulkanContext::VulkanContext() {
-	use_validation_layers = Engine::get_singleton()->is_validation_layers_enabled();
-
 	command_buffer_queue.resize(1); // First one is always the setup command.
 	command_buffer_queue.write[0] = nullptr;
 }

+ 5 - 8
drivers/vulkan/vulkan_context.h

@@ -151,9 +151,6 @@ private:
 	 */
 	bool enabled_debug_report = false;
 
-	uint32_t enabled_layer_count = 0;
-	const char *enabled_layers[MAX_LAYERS];
-
 	PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
 	PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
 	PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
@@ -180,11 +177,10 @@ private:
 	VkDebugReportCallbackEXT dbg_debug_report = VK_NULL_HANDLE;
 
 	Error _obtain_vulkan_version();
-	Error _create_validation_layers();
 	Error _initialize_extensions();
 	Error _check_capabilities();
 
-	VkBool32 _check_layers(uint32_t check_count, const char **check_names, uint32_t layer_count, VkLayerProperties *layers);
+	VkBool32 _check_layers(uint32_t check_count, const char *const *check_names, uint32_t layer_count, VkLayerProperties *layers);
 	static VKAPI_ATTR VkBool32 VKAPI_CALL _debug_messenger_callback(
 			VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
 			VkDebugUtilsMessageTypeFlagsEXT messageType,
@@ -217,11 +213,12 @@ private:
 protected:
 	virtual const char *_get_platform_surface_extension() const = 0;
 
-	// Enabled via command line argument.
-	bool use_validation_layers = false;
-
 	virtual Error _window_create(DisplayServer::WindowID p_window_id, VkSurfaceKHR p_surface, int p_width, int p_height);
 
+	virtual bool _use_validation_layers();
+
+	Error _get_preferred_validation_layers(uint32_t *count, const char *const **names);
+
 	VkInstance _get_instance() {
 		return inst;
 	}

+ 1 - 1
platform/android/java/app/build.gradle

@@ -157,7 +157,7 @@ android {
             aidl.srcDirs = ['aidl']
             assets.srcDirs = ['assets']
         }
-        debug.jniLibs.srcDirs = ['libs/debug']
+        debug.jniLibs.srcDirs = ['libs/debug', 'libs/debug/vulkan_validation_layers']
         release.jniLibs.srcDirs = ['libs/release']
     }
 

+ 5 - 5
platform/android/vulkan/vulkan_context_android.cpp

@@ -52,10 +52,10 @@ int VulkanContextAndroid::window_create(ANativeWindow *p_window, int p_width, in
 	return _window_create(DisplayServer::MAIN_WINDOW_ID, surface, p_width, p_height);
 }
 
-VulkanContextAndroid::VulkanContextAndroid() {
-	// TODO: fix validation layers
-	use_validation_layers = false;
-}
+bool VulkanContextAndroid::_use_validation_layers() {
+	uint32_t count = 0;
+	_get_preferred_validation_layers(&count, nullptr);
 
-VulkanContextAndroid::~VulkanContextAndroid() {
+	// On Android, we use validation layers automatically if they were explicitly linked with the app.
+	return count > 0;
 }

+ 6 - 3
platform/android/vulkan/vulkan_context_android.h

@@ -36,13 +36,16 @@
 struct ANativeWindow;
 
 class VulkanContextAndroid : public VulkanContext {
-	virtual const char *_get_platform_surface_extension() const;
+	virtual const char *_get_platform_surface_extension() const override;
 
 public:
 	int window_create(ANativeWindow *p_window, int p_width, int p_height);
 
-	VulkanContextAndroid();
-	~VulkanContextAndroid();
+	VulkanContextAndroid() = default;
+	~VulkanContextAndroid() override = default;
+
+protected:
+	bool _use_validation_layers() override;
 };
 
 #endif // VULKAN_CONTEXT_ANDROID_H