Skip to content

Commit 43c23e5

Browse files
authored
shader_debugprintf: support new VVL-DEBUG-PRINTF message and fix VVL version check for API selection (#1187)
* shader_debugprintf: support new VVL-DEBUG-PRINTF message and fix VVL version check for API selection * Incorporate review feedback: update comments and simpify code * Add VK_EXT_validation_features and move VK_EXT_layer_settings extensions to ShaderDebugPrintf::create_instance() * Fix VK_EXT_layer_settings string comparison in [HPP]Instance::[HPP]Instance() * When VK_EXT_layer_settings extension is available don't enable it during instance creation * Check for VK_EXT_layer_settings available vs. enabled in [HPP]Instance::[HPP]Instance() * Use vk::ExtensionProperties vs. VkExtensionProperties in HPPInstance::HPPInstance() * Update comments and explicitly request required GPU features for debugPrintfEXT (cherry picked from commit 3365c7d974ae1cb7222cf35fdbe82accfa3fd926) * Check for defined layer settings before chaining-in layerSettingsCreateInfo in [HPP]Instance::[HPP]Instance() * Check VVL instance extensions for VK_EXT_layer_settings and use #define for VVL layer name * Check for required GPU features otherwise throw exception with error message * Update copyright year for all affected files * Review: Remove shaderInt64 feature request, Use %v3f shader print format * Fix copyright dates in updated shaders * Update hwcpipe submodule to match main branch
1 parent aaccd0c commit 43c23e5

File tree

6 files changed

+110
-63
lines changed

6 files changed

+110
-63
lines changed

framework/core/hpp_instance.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ HPPInstance::HPPInstance(const std::string &applicati
311311

312312
vk::LayerSettingsCreateInfoEXT layerSettingsCreateInfo;
313313

314-
// If layer settings extension enabled by sample, then activate layer settings during instance creation
315-
if (std::find(enabled_extensions.begin(), enabled_extensions.end(), VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) != enabled_extensions.end())
314+
// If layer settings are defined, then activate the sample's required layer settings during instance creation
315+
if (required_layer_settings.size() > 0)
316316
{
317317
layerSettingsCreateInfo.settingCount = static_cast<uint32_t>(required_layer_settings.size());
318318
layerSettingsCreateInfo.pSettings = required_layer_settings.data();

framework/core/instance.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ Instance::Instance(const std::string &application_nam
340340

341341
VkLayerSettingsCreateInfoEXT layerSettingsCreateInfo{VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT};
342342

343-
// If layer settings extension enabled by sample, then activate layer settings during instance creation
344-
if (std::find(enabled_extensions.begin(), enabled_extensions.end(), VK_EXT_LAYER_SETTINGS_EXTENSION_NAME) != enabled_extensions.end())
343+
// If layer settings are defined, then activate the sample's required layer settings during instance creation
344+
if (required_layer_settings.size() > 0)
345345
{
346346
layerSettingsCreateInfo.settingCount = static_cast<uint32_t>(required_layer_settings.size());
347347
layerSettingsCreateInfo.pSettings = required_layer_settings.data();

samples/extensions/shader_debugprintf/shader_debugprintf.cpp

Lines changed: 87 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include "scene_graph/components/sub_mesh.h"
2222

23+
#define validation_layer_name "VK_LAYER_KHRONOS_validation"
24+
2325
std::string ShaderDebugPrintf::debug_output{};
2426

2527
VKAPI_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

6754
ShaderDebugPrintf::~ShaderDebugPrintf()
@@ -86,10 +73,24 @@ ShaderDebugPrintf::~ShaderDebugPrintf()
8673

8774
void 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
423424
std::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();

samples/extensions/shader_debugprintf/shader_debugprintf.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,21 @@ class ShaderDebugPrintf : public ApiVulkanSample
8282

8383
ShaderDebugPrintf();
8484
~ShaderDebugPrintf();
85-
virtual void request_gpu_features(vkb::PhysicalDevice &gpu) override;
86-
void build_command_buffers() override;
87-
void load_assets();
88-
void setup_descriptor_pool();
89-
void setup_descriptor_set_layout();
90-
void setup_descriptor_sets();
91-
void prepare_pipelines();
92-
void prepare_uniform_buffers();
93-
void update_uniform_buffers();
94-
void draw();
95-
bool prepare(const vkb::ApplicationOptions &options) override;
96-
std::unique_ptr<vkb::Instance> create_instance() override;
97-
virtual void render(float delta_time) override;
98-
virtual void on_update_ui_overlay(vkb::Drawer &drawer) override;
99-
virtual bool resize(const uint32_t width, const uint32_t height) override;
85+
virtual void request_gpu_features(vkb::PhysicalDevice &gpu) override;
86+
void build_command_buffers() override;
87+
void load_assets();
88+
void setup_descriptor_pool();
89+
void setup_descriptor_set_layout();
90+
void setup_descriptor_sets();
91+
void prepare_pipelines();
92+
void prepare_uniform_buffers();
93+
void update_uniform_buffers();
94+
void draw();
95+
bool prepare(const vkb::ApplicationOptions &options) override;
96+
std::unique_ptr<vkb::Instance> create_instance() override;
97+
virtual void render(float delta_time) override;
98+
virtual void on_update_ui_overlay(vkb::Drawer &drawer) override;
99+
virtual bool resize(const uint32_t width, const uint32_t height) override;
100100
};
101101

102102
std::unique_ptr<vkb::Application> create_shader_debugprintf();

shaders/shader_debugprintf/glsl/scene.vert

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#version 450
2-
/* Copyright (c) 2024, Sascha Willems
2+
/* Copyright (c) 2024-2025, Sascha Willems
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*
@@ -63,6 +63,6 @@ void main()
6363

6464
// Output the vertex position using debug printf
6565
if (gl_VertexIndex == 0) {
66-
debugPrintfEXT("Position = %v4f", outPos);
66+
debugPrintfEXT("Position = %v3f", outPos);
6767
}
6868
}

shaders/shader_debugprintf/hlsl/scene.vert.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2024, Sascha Willems
1+
/* Copyright (c) 2024-2025, Sascha Willems
22
*
33
* SPDX-License-Identifier: Apache-2.0
44
*
@@ -75,7 +75,7 @@ VSOutput main(VSInput input)
7575

7676
// Output the vertex position using debug printf
7777
if (input.VertexIndex == 0) {
78-
printf("Position = %v4f", output.Pos);
78+
printf("Position = %v3f", output.Pos);
7979
}
8080

8181
return output;

0 commit comments

Comments
 (0)