From a64877f04508b1b458e91445862deb6e05a45ae6 Mon Sep 17 00:00:00 2001 From: Kazashi Yoshioka Date: Tue, 28 Mar 2023 10:45:44 +0200 Subject: [PATCH] Vulkan: Added prerequisite checks for using VK_Layer_Validation This PR adds pre-checks when enabling validation layers. For validation layers to work some platforms require that the Vulkan SDK is installed. Validation layers are activated when running blender with `--debug-gpu`. Sometimes we expect users to run with `--debug-gpu` for narrowing down an issue and we cannot expect them to have the Vulkan SDK installed. This patch will check if the `VK_LAYER_PATH` is available and that the configuration file of the validation layer is present. If this isn't the case we don't activate the requested validation layer. Pull Request: https://projects.blender.org/blender/blender/pulls/105922 --- intern/ghost/intern/GHOST_ContextVK.cpp | 56 +++++++++++++++++++++---- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/intern/ghost/intern/GHOST_ContextVK.cpp b/intern/ghost/intern/GHOST_ContextVK.cpp index 5ac0e4727e8..b6d64b157eb 100644 --- a/intern/ghost/intern/GHOST_ContextVK.cpp +++ b/intern/ghost/intern/GHOST_ContextVK.cpp @@ -23,6 +23,9 @@ #include #include #include +#include + +#include /* Set to 0 to allow devices that do not have the required features. * This allows development on OSX until we really needs these features. */ @@ -80,6 +83,21 @@ static const char *vulkan_error_as_string(VkResult result) } } +enum class VkLayer : uint8_t { KHRONOS_validation }; + +static bool vklayer_config_exist(const char *vk_extension_config) +{ + const char *ev_val = getenv("VK_LAYER_PATH"); + if (ev_val == nullptr) { + return false; + } + std::stringstream filename; + filename << ev_val; + filename << "/" << vk_extension_config; + struct stat buffer; + return (stat(filename.str().c_str(), &buffer) == 0); +} + #define __STR(A) "" #A #define VK_CHECK(__expression) \ do { \ @@ -401,16 +419,38 @@ static bool checkLayerSupport(vector &layers_available, const static void enableLayer(vector &layers_available, vector &layers_enabled, - const char *layer_name, - const bool debug) + const VkLayer layer, + const bool display_warning) { - if (checkLayerSupport(layers_available, layer_name)) { - layers_enabled.push_back(layer_name); +#define PUSH_VKLAYER(name, name2) \ + if (vklayer_config_exist("VkLayer_" #name ".json") && \ + checkLayerSupport(layers_available, "VK_LAYER_" #name2)) { \ + layers_enabled.push_back("VK_LAYER_" #name2); \ + enabled = true; \ + } \ + else { \ + warnings << "VK_LAYER_" #name2; \ } - else if (debug) { - fprintf( - stderr, "Warning: Layer requested, but not supported by the platform. [%s]\n", layer_name); + + bool enabled = false; + std::stringstream warnings; + + switch (layer) { + case VkLayer::KHRONOS_validation: + PUSH_VKLAYER(khronos_validation, KHRONOS_validation); + }; + + if (enabled) { + return; } + + if (display_warning) { + fprintf(stderr, + "Warning: Layer requested, but not supported by the platform. [%s] \n", + warnings.str().c_str()); + } + +#undef PUSH_VKLAYER } static bool device_extensions_support(VkPhysicalDevice device, vector required_exts) @@ -864,7 +904,7 @@ GHOST_TSuccess GHOST_ContextVK::initializeDrawingContext() vector layers_enabled; if (m_debug) { - enableLayer(layers_available, layers_enabled, "VK_LAYER_KHRONOS_validation", m_debug); + enableLayer(layers_available, layers_enabled, VkLayer::KHRONOS_validation, m_debug); } vector extensions_device;