Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
8c00ce4
shader_debugprintf: support new VVL-DEBUG-PRINTF message and fix VVL …
SRSaunders Oct 9, 2024
0dc4963
Incorporate review feedback: update comments and simpify code
SRSaunders Oct 22, 2024
4f53d15
Add VK_EXT_validation_features and move VK_EXT_layer_settings extensi…
SRSaunders Oct 23, 2024
5fca9a6
Fix VK_EXT_layer_settings string comparison in [HPP]Instance::[HPP]In…
SRSaunders Oct 23, 2024
badd409
When VK_EXT_layer_settings extension is available don't enable it dur…
SRSaunders Oct 24, 2024
918cef1
Check for VK_EXT_layer_settings available vs. enabled in [HPP]Instanc…
SRSaunders Oct 24, 2024
61c2d81
Use vk::ExtensionProperties vs. VkExtensionProperties in HPPInstance:…
SRSaunders Oct 24, 2024
e23c4e5
Update comments and explicitly request required GPU features for debu…
SRSaunders Oct 25, 2024
bf7c37d
Check for defined layer settings before chaining-in layerSettingsCrea…
SRSaunders Oct 30, 2024
7484c6b
Check VVL instance extensions for VK_EXT_layer_settings and use #defi…
SRSaunders Oct 30, 2024
6b7f548
Merge branch 'main' into debugprintf-2
SRSaunders Nov 18, 2024
6b9329a
Merge branch 'KhronosGroup:main' into debugprintf-2
SRSaunders Nov 18, 2024
37d3dc6
Check for required GPU features otherwise throw exception with error …
SRSaunders Feb 7, 2025
cbe92fc
Update copyright year for all affected files
SRSaunders Feb 7, 2025
2969e5b
Merge branch 'main'
SRSaunders Feb 25, 2025
fc26c16
Review: Remove shaderInt64 feature request, Use %v3f shader print format
SRSaunders Feb 25, 2025
00d0408
Fix copyright dates in updated shaders
SRSaunders Feb 25, 2025
839291f
Update hwcpipe submodule to match main branch
SRSaunders Feb 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions framework/core/hpp_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,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<uint32_t>(required_layer_settings.size());
layerSettingsCreateInfo.pSettings = required_layer_settings.data();
Expand Down
4 changes: 2 additions & 2 deletions framework/core/instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,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<uint32_t>(required_layer_settings.size());
layerSettingsCreateInfo.pSettings = required_layer_settings.data();
Expand Down
127 changes: 87 additions & 40 deletions samples/extensions/shader_debugprintf/shader_debugprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -28,11 +30,11 @@ 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);
// See scene.vert: debugPrintfEXT("Position = %v3f", outPos);
std::string shader_message{pCallbackData->pMessage};
shader_message = shader_message.substr(shader_message.find("Position"));
debug_output.append(shader_message + "\n");
Expand All @@ -46,22 +48,7 @@ ShaderDebugPrintf::ShaderDebugPrintf()

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);

add_instance_layer("VK_LAYER_KHRONOS_shader_object");

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);
add_instance_layer(validation_layer_name);
}

ShaderDebugPrintf::~ShaderDebugPrintf()
Expand All @@ -86,10 +73,24 @@ 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 and vertexPipelineStoresAndAtomics
if (supportedFeatures.fragmentStoresAndAtomics && supportedFeatures.vertexPipelineStoresAndAtomics)
{
requestedFeatures.fragmentStoresAndAtomics = VK_TRUE;
requestedFeatures.vertexPipelineStoresAndAtomics = VK_TRUE;
}
else
{
throw vkb::VulkanException(VK_ERROR_FEATURE_NOT_PRESENT, "Selected GPU does not support features fragmentStoresAndAtomics and/or vertexPipelineStoresAndAtomics");
}

// 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;
}
}

Expand Down Expand Up @@ -422,29 +423,64 @@ bool ShaderDebugPrintf::prepare(const vkb::ApplicationOptions &options)
// This sample overrides the instance creation part of the framework to chain in additional structures
std::unique_ptr<vkb::Instance> 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<VkExtensionProperties> 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<VkLayerProperties> 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<VkExtensionProperties> 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;

// Run standard create_instance() from framework (with set_api_version and layer settings support) and return
return VulkanSample::create_instance();
// 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);

// 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<const char *> enabled_extensions;
enabled_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);

Expand All @@ -455,7 +491,15 @@ std::unique_ptr<vkb::Instance> 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<VkExtensionProperties> 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(),
Expand All @@ -469,7 +513,10 @@ std::unique_ptr<vkb::Instance> 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<VkValidationFeatureEnableEXT> validation_feature_enables = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT};
Expand All @@ -478,7 +525,7 @@ std::unique_ptr<vkb::Instance> ShaderDebugPrintf::create_instance()
validation_features.enabledValidationFeatureCount = static_cast<uint32_t>(validation_feature_enables.size());
validation_features.pEnabledValidationFeatures = validation_feature_enables.data();

std::vector<const char *> validation_layers = {"VK_LAYER_KHRONOS_validation"};
std::vector<const char *> validation_layers = {validation_layer_name};

VkInstanceCreateInfo instance_create_info{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
instance_create_info.ppEnabledExtensionNames = enabled_extensions.data();
Expand Down
30 changes: 15 additions & 15 deletions samples/extensions/shader_debugprintf/shader_debugprintf.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,21 @@ class ShaderDebugPrintf : public ApiVulkanSample

ShaderDebugPrintf();
~ShaderDebugPrintf();
virtual void request_gpu_features(vkb::PhysicalDevice &gpu) override;
void build_command_buffers() override;
void load_assets();
void setup_descriptor_pool();
void setup_descriptor_set_layout();
void setup_descriptor_sets();
void prepare_pipelines();
void prepare_uniform_buffers();
void update_uniform_buffers();
void draw();
bool prepare(const vkb::ApplicationOptions &options) override;
std::unique_ptr<vkb::Instance> create_instance() override;
virtual void render(float delta_time) override;
virtual void on_update_ui_overlay(vkb::Drawer &drawer) override;
virtual bool resize(const uint32_t width, const uint32_t height) override;
virtual void request_gpu_features(vkb::PhysicalDevice &gpu) override;
void build_command_buffers() override;
void load_assets();
void setup_descriptor_pool();
void setup_descriptor_set_layout();
void setup_descriptor_sets();
void prepare_pipelines();
void prepare_uniform_buffers();
void update_uniform_buffers();
void draw();
bool prepare(const vkb::ApplicationOptions &options) override;
std::unique_ptr<vkb::Instance> create_instance() override;
virtual void render(float delta_time) override;
virtual void on_update_ui_overlay(vkb::Drawer &drawer) override;
virtual bool resize(const uint32_t width, const uint32_t height) override;
};

std::unique_ptr<vkb::Application> create_shader_debugprintf();
4 changes: 2 additions & 2 deletions shaders/shader_debugprintf/glsl/scene.vert
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#version 450
/* Copyright (c) 2024, Sascha Willems
/* Copyright (c) 2024-2025, Sascha Willems
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -63,6 +63,6 @@ void main()

// Output the vertex position using debug printf
if (gl_VertexIndex == 0) {
debugPrintfEXT("Position = %v4f", outPos);
debugPrintfEXT("Position = %v3f", outPos);
}
}
4 changes: 2 additions & 2 deletions shaders/shader_debugprintf/hlsl/scene.vert.hlsl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2024, Sascha Willems
/* Copyright (c) 2024-2025, Sascha Willems
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -75,7 +75,7 @@ VSOutput main(VSInput input)

// Output the vertex position using debug printf
if (input.VertexIndex == 0) {
printf("Position = %v4f", output.Pos);
printf("Position = %v3f", output.Pos);
}

return output;
Expand Down
Loading