2020
2121#include " scene_graph/components/sub_mesh.h"
2222
23+ #define validation_layer_name " VK_LAYER_KHRONOS_validation"
24+
2325std::string ShaderDebugPrintf::debug_output{};
2426
2527VKAPI_ATTR VkBool32 VKAPI_CALL ShaderDebugPrintf::debug_utils_message_callback (
@@ -28,11 +30,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ShaderDebugPrintf::debug_utils_message_callback(
2830 const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
2931 void *pUserData)
3032{
31- // Look for Validation Layer message id names: WARNING-DEBUG-PRINTF or UNASSIGNED-DEBUG-PRINTF (have observed UNASSIGNED with older Vulkan SDKs)
32- if (strcmp (pCallbackData->pMessageIdName , " WARNING-DEBUG-PRINTF" ) == 0 || strcmp (pCallbackData->pMessageIdName , " UNASSIGNED-DEBUG-PRINTF" ) == 0 )
33+ // 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)
34+ if (strcmp (pCallbackData->pMessageIdName , " VVL-DEBUG-PRINTF " ) == 0 || strcmp (pCallbackData-> pMessageIdName , " WARNING-DEBUG-PRINTF" ) == 0 || strcmp (pCallbackData->pMessageIdName , " UNASSIGNED-DEBUG-PRINTF" ) == 0 )
3335 {
3436 // 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
35- // See scene.vert: debugPrintfEXT("Position = %v4f ", outPos);
37+ // See scene.vert: debugPrintfEXT("Position = %v3f ", outPos);
3638 std::string shader_message{pCallbackData->pMessage };
3739 shader_message = shader_message.substr (shader_message.find (" Position" ));
3840 debug_output.append (shader_message + " \n " );
@@ -46,22 +48,7 @@ ShaderDebugPrintf::ShaderDebugPrintf()
4648
4749 add_device_extension (VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME);
4850
49- // If layer settings available, use it to configure validation layer for debugPrintfEXT
50- add_instance_extension (VK_EXT_LAYER_SETTINGS_EXTENSION_NAME, /* optional*/ true );
51-
52- add_instance_layer (" VK_LAYER_KHRONOS_shader_object" );
53-
54- VkLayerSettingEXT layerSetting;
55- layerSetting.pLayerName = " VK_LAYER_KHRONOS_validation" ;
56- layerSetting.pSettingName = " enables" ;
57- layerSetting.type = VK_LAYER_SETTING_TYPE_STRING_EXT;
58- layerSetting.valueCount = 1 ;
59-
60- // Make this static so layer setting reference remains valid after leaving constructor scope
61- static const char *layerEnables = " VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT" ;
62- layerSetting.pValues = &layerEnables;
63-
64- add_layer_setting (layerSetting);
51+ add_instance_layer (validation_layer_name);
6552}
6653
6754ShaderDebugPrintf::~ShaderDebugPrintf ()
@@ -86,10 +73,24 @@ ShaderDebugPrintf::~ShaderDebugPrintf()
8673
8774void ShaderDebugPrintf::request_gpu_features (vkb::PhysicalDevice &gpu)
8875{
76+ auto const &supportedFeatures = gpu.get_features ();
77+ auto &requestedFeatures = gpu.get_mutable_requested_features ();
78+
79+ // debugPrintfEXT requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics
80+ if (supportedFeatures.fragmentStoresAndAtomics && supportedFeatures.vertexPipelineStoresAndAtomics )
81+ {
82+ requestedFeatures.fragmentStoresAndAtomics = VK_TRUE;
83+ requestedFeatures.vertexPipelineStoresAndAtomics = VK_TRUE;
84+ }
85+ else
86+ {
87+ throw vkb::VulkanException (VK_ERROR_FEATURE_NOT_PRESENT, " Selected GPU does not support features fragmentStoresAndAtomics and/or vertexPipelineStoresAndAtomics" );
88+ }
89+
8990 // Enable anisotropic filtering if supported
90- if (gpu. get_features () .samplerAnisotropy )
91+ if (supportedFeatures .samplerAnisotropy )
9192 {
92- gpu. get_mutable_requested_features () .samplerAnisotropy = VK_TRUE;
93+ requestedFeatures .samplerAnisotropy = VK_TRUE;
9394 }
9495}
9596
@@ -422,29 +423,64 @@ bool ShaderDebugPrintf::prepare(const vkb::ApplicationOptions &options)
422423// This sample overrides the instance creation part of the framework to chain in additional structures
423424std::unique_ptr<vkb::Instance> ShaderDebugPrintf::create_instance ()
424425{
425- uint32_t instanceApiVersion;
426- VK_CHECK (vkEnumerateInstanceVersion (&instanceApiVersion));
426+ auto debugprintf_api_version = VK_API_VERSION_1_1;
427427
428- uint32_t instance_extension_count;
429- VK_CHECK (vkEnumerateInstanceExtensionProperties (nullptr , &instance_extension_count, nullptr ));
430- std::vector<VkExtensionProperties> available_instance_extensions (instance_extension_count);
431- VK_CHECK (vkEnumerateInstanceExtensionProperties (nullptr , &instance_extension_count, available_instance_extensions.data ()));
428+ // Enumerate all instance layer properties so we can find and use the validation layer (VVL) version in subsequent steps
429+ // The VVL version is needed to work around validation layer performance issues when running with Vulkan SDKs <= 1.3.290
430+ uint32_t layer_property_count;
431+ VK_CHECK (vkEnumerateInstanceLayerProperties (&layer_property_count, nullptr ));
432+ std::vector<VkLayerProperties> layer_properties (layer_property_count);
433+ VK_CHECK (vkEnumerateInstanceLayerProperties (&layer_property_count, layer_properties.data ()));
432434
433- // When VK_EXT_layer_settings is available at runtime, the debugPrintfEXT layer feature is enabled using the standard framework
434- // For backwards compatibility with SDKs < 1.3.272 without VK_EXT_layer_settings, the remainder of this custom override is required
435- if (std::any_of (available_instance_extensions.begin (),
436- available_instance_extensions.end (),
437- [](VkExtensionProperties const &extension) { return strcmp (extension.extensionName , VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0 ; }))
435+ const auto vvl_properties = std::find_if (layer_properties.begin (),
436+ layer_properties.end (),
437+ [](VkLayerProperties const &properties) { return strcmp (properties.layerName , validation_layer_name) == 0 ; });
438+
439+ // Make sure we have found the validation layer before checking the VVL version and enumerating VVL instance extensions for VK_EXT_layer_settings
440+ if (vvl_properties != layer_properties.end ())
438441 {
439- // debugPrintfEXT layer feature requires Vulkan API 1.1, but use API 1.2 until VVL performance fix is available in SDKs > 1.3.290
440- // See VVL issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7562 for defect and fix information
441- set_api_version (instanceApiVersion <= VK_MAKE_API_VERSION (0 , 1 , 3 , 290 ) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1);
442+ // 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
443+ // See VVL issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/7562 for defect and fix information (fix available in SDK 1.3.296)
444+ // Note: An additional, unrelated VVL performance issue affecting nVidia GPUs was found in SDK 1.3.296 following release - for nVidia GPUs please
445+ // use SDK 1.3.290 until a fix is made available in a later SDK (see https://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/8766).
446+ if (vvl_properties->specVersion <= VK_MAKE_API_VERSION (0 , 1 , 3 , 290 ))
447+ {
448+ debugprintf_api_version = VK_API_VERSION_1_2;
449+ }
450+
451+ // Enumerate all instance extensions for the validation layer to determine if VK_EXT_layer_settings is supported by the layer
452+ uint32_t vvl_extension_count;
453+ VK_CHECK (vkEnumerateInstanceExtensionProperties (validation_layer_name, &vvl_extension_count, nullptr ));
454+ std::vector<VkExtensionProperties> vvl_instance_extensions (vvl_extension_count);
455+ VK_CHECK (vkEnumerateInstanceExtensionProperties (validation_layer_name, &vvl_extension_count, vvl_instance_extensions.data ()));
456+
457+ // When VK_EXT_layer_settings is available at runtime, the debugPrintfEXT layer feature is enabled using the standard framework
458+ // For this case set Vulkan API version and return via base class, otherwise the remainder of this custom override is required
459+ if (std::any_of (vvl_instance_extensions.begin (),
460+ vvl_instance_extensions.end (),
461+ [](VkExtensionProperties const &extension) { return strcmp (extension.extensionName , VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) == 0 ; }))
462+ {
463+ set_api_version (debugprintf_api_version);
464+
465+ // Since layer settings extension is available, use it to configure validation layer for debugPrintfEXT
466+ VkLayerSettingEXT layerSetting;
467+ layerSetting.pLayerName = validation_layer_name;
468+ layerSetting.pSettingName = " enables" ;
469+ layerSetting.type = VK_LAYER_SETTING_TYPE_STRING_EXT;
470+ layerSetting.valueCount = 1 ;
442471
443- // Run standard create_instance() from framework (with set_api_version and layer settings support) and return
444- return VulkanSample::create_instance ();
472+ // Make this static so layer setting reference remains valid after leaving the current scope
473+ static const char *layerEnables = " VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT" ;
474+ layerSetting.pValues = &layerEnables;
475+
476+ add_layer_setting (layerSetting);
477+
478+ // Run standard create_instance() from framework with set_api_version() and add_layer_setting() support
479+ return VulkanSample::create_instance ();
480+ }
445481 }
446482
447- // Run remainder of this custom create_instance() (without layer settings support) and return
483+ // As a fallack, run remainder of this custom create_instance() override (without layer settings support) and return
448484 std::vector<const char *> enabled_extensions;
449485 enabled_extensions.push_back (VK_KHR_SURFACE_EXTENSION_NAME);
450486
@@ -455,7 +491,15 @@ std::unique_ptr<vkb::Instance> ShaderDebugPrintf::create_instance()
455491
456492 enabled_extensions.push_back (VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
457493 enabled_extensions.push_back (VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
494+
458495#if (defined(VKB_ENABLE_PORTABILITY))
496+ // Enumerate all instance extensions for the loader + driver to determine if VK_KHR_portability_enumeration is available
497+ uint32_t available_extension_count;
498+ VK_CHECK (vkEnumerateInstanceExtensionProperties (nullptr , &available_extension_count, nullptr ));
499+ std::vector<VkExtensionProperties> available_instance_extensions (available_extension_count);
500+ VK_CHECK (vkEnumerateInstanceExtensionProperties (nullptr , &available_extension_count, available_instance_extensions.data ()));
501+
502+ // If VK_KHR_portability_enumeration is available in the portability implementation, then we must enable the extension
459503 bool portability_enumeration_available = false ;
460504 if (std::any_of (available_instance_extensions.begin (),
461505 available_instance_extensions.end (),
@@ -469,7 +513,10 @@ std::unique_ptr<vkb::Instance> ShaderDebugPrintf::create_instance()
469513 VkApplicationInfo app_info{VK_STRUCTURE_TYPE_APPLICATION_INFO};
470514 app_info.pApplicationName = " Shader debugprintf" ;
471515 app_info.pEngineName = " Vulkan Samples" ;
472- app_info.apiVersion = instanceApiVersion <= VK_MAKE_API_VERSION (0 , 1 , 3 , 290 ) ? VK_API_VERSION_1_2 : VK_API_VERSION_1_1;
516+ app_info.apiVersion = debugprintf_api_version;
517+
518+ // Enable VK_EXT_validation_features extension for configuring validation layer features using VkValidationFeaturesEXT
519+ enabled_extensions.push_back (VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME);
473520
474521 // Shader printf is a feature of the validation layers that needs to be enabled
475522 std::vector<VkValidationFeatureEnableEXT> validation_feature_enables = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT};
@@ -478,7 +525,7 @@ std::unique_ptr<vkb::Instance> ShaderDebugPrintf::create_instance()
478525 validation_features.enabledValidationFeatureCount = static_cast <uint32_t >(validation_feature_enables.size ());
479526 validation_features.pEnabledValidationFeatures = validation_feature_enables.data ();
480527
481- std::vector<const char *> validation_layers = {" VK_LAYER_KHRONOS_validation " };
528+ std::vector<const char *> validation_layers = {validation_layer_name };
482529
483530 VkInstanceCreateInfo instance_create_info{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
484531 instance_create_info.ppEnabledExtensionNames = enabled_extensions.data ();
0 commit comments