diff --git a/framework/core/hpp_instance.cpp b/framework/core/hpp_instance.cpp index 669de5948..1bc0286c4 100644 --- a/framework/core/hpp_instance.cpp +++ b/framework/core/hpp_instance.cpp @@ -344,8 +344,8 @@ HPPInstance::HPPInstance(const std::string &applicati vk::LayerSettingsCreateInfoEXT layerSettingsCreateInfo; - // If layer settings extension enabled by sample, then activate layer settings during instance creation - if (std::find(enabled_extensions.begin(), enabled_extensions.end(), VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) != enabled_extensions.end()) + // If layer settings are defined, then activate the sample's required layer settings during instance creation + if (required_layer_settings.size() > 0) { layerSettingsCreateInfo.settingCount = static_cast(required_layer_settings.size()); layerSettingsCreateInfo.pSettings = required_layer_settings.data(); diff --git a/framework/core/instance.cpp b/framework/core/instance.cpp index 42e0886d0..9b277f4aa 100644 --- a/framework/core/instance.cpp +++ b/framework/core/instance.cpp @@ -372,8 +372,8 @@ Instance::Instance(const std::string &application_nam VkLayerSettingsCreateInfoEXT layerSettingsCreateInfo{VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT}; - // If layer settings extension enabled by sample, then activate layer settings during instance creation - if (std::find(enabled_extensions.begin(), enabled_extensions.end(), VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) != enabled_extensions.end()) + // If layer settings are defined, then activate the sample's required layer settings during instance creation + if (required_layer_settings.size() > 0) { layerSettingsCreateInfo.settingCount = static_cast(required_layer_settings.size()); layerSettingsCreateInfo.pSettings = required_layer_settings.data(); diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 67bbb7b15..06e5b370d 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -20,6 +20,8 @@ #include "scene_graph/components/sub_mesh.h" +#define validation_layer_name "VK_LAYER_KHRONOS_validation" + std::string ShaderDebugPrintf::debug_output{}; VKAPI_ATTR VkBool32 VKAPI_CALL ShaderDebugPrintf::debug_utils_message_callback( @@ -28,8 +30,8 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ShaderDebugPrintf::debug_utils_message_callback( const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) { - // Look for Validation Layer message id names: WARNING-DEBUG-PRINTF or UNASSIGNED-DEBUG-PRINTF (have observed UNASSIGNED with older Vulkan SDKs) - if (strcmp(pCallbackData->pMessageIdName, "WARNING-DEBUG-PRINTF") == 0 || strcmp(pCallbackData->pMessageIdName, "UNASSIGNED-DEBUG-PRINTF") == 0) + // Look for Validation Layer message id names: VVL-DEBUG-PRINTF or WARNING-DEBUG-PRINTF or UNASSIGNED-DEBUG-PRINTF (have observed WARNING and UNASSIGNED with older Vulkan SDKs) + if (strcmp(pCallbackData->pMessageIdName, "VVL-DEBUG-PRINTF") == 0 || strcmp(pCallbackData->pMessageIdName, "WARNING-DEBUG-PRINTF") == 0 || strcmp(pCallbackData->pMessageIdName, "UNASSIGNED-DEBUG-PRINTF") == 0) { // Validation messages are a bit verbose, but we only want the text from the shader, so we cut off everything before the first word from the shader message // See scene.vert: debugPrintfEXT("Position = %v4f", outPos); @@ -45,21 +47,6 @@ ShaderDebugPrintf::ShaderDebugPrintf() title = "Shader debugprintf"; add_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME); - - // If layer settings available, use it to configure validation layer for debugPrintfEXT - add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ true); - - VkLayerSettingEXT layerSetting; - layerSetting.pLayerName = "VK_LAYER_KHRONOS_validation"; - layerSetting.pSettingName = "enables"; - layerSetting.type = VK_LAYER_SETTING_TYPE_STRING_EXT; - layerSetting.valueCount = 1; - - // Make this static so layer setting reference remains valid after leaving constructor scope - static const char *layerEnables = "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"; - layerSetting.pValues = &layerEnables; - - add_layer_setting(layerSetting); } ShaderDebugPrintf::~ShaderDebugPrintf() @@ -84,6 +71,11 @@ ShaderDebugPrintf::~ShaderDebugPrintf() void ShaderDebugPrintf::request_gpu_features(vkb::PhysicalDevice &gpu) { + // debugPrintfEXT requires fragmentStoresAndAtomics, vertexPipelineStoresAndAtomics, and shaderInt64 + gpu.get_mutable_requested_features().fragmentStoresAndAtomics = VK_TRUE; + gpu.get_mutable_requested_features().vertexPipelineStoresAndAtomics = VK_TRUE; + gpu.get_mutable_requested_features().shaderInt64 = VK_TRUE; + // Enable anisotropic filtering if supported if (gpu.get_features().samplerAnisotropy) { @@ -425,7 +417,7 @@ const std::vector ShaderDebugPrintf::get_validation_layers() #if !defined(VKB_DEBUG) && !defined(VKB_VALIDATION_LAYERS) // Force activation of validation layer on release builds for access to debugPrintfEXT feature - validation_layers.push_back("VK_LAYER_KHRONOS_validation"); + validation_layers.push_back(validation_layer_name); #endif return validation_layers; @@ -434,29 +426,64 @@ const std::vector ShaderDebugPrintf::get_validation_layers() // This sample overrides the instance creation part of the framework to chain in additional structures std::unique_ptr ShaderDebugPrintf::create_instance() { - uint32_t instanceApiVersion; - VK_CHECK(vkEnumerateInstanceVersion(&instanceApiVersion)); + auto debugprintf_api_version = VK_API_VERSION_1_1; - uint32_t instance_extension_count; - VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr)); - std::vector available_instance_extensions(instance_extension_count); - VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, available_instance_extensions.data())); + // Enumerate all instance layer properties so we can find and use the validation layer (VVL) version in subsequent steps + // The VVL version is needed to work around validation layer performance issues when running with Vulkan SDKs <= 1.3.290 + uint32_t layer_property_count; + VK_CHECK(vkEnumerateInstanceLayerProperties(&layer_property_count, nullptr)); + std::vector layer_properties(layer_property_count); + VK_CHECK(vkEnumerateInstanceLayerProperties(&layer_property_count, layer_properties.data())); - // When VK_EXT_layer_settings is available at runtime, the debugPrintfEXT layer feature is enabled using the standard framework - // For backwards compatibility with SDKs < 1.3.272 without VK_EXT_layer_settings, the remainder of this custom override is required - if (std::any_of(available_instance_extensions.begin(), - available_instance_extensions.end(), - [](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) + const auto vvl_properties = std::find_if(layer_properties.begin(), + layer_properties.end(), + [](VkLayerProperties const &properties) { return strcmp(properties.layerName, validation_layer_name) == 0; }); + + // Make sure we have found the validation layer before checking the VVL version and enumerating VVL instance extensions for VK_EXT_layer_settings + if (vvl_properties != layer_properties.end()) { - // debugPrintfEXT layer feature requires Vulkan API 1.1, but use API 1.2 until VVL performance fix is available in SDKs > 1.3.290 - // See VVL issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7562 for defect and fix information - set_api_version(instanceApiVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1); + // debugPrintfEXT layer feature requires Vulkan API 1.1, but override with API 1.2 for Vulkan SDKs <= 1.3.290 to work around VVL performance defect + // See VVL issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7562 for defect and fix information (fix available in SDK 1.3.296) + // Note: An additional, unrelated VVL performance issue affecting nVidia GPUs was found in SDK 1.3.296 following release - for nVidia GPUs please + // use SDK 1.3.290 until a fix is made available in a later SDK (see https://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/8766). + if (vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290)) + { + debugprintf_api_version = VK_API_VERSION_1_2; + } + + // Enumerate all instance extensions for the validation layer to determine if VK_EXT_layer_settings is supported by the layer + uint32_t vvl_extension_count; + VK_CHECK(vkEnumerateInstanceExtensionProperties(validation_layer_name, &vvl_extension_count, nullptr)); + std::vector vvl_instance_extensions(vvl_extension_count); + VK_CHECK(vkEnumerateInstanceExtensionProperties(validation_layer_name, &vvl_extension_count, vvl_instance_extensions.data())); + + // When VK_EXT_layer_settings is available at runtime, the debugPrintfEXT layer feature is enabled using the standard framework + // For this case set Vulkan API version and return via base class, otherwise the remainder of this custom override is required + if (std::any_of(vvl_instance_extensions.begin(), + vvl_instance_extensions.end(), + [](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) + { + set_api_version(debugprintf_api_version); + + // Since layer settings extension is available, use it to configure validation layer for debugPrintfEXT + VkLayerSettingEXT layerSetting; + layerSetting.pLayerName = validation_layer_name; + layerSetting.pSettingName = "enables"; + layerSetting.type = VK_LAYER_SETTING_TYPE_STRING_EXT; + layerSetting.valueCount = 1; + + // Make this static so layer setting reference remains valid after leaving the current scope + static const char *layerEnables = "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"; + layerSetting.pValues = &layerEnables; - // Run standard create_instance() from framework (with set_api_version and layer settings support) and return - return VulkanSample::create_instance(); + add_layer_setting(layerSetting); + + // Run standard create_instance() from framework with set_api_version() and add_layer_setting() support + return VulkanSample::create_instance(); + } } - // Run remainder of this custom create_instance() (without layer settings support) and return + // As a fallack, run remainder of this custom create_instance() override (without layer settings support) and return std::vector enabled_extensions; enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); @@ -467,7 +494,15 @@ std::unique_ptr ShaderDebugPrintf::create_instance() enabled_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); enabled_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + #if (defined(VKB_ENABLE_PORTABILITY)) + // Enumerate all instance extensions for the loader + driver to determine if VK_KHR_portability_enumeration is available + uint32_t available_extension_count; + VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &available_extension_count, nullptr)); + std::vector available_instance_extensions(available_extension_count); + VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &available_extension_count, available_instance_extensions.data())); + + // If VK_KHR_portability_enumeration is available in the portability implementation, then we must enable the extension bool portability_enumeration_available = false; if (std::any_of(available_instance_extensions.begin(), available_instance_extensions.end(), @@ -481,7 +516,10 @@ std::unique_ptr ShaderDebugPrintf::create_instance() VkApplicationInfo app_info{VK_STRUCTURE_TYPE_APPLICATION_INFO}; app_info.pApplicationName = "Shader debugprintf"; app_info.pEngineName = "Vulkan Samples"; - app_info.apiVersion = instanceApiVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1; + app_info.apiVersion = debugprintf_api_version; + + // Enable VK_EXT_validation_features extension for configuring validation layer features using VkValidationFeaturesEXT + enabled_extensions.push_back(VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME); // Shader printf is a feature of the validation layers that needs to be enabled std::vector validation_feature_enables = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT}; @@ -490,7 +528,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance() validation_features.enabledValidationFeatureCount = static_cast(validation_feature_enables.size()); validation_features.pEnabledValidationFeatures = validation_feature_enables.data(); - std::vector validation_layers = {"VK_LAYER_KHRONOS_validation"}; + std::vector validation_layers = {validation_layer_name}; VkInstanceCreateInfo instance_create_info{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; instance_create_info.ppEnabledExtensionNames = enabled_extensions.data();