From 0a29322991b2c2cc9aa05a951efeffb4f163ddf7 Mon Sep 17 00:00:00 2001 From: Szymon Majewski Date: Mon, 22 Mar 2021 10:38:25 -0700 Subject: [PATCH] Validation layers on Android --- drivers/vulkan/vulkan_context.cpp | 113 ++++++++---------- drivers/vulkan/vulkan_context.h | 13 +- platform/android/java/app/build.gradle | 2 +- .../android/vulkan/vulkan_context_android.cpp | 10 +- .../android/vulkan/vulkan_context_android.h | 9 +- 5 files changed, 70 insertions(+), 77 deletions(-) diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index 504e63392fd..e759e532889 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #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() { +Error VulkanContext::_get_preferred_validation_layers(uint32_t *count, const char *const **names) { + static const std::vector> instance_validation_layers_alt{ + // Preferred set of validation layers + { "VK_LAYER_KHRONOS_validation" }, + + // Alternative (deprecated, removed in SDK 1.1.126.0) set of validation layers + { "VK_LAYER_LUNARG_standard_validation" }, + + // 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" } + }; + + // Clear out-arguments + *count = 0; + if (names != nullptr) { + *names = nullptr; + } + 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" }; + uint32_t instance_layer_count; - uint32_t instance_layer_count = 0; err = vkEnumerateInstanceLayerProperties(&instance_layer_count, nullptr); - ERR_FAIL_COND_V(err, ERR_CANT_CREATE); + if (err) { + ERR_FAIL_V(ERR_CANT_CREATE); + } - 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); - } - - 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); - - // 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); - } - - // 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); - } + 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; } diff --git a/drivers/vulkan/vulkan_context.h b/drivers/vulkan/vulkan_context.h index b788181ab99..88e4f26bb19 100644 --- a/drivers/vulkan/vulkan_context.h +++ b/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; } diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index f103f22db20..1b1fb47bd8b 100644 --- a/platform/android/java/app/build.gradle +++ b/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'] } diff --git a/platform/android/vulkan/vulkan_context_android.cpp b/platform/android/vulkan/vulkan_context_android.cpp index 1bf85f07f19..63f2026fae3 100644 --- a/platform/android/vulkan/vulkan_context_android.cpp +++ b/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; } diff --git a/platform/android/vulkan/vulkan_context_android.h b/platform/android/vulkan/vulkan_context_android.h index c608f2d6654..5a84eaf8f34 100644 --- a/platform/android/vulkan/vulkan_context_android.h +++ b/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