From 8c00ce468a966851413094ade1a2d99acd44ba55 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:42:47 -0400 Subject: [PATCH 01/12] shader_debugprintf: support new VVL-DEBUG-PRINTF message and fix VVL version check for API selection --- .../shader_debugprintf/shader_debugprintf.cpp | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 0a59717f3..aee667793 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -27,8 +27,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); @@ -433,8 +433,15 @@ 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(bool headless) { - uint32_t instanceApiVersion; - VK_CHECK(vkEnumerateInstanceVersion(&instanceApiVersion)); + 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())); + + // Find validation layer properties so we can extract the VVL version and select the correct Vulkan API based on SDK release + const auto vvl_properties = std::find_if(layer_properties.begin(), + layer_properties.end(), + [](VkLayerProperties const &properties) { return strcmp(properties.layerName, "VK_LAYER_KHRONOS_validation") == 0; }); uint32_t instance_extension_count; VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr)); @@ -442,14 +449,14 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, available_instance_extensions.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 + // For this case set Vulkan API version and return via parent class, otherwise 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; })) { // 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); + set_api_version(vvl_properties != layer_properties.end() && vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1); // Run standard create_instance() from framework (with set_api_version and layer settings support) and return return VulkanSample::create_instance(headless); @@ -480,7 +487,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) 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 = vvl_properties != layer_properties.end() && vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1; // 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}; From 0dc49635f09d33687b3999869d2196d48fe06789 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:20:35 -0400 Subject: [PATCH 02/12] Incorporate review feedback: update comments and simpify code --- .../shader_debugprintf/shader_debugprintf.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index aee667793..5848d3c1f 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -433,30 +433,37 @@ 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(bool headless) { + // 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())); - // Find validation layer properties so we can extract the VVL version and select the correct Vulkan API based on SDK release const auto vvl_properties = std::find_if(layer_properties.begin(), layer_properties.end(), [](VkLayerProperties const &properties) { return strcmp(properties.layerName, "VK_LAYER_KHRONOS_validation") == 0; }); + // 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) + auto debugprintf_api_version = VK_API_VERSION_1_1; + if (vvl_properties != layer_properties.end() && vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290)) + { + debugprintf_api_version = VK_API_VERSION_1_2; + } + 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())); // 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 parent class, otherwise the remainder of this custom override is required + // 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(available_instance_extensions.begin(), available_instance_extensions.end(), [](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) { - // 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(vvl_properties != layer_properties.end() && vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1); + set_api_version(debugprintf_api_version); // Run standard create_instance() from framework (with set_api_version and layer settings support) and return return VulkanSample::create_instance(headless); @@ -487,7 +494,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) VkApplicationInfo app_info{VK_STRUCTURE_TYPE_APPLICATION_INFO}; app_info.pApplicationName = "Shader debugprintf"; app_info.pEngineName = "Vulkan Samples"; - app_info.apiVersion = vvl_properties != layer_properties.end() && vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1; + app_info.apiVersion = debugprintf_api_version; // 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}; From 4f53d1538db2b0abff42ea9fa703393ae3a9acb4 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:04:56 -0400 Subject: [PATCH 03/12] Add VK_EXT_validation_features and move VK_EXT_layer_settings extensions to ShaderDebugPrintf::create_instance() --- .../shader_debugprintf/shader_debugprintf.cpp | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 5848d3c1f..d4f9556a8 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -44,21 +44,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() @@ -465,14 +450,27 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) { set_api_version(debugprintf_api_version); - // Run standard create_instance() from framework (with set_api_version and layer settings support) and return + // Since layer settings extension is available, use it to configure validation layer for debugPrintfEXT + add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ false); + + 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); + + // Run standard create_instance() from framework with set_api_version(), add_instance_extension(), and add_layer_setting() support return VulkanSample::create_instance(headless); } // Run remainder of this custom create_instance() (without layer settings support) and return std::vector enabled_extensions; - enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - for (const char *extension_name : window->get_required_surface_extensions()) { enabled_extensions.push_back(extension_name); @@ -496,6 +494,9 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) app_info.pEngineName = "Vulkan Samples"; app_info.apiVersion = debugprintf_api_version; + // Legacy 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}; From 5fca9a673c944c13810ec01438a7cf6c80b95669 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:09:41 -0400 Subject: [PATCH 04/12] Fix VK_EXT_layer_settings string comparison in [HPP]Instance::[HPP]Instance() --- framework/core/hpp_instance.cpp | 4 +++- framework/core/instance.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/framework/core/hpp_instance.cpp b/framework/core/hpp_instance.cpp index 27d381b4b..098603dfe 100644 --- a/framework/core/hpp_instance.cpp +++ b/framework/core/hpp_instance.cpp @@ -354,7 +354,9 @@ 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 (std::any_of(enabled_extensions.begin(), + enabled_extensions.end(), + [](const char *extension) { return strcmp(extension, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 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 5a28e8be6..2c05aa8d3 100644 --- a/framework/core/instance.cpp +++ b/framework/core/instance.cpp @@ -383,7 +383,9 @@ 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 (std::any_of(enabled_extensions.begin(), + enabled_extensions.end(), + [](const char *extension) { return strcmp(extension, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) { layerSettingsCreateInfo.settingCount = static_cast(required_layer_settings.size()); layerSettingsCreateInfo.pSettings = required_layer_settings.data(); From badd40901df10d341b63188a24d7d20a96ea9af1 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Thu, 24 Oct 2024 01:27:11 -0400 Subject: [PATCH 05/12] When VK_EXT_layer_settings extension is available don't enable it during instance creation --- samples/extensions/shader_debugprintf/shader_debugprintf.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index d4f9556a8..c8c135c46 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -451,8 +451,6 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) set_api_version(debugprintf_api_version); // Since layer settings extension is available, use it to configure validation layer for debugPrintfEXT - add_instance_extension(VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /*optional*/ false); - VkLayerSettingEXT layerSetting; layerSetting.pLayerName = "VK_LAYER_KHRONOS_validation"; layerSetting.pSettingName = "enables"; @@ -465,7 +463,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) add_layer_setting(layerSetting); - // Run standard create_instance() from framework with set_api_version(), add_instance_extension(), and add_layer_setting() support + // Run standard create_instance() from framework with set_api_version() and add_layer_setting() support return VulkanSample::create_instance(headless); } From 918cef1360c7c131066fd2cd440e7462c5dafa79 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Thu, 24 Oct 2024 01:29:25 -0400 Subject: [PATCH 06/12] Check for VK_EXT_layer_settings available vs. enabled in [HPP]Instance::[HPP]Instance() --- framework/core/hpp_instance.cpp | 8 ++++---- framework/core/instance.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/framework/core/hpp_instance.cpp b/framework/core/hpp_instance.cpp index 098603dfe..c9782b470 100644 --- a/framework/core/hpp_instance.cpp +++ b/framework/core/hpp_instance.cpp @@ -353,10 +353,10 @@ 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::any_of(enabled_extensions.begin(), - enabled_extensions.end(), - [](const char *extension) { return strcmp(extension, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) + // If layer settings extension available, then activate the sample's layer settings during instance creation + 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; })) { 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 2c05aa8d3..79ba90b0f 100644 --- a/framework/core/instance.cpp +++ b/framework/core/instance.cpp @@ -382,10 +382,10 @@ 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::any_of(enabled_extensions.begin(), - enabled_extensions.end(), - [](const char *extension) { return strcmp(extension, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) + // If layer settings extension available, then activate the sample's layer settings during instance creation + 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; })) { layerSettingsCreateInfo.settingCount = static_cast(required_layer_settings.size()); layerSettingsCreateInfo.pSettings = required_layer_settings.data(); From 61c2d812e3706ec1fca9ebf0142236b6979173eb Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Thu, 24 Oct 2024 10:25:58 -0400 Subject: [PATCH 07/12] Use vk::ExtensionProperties vs. VkExtensionProperties in HPPInstance::HPPInstance() --- framework/core/hpp_instance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/core/hpp_instance.cpp b/framework/core/hpp_instance.cpp index c9782b470..1748db7d2 100644 --- a/framework/core/hpp_instance.cpp +++ b/framework/core/hpp_instance.cpp @@ -356,7 +356,7 @@ HPPInstance::HPPInstance(const std::string &applicati // If layer settings extension available, then activate the sample's layer settings during instance creation 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; })) + [](vk::ExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) { layerSettingsCreateInfo.settingCount = static_cast(required_layer_settings.size()); layerSettingsCreateInfo.pSettings = required_layer_settings.data(); From e23c4e5d4e8233fe3c247d976c63d5a3eca926fe Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Fri, 25 Oct 2024 11:46:13 -0400 Subject: [PATCH 08/12] Update comments and explicitly request required GPU features for debugPrintfEXT (cherry picked from commit 3365c7d974ae1cb7222cf35fdbe82accfa3fd926) --- .../shader_debugprintf/shader_debugprintf.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index c8c135c46..deaa0828a 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -68,6 +68,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) { @@ -467,8 +472,10 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) return VulkanSample::create_instance(headless); } - // 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); + for (const char *extension_name : window->get_required_surface_extensions()) { enabled_extensions.push_back(extension_name); @@ -492,7 +499,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) app_info.pEngineName = "Vulkan Samples"; app_info.apiVersion = debugprintf_api_version; - // Legacy extension for configuring validation layer features using VkValidationFeaturesEXT + // 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 From bf7c37d9163e251ed7dba61cc93e7c09184e35df Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Tue, 29 Oct 2024 22:07:14 -0400 Subject: [PATCH 09/12] Check for defined layer settings before chaining-in layerSettingsCreateInfo in [HPP]Instance::[HPP]Instance() --- framework/core/hpp_instance.cpp | 6 ++---- framework/core/instance.cpp | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/framework/core/hpp_instance.cpp b/framework/core/hpp_instance.cpp index 1748db7d2..21abdeb96 100644 --- a/framework/core/hpp_instance.cpp +++ b/framework/core/hpp_instance.cpp @@ -353,10 +353,8 @@ HPPInstance::HPPInstance(const std::string &applicati vk::LayerSettingsCreateInfoEXT layerSettingsCreateInfo; - // If layer settings extension available, then activate the sample's layer settings during instance creation - if (std::any_of(available_instance_extensions.begin(), - available_instance_extensions.end(), - [](vk::ExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) + // 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 79ba90b0f..19acdda22 100644 --- a/framework/core/instance.cpp +++ b/framework/core/instance.cpp @@ -382,10 +382,8 @@ Instance::Instance(const std::string &application_nam VkLayerSettingsCreateInfoEXT layerSettingsCreateInfo{VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT}; - // If layer settings extension available, then activate the sample's layer settings during instance creation - 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; })) + // 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(); From 7484c6bde477b9431901e2206ddcadbf87ddc8d8 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Tue, 29 Oct 2024 22:17:56 -0400 Subject: [PATCH 10/12] Check VVL instance extensions for VK_EXT_layer_settings and use #define for VVL layer name --- .../shader_debugprintf/shader_debugprintf.cpp | 84 +++++++++++-------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index deaa0828a..5f1e4871a 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -19,6 +19,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( @@ -414,7 +416,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; @@ -423,6 +425,8 @@ 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(bool headless) { + auto debugprintf_api_version = VK_API_VERSION_1_1; + // 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; @@ -432,44 +436,50 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) const auto vvl_properties = std::find_if(layer_properties.begin(), layer_properties.end(), - [](VkLayerProperties const &properties) { return strcmp(properties.layerName, "VK_LAYER_KHRONOS_validation") == 0; }); + [](VkLayerProperties const &properties) { return strcmp(properties.layerName, validation_layer_name) == 0; }); - // 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) - auto debugprintf_api_version = VK_API_VERSION_1_1; - if (vvl_properties != layer_properties.end() && vvl_properties->specVersion <= VK_MAKE_API_VERSION(0, 1, 3, 290)) + // 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()) { - debugprintf_api_version = VK_API_VERSION_1_2; - } - - 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())); + // 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; + } - // 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(available_instance_extensions.begin(), - available_instance_extensions.end(), - [](VkExtensionProperties const &extension) { return strcmp(extension.extensionName, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0; })) - { - set_api_version(debugprintf_api_version); + // 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 = "VK_LAYER_KHRONOS_validation"; - layerSetting.pSettingName = "enables"; - layerSetting.type = VK_LAYER_SETTING_TYPE_STRING_EXT; - layerSetting.valueCount = 1; + // 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 constructor scope - static const char *layerEnables = "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT"; - layerSetting.pValues = &layerEnables; + // 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; - add_layer_setting(layerSetting); + add_layer_setting(layerSetting); - // Run standard create_instance() from framework with set_api_version() and add_layer_setting() support - return VulkanSample::create_instance(headless); + // Run standard create_instance() from framework with set_api_version() and add_layer_setting() support + return VulkanSample::create_instance(headless); + } } // As a fallack, run remainder of this custom create_instance() override (without layer settings support) and return @@ -483,7 +493,15 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) 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(), @@ -509,7 +527,7 @@ std::unique_ptr ShaderDebugPrintf::create_instance(bool headless) 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(); From 37d3dc6d8b4f9adf7b68fdf31218a379f2794ce8 Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Fri, 7 Feb 2025 10:47:57 -0500 Subject: [PATCH 11/12] Check for required GPU features otherwise throw exception with error message --- .../shader_debugprintf/shader_debugprintf.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 06e5b370d..1fb100452 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -71,15 +71,25 @@ ShaderDebugPrintf::~ShaderDebugPrintf() void ShaderDebugPrintf::request_gpu_features(vkb::PhysicalDevice &gpu) { + auto const &supportedFeatures = gpu.get_features(); + auto &requestedFeatures = gpu.get_mutable_requested_features(); + // 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; + if (supportedFeatures.fragmentStoresAndAtomics && supportedFeatures.vertexPipelineStoresAndAtomics && supportedFeatures.shaderInt64) + { + requestedFeatures.fragmentStoresAndAtomics = VK_TRUE; + requestedFeatures.vertexPipelineStoresAndAtomics = VK_TRUE; + requestedFeatures.shaderInt64 = VK_TRUE; + } + else + { + throw vkb::VulkanException(VK_ERROR_FEATURE_NOT_PRESENT, "Selected GPU does not support features fragmentStoresAndAtomics, vertexPipelineStoresAndAtomics, and/or shaderInt64"); + } // Enable anisotropic filtering if supported - if (gpu.get_features().samplerAnisotropy) + if (supportedFeatures.samplerAnisotropy) { - gpu.get_mutable_requested_features().samplerAnisotropy = VK_TRUE; + requestedFeatures.samplerAnisotropy = VK_TRUE; } } From cbe92fc98b4ca7993f4fcfb2f9ccfef4db4843df Mon Sep 17 00:00:00 2001 From: SRSaunders <82544213+SRSaunders@users.noreply.github.com> Date: Fri, 7 Feb 2025 10:59:38 -0500 Subject: [PATCH 12/12] Update copyright year for all affected files --- framework/core/hpp_instance.cpp | 4 ++-- framework/core/instance.cpp | 2 +- samples/extensions/shader_debugprintf/shader_debugprintf.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/core/hpp_instance.cpp b/framework/core/hpp_instance.cpp index 1bc0286c4..37d9456e1 100644 --- a/framework/core/hpp_instance.cpp +++ b/framework/core/hpp_instance.cpp @@ -1,5 +1,5 @@ -/* Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. - * Copyright (c) 2024, Arm Limited and Contributors +/* Copyright (c) 2022-2025, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2024-2025, Arm Limited and Contributors * * SPDX-License-Identifier: Apache-2.0 * diff --git a/framework/core/instance.cpp b/framework/core/instance.cpp index 9b277f4aa..50d7e7629 100644 --- a/framework/core/instance.cpp +++ b/framework/core/instance.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2024, Arm Limited and Contributors +/* Copyright (c) 2018-2025, Arm Limited and Contributors * * SPDX-License-Identifier: Apache-2.0 * diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 1fb100452..4fe7da860 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -1,5 +1,5 @@ /* Copyright (c) 2024, Sascha Willems - * Copyright (c) 2024, Arm Limited and Contributors + * Copyright (c) 2024-2025, Arm Limited and Contributors * * SPDX-License-Identifier: Apache-2.0 *