diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index fc52c0306a..53071ddb07 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -49,6 +49,7 @@ set(FRAMEWORK_FILES hpp_resource_record.h hpp_resource_replay.h hpp_semaphore_pool.h + structure_chain_builder.h # Source Files drawer.cpp spirv_reflection.cpp diff --git a/framework/common/helpers.h b/framework/common/helpers.h index 80705c68d2..79314d8fd3 100644 --- a/framework/common/helpers.h +++ b/framework/common/helpers.h @@ -41,9 +41,14 @@ namespace vkb { +inline bool contains(uint32_t range_count, char const *const *range, char const *value) +{ + return std::any_of(range, range + range_count, [value](char const *range_value) { return strcmp(range_value, value) == 0; }); +} + inline bool contains(std::vector const &range, char const *value) { - return std::ranges::find_if(range, [value](std::string const &range_value) { return range_value == value; }) != range.end(); + return std::ranges::any_of(range, [value](std::string const &range_value) { return range_value == value; }); } template diff --git a/framework/core/instance.h b/framework/core/instance.h index 1b009255f8..b8a86d7b5a 100644 --- a/framework/core/instance.h +++ b/framework/core/instance.h @@ -19,6 +19,7 @@ #pragma once #include "common/helpers.h" +#include "structure_chain_builder.h" #include namespace vkb @@ -39,11 +40,6 @@ typename std::conditional const &, std::vector const &) -{ - return nullptr; -} } // namespace /** @@ -57,6 +53,7 @@ class Instance { public: using InstanceCreateFlagsType = typename std::conditional::type; + using InstanceCreateInfoType = typename std::conditional::type; using InstanceType = typename std::conditional::type; public: @@ -66,17 +63,17 @@ class Instance * @param api_version The Vulkan API version that the instance will be using * @param requested_layers The requested layers to be enabled * @param requested_extensions The requested extensions to be enabled - * @param get_pNext A function pointer returning the pNext pointer for the InstanceCreateInfo * @param get_create_flags A function pointer returning the InstanceCreateFlags for the InstanceCreateInfo + * @param extend_instance_create_info A function pointer to extend the InstanceCreateInfo with additional structures in the pNext chain * @throws runtime_error if a required layer or extension is not available */ Instance( - std::string const &application_name, - uint32_t api_version = VK_API_VERSION_1_1, - std::unordered_map const &requested_layers = {}, - std::unordered_map const &requested_extensions = {}, - std::function const &, std::vector const &)> const &get_pNext = get_default_pNext, - std::function const &)> const &get_create_flags = get_default_create_flags); + std::string const &application_name, + uint32_t api_version = VK_API_VERSION_1_1, + std::unordered_map const &requested_layers = {}, + std::unordered_map const &requested_extensions = {}, + std::function const &)> const &get_create_flags = get_default_create_flags, + std::function &)> const &extend_instance_create_info = [](vkb::StructureChainBuilder const &) {}); Instance(vk::Instance instance, std::vector const &externally_enabled_extensions = {}, bool needsToInitializeDispatcher = false); Instance(VkInstance instance, std::vector const &externally_enabled_extensions = {}); @@ -158,12 +155,12 @@ inline bool } // namespace template -inline Instance::Instance(std::string const &application_name, - uint32_t api_version, - std::unordered_map const &requested_layers, - std::unordered_map const &requested_extensions, - std::function const &, std::vector const &)> const &get_pNext, - std::function const &)> const &get_create_flags) +inline Instance::Instance(std::string const &application_name, + uint32_t api_version, + std::unordered_map const &requested_layers, + std::unordered_map const &requested_extensions, + std::function const &)> const &get_create_flags, + std::function &)> const &extend_instance_create_info) { // check API version LOGI("Requesting Vulkan API version {}.{}", VK_VERSION_MAJOR(api_version), VK_VERSION_MINOR(api_version)); @@ -243,16 +240,26 @@ inline Instance::Instance(std::string const vk::ApplicationInfo app_info{.pApplicationName = application_name.c_str(), .pEngineName = "Vulkan Samples", .apiVersion = api_version}; - vk::InstanceCreateInfo create_info{.pNext = get_pNext(enabled_layers, enabled_extensions), - .flags = static_cast(get_create_flags(enabled_extensions)), + vk::InstanceCreateInfo create_info{.flags = static_cast(get_create_flags(enabled_extensions)), .pApplicationInfo = &app_info, .enabledLayerCount = static_cast(enabled_layers_cstr.size()), .ppEnabledLayerNames = enabled_layers_cstr.data(), .enabledExtensionCount = static_cast(enabled_extensions_cstr.size()), .ppEnabledExtensionNames = enabled_extensions_cstr.data()}; + vkb::StructureChainBuilder scb; + scb.set_anchor_struct(create_info); + if constexpr (bindingType == vkb::BindingType::Cpp) + { + extend_instance_create_info(scb); + } + else + { + extend_instance_create_info(reinterpret_cast &>(scb)); + } + // Create the Vulkan instance - handle = vk::createInstance(create_info); + handle = vk::createInstance(*scb.get_struct()); // initialize the Vulkan-Hpp default dispatcher on the instance VULKAN_HPP_DEFAULT_DISPATCHER.init(handle); diff --git a/framework/structure_chain_builder.h b/framework/structure_chain_builder.h new file mode 100644 index 0000000000..7b68905de4 --- /dev/null +++ b/framework/structure_chain_builder.h @@ -0,0 +1,162 @@ +/* Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 the "License"; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace vkb +{ +template +class StructureChainBuilder +{ + public: + StructureChainBuilder(); + + template + T &add_chain_data(T const &data_to_add = {}); // Adds data to the structure chain builder that is not part of the structure chain itself, but is used by the + // structures in the chain (e.g. pointed to by a member of a struct in the structure chain) + + template + StructType &add_struct(StructType const &struct_to_add = {}); + + template + StructType const *get_struct(size_t skip = 0) const; + + void set_anchor_struct(AnchorStructType const &anchor_struct); + + private: + template + StructType &add_struct_impl(StructType const &struct_to_add); + template + StructType const *get_struct_impl(size_t skip) const; + void set_anchor_struct_impl(AnchorStructType const &anchor_struct); + + private: + std::vector> structure_chain; + std::vector> chain_data; // data used with the structure chain, stored separately to ensure correct destruction order (the structs + // in the structure chain may contain pointers to data owned by the chain_data) +}; + +template +using StructureChainBuilderC = StructureChainBuilder; +template +using StructureChainBuilderCpp = StructureChainBuilder; + +template +template +T &StructureChainBuilder::add_chain_data(T const &data_to_add) +{ + chain_data.push_back(std::make_unique(std::make_any(data_to_add))); + return *std::any_cast(chain_data.back().get()); +} + +template +inline StructureChainBuilder::StructureChainBuilder() +{ + static_assert((offsetof(AnchorStructType, sType) == 0) && (offsetof(AnchorStructType, pNext) == sizeof(void *))); + structure_chain.push_back(std::make_unique(std::make_any())); +} + +template +template +inline StructType &StructureChainBuilder::add_struct(StructType const &struct_to_add) +{ + if constexpr (bindingType == vkb::BindingType::Cpp) + { + return add_struct_impl(struct_to_add); + } + else + { + return reinterpret_cast::Type> *>(this)->add_struct( + reinterpret_cast::Type const &>(struct_to_add)); + } +} + +template +template +inline StructType &StructureChainBuilder::add_struct_impl(StructType const &struct_to_add) +{ +#if !defined(NDEBUG) + auto it = std::ranges::find_if(structure_chain, [](auto const &chain_element) { + return std::any_cast(chain_element.get()) != nullptr; + }); + assert(it == structure_chain.end() || StructType::allowDuplicate); // If the struct type already exists in the structure chain, it must allow duplicates +#endif + + structure_chain.push_back(std::make_unique(std::make_any(struct_to_add))); + std::any_cast(structure_chain.back().get())->pNext = std::any_cast(structure_chain.front().get())->pNext; + std::any_cast(structure_chain.front().get())->pNext = std::any_cast(structure_chain.back().get()); + return *std::any_cast(structure_chain.back().get()); +} + +template +template +inline StructType const *StructureChainBuilder::get_struct(size_t skip) const +{ + if constexpr (bindingType == vkb::BindingType::Cpp) + { + return get_struct_impl(skip); + } + else + { + return reinterpret_cast(get_struct_impl::Type>(skip)); + } +} + +template +template +inline StructType const *StructureChainBuilder::get_struct_impl(size_t skip) const +{ + assert(!skip || StructType::allowDuplicate); // If skip is non-zero, the struct type must allow duplicates in the structure chain + + auto it = std::ranges::find_if(structure_chain, [](auto const &chain_element) { + return std::any_cast(chain_element.get()) != nullptr; + }); + for (size_t i = 0; (i < skip) && (it != structure_chain.end()); ++i) + { + it = std::find_if(std::next(it), structure_chain.end(), [](auto const &chain_element) { + return std::any_cast(chain_element.get()) != nullptr; + }); + } + return (it != structure_chain.end()) ? std::any_cast(it->get()) : nullptr; +} + +template +inline void StructureChainBuilder::set_anchor_struct(AnchorStructType const &anchor_struct) +{ + if constexpr (bindingType == vkb::BindingType::Cpp) + { + set_anchor_struct_impl(anchor_struct); + } + else + { + return reinterpret_cast::Type> *>(this)->add_anchor_struct( + reinterpret_cast::Type const &>(anchor_struct)); + } +} + +template +inline void StructureChainBuilder::set_anchor_struct_impl(AnchorStructType const &anchor_struct) +{ + void const *pNext = std::any_cast(structure_chain.front().get())->pNext; + *std::any_cast(structure_chain.front().get()) = anchor_struct; + std::any_cast(structure_chain.front().get())->pNext = pNext; +} + +} // namespace vkb diff --git a/framework/vulkan_sample.h b/framework/vulkan_sample.h index d5b90c52b0..6b0bfb2fea 100644 --- a/framework/vulkan_sample.h +++ b/framework/vulkan_sample.h @@ -135,11 +135,14 @@ class VulkanSample : public vkb::Application using SceneType = typename std::conditional::type; using StatsType = typename std::conditional::type; + template + using StructureChainBuilderType = typename std::conditional, vkb::StructureChainBuilder>::type; using Extent2DType = typename std::conditional::type; using DebugReportCallbackCreateInfoType = typename std::conditional::type; using DebugUtilsMessengerCreateInfoType = typename std::conditional::type; using InstanceCreateFlagsType = typename std::conditional::type; + using InstanceCreateInfoType = typename std::conditional::type; using LayerSettingType = typename std::conditional::type; using PhysicalDeviceType = typename std::conditional::type; using SurfaceFormatType = typename std::conditional::type; @@ -198,11 +201,11 @@ class VulkanSample : public vkb::Application */ virtual void draw_renderpass(vkb::core::CommandBuffer &command_buffer, vkb::rendering::RenderTarget &render_target); + virtual void extend_instance_create_info(vkb::StructureChainBuilder &create_info) const; virtual uint32_t get_api_version() const; virtual DebugReportCallbackCreateInfoType const *get_debug_report_callback_create_info() const; virtual DebugUtilsMessengerCreateInfoType const *get_debug_utils_messenger_create_info() const; virtual InstanceCreateFlagsType get_instance_create_flags(std::vector const &enabled_extensions) const; - virtual void const *get_instance_create_info_extensions(std::vector const &enabled_layers, std::vector const &enabled_extensions) const; /** * @brief Override this to customise the creation of the swapchain and render_context @@ -222,7 +225,7 @@ class VulkanSample : public vkb::Application virtual void request_instance_extensions(std::unordered_map &requested_extensions) const; virtual void request_layers(std::unordered_map &requested_layers) const; - virtual void request_layer_settings(std::vector &requested_layer_settings) const; + virtual void request_layer_settings(std::vector &requested_layer_settings, StructureChainBuilderType &scb) const; virtual void request_validation_feature_enables(std::vector &requested_validation_feature_enables) const; /** @@ -336,8 +339,9 @@ class VulkanSample : public vkb::Application size_t determine_physical_device_score_impl(vk::PhysicalDevice const &gpu) const; void draw_impl(vkb::core::CommandBufferCpp &command_buffer, vkb::rendering::RenderTargetCpp &render_target); void draw_renderpass_impl(vkb::core::CommandBufferCpp &command_buffer, vkb::rendering::RenderTargetCpp &render_target); + void extend_instance_create_info_impl(vkb::StructureChainBuilderCpp &create_info) const; void render_impl(vkb::core::CommandBufferCpp &command_buffer); - void request_layer_settings_impl(std::vector &requested_layer_settings) const; + void request_layer_settings_impl(std::vector &requested_layer_settings, vkb::StructureChainBuilderCpp &scb) const; static void set_viewport_and_scissor_impl(vkb::core::CommandBufferCpp const &command_buffer, vk::Extent2D const &extent); /** @@ -494,7 +498,6 @@ inline std::unique_ptr> VulkanSample const &enabled_layers, std::vector const &enabled_extensions) { return get_instance_create_info_extensions(enabled_layers, enabled_extensions); }, [this](std::vector const &enabled_extensions) { if constexpr (bindingType == BindingType::Cpp) { @@ -504,7 +507,8 @@ inline std::unique_ptr> VulkanSample(get_instance_create_flags(enabled_extensions)); } - }); + }, + [this](vkb::StructureChainBuilder &scb) { return extend_instance_create_info(scb); }); } template @@ -703,19 +707,27 @@ inline void VulkanSample::finish() } template -inline uint32_t VulkanSample::get_api_version() const +inline void VulkanSample::extend_instance_create_info(vkb::StructureChainBuilder &scb) const { - return VK_API_VERSION_1_1; + if constexpr (bindingType == vkb::BindingType::Cpp) + { + extend_instance_create_info_impl(scb); + } + else + { + extend_instance_create_info_impl(reinterpret_cast &>(scb)); + } } inline bool enable_layer_setting(vk::LayerSettingEXT const &requested_layer_setting, - std::vector const &enabled_layers, + uint32_t enabled_layers_count, + char const *const *enabled_layers, std::vector &enabled_layer_settings) { // We are checking if the layer is available. // Vulkan does not provide a reflection API for layer settings. Layer settings are described in each layer JSON manifest. - bool is_available = std::ranges::any_of( - enabled_layers, [&requested_layer_setting](auto const &enabled_layer) { return enabled_layer == requested_layer_setting.pLayerName; }); + bool is_available = std::any_of( + enabled_layers, enabled_layers + enabled_layers_count, [&requested_layer_setting](auto const &enabled_layer) { return strcmp(enabled_layer, requested_layer_setting.pLayerName) == 0; }); #if defined(PLATFORM__MACOS) // On Apple the MoltenVK driver configuration layer is implicitly enabled and available, and cannot be explicitly added or checked via enabled_layers. @@ -755,25 +767,97 @@ inline bool enable_layer_setting(vk::LayerSettingEXT const &requested_lay } inline bool enable_layer_setting(VkLayerSettingEXT const &requested_layer_setting, - std::vector const &enabled_layers, + uint32_t enabled_layers_count, + char const *const *enabled_layers, std::vector &enabled_layer_settings) { - return enable_layer_setting(reinterpret_cast(requested_layer_setting), enabled_layers, enabled_layer_settings); + return enable_layer_setting( + reinterpret_cast(requested_layer_setting), enabled_layers_count, enabled_layers, enabled_layer_settings); +} + +template +inline void VulkanSample::extend_instance_create_info_impl(vkb::StructureChainBuilderCpp &scb) const +{ + vk::InstanceCreateInfo const *create_info = scb.get_struct(); + assert(create_info); + +#if defined(VKB_DEBUG) || defined(VKB_VALIDATION_LAYERS) + if (contains(create_info->enabledExtensionCount, create_info->ppEnabledExtensionNames, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) + { + vk::DebugUtilsMessengerCreateInfoEXT debug_utils_messenger_create_info{.messageSeverity = vk::DebugUtilsMessageSeverityFlagBitsEXT::eError | vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning, + .messageType = vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance, + .pfnUserCallback = vkb::core::debug_utils_messenger_callback}; + scb.add_struct(debug_utils_messenger_create_info); + } + else if (contains(create_info->enabledExtensionCount, create_info->ppEnabledExtensionNames, VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) + { + vk::DebugReportCallbackCreateInfoEXT debug_report_callback_create_info{.flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning, + .pfnCallback = vkb::core::debug_callback}; + scb.add_struct(debug_report_callback_create_info); + } +#endif + + if (contains(create_info->enabledExtensionCount, create_info->ppEnabledExtensionNames, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME)) + { + std::vector requested_layer_settings; + if constexpr (bindingType == vkb::BindingType::Cpp) + { + request_layer_settings(requested_layer_settings, scb); + } + else + { + request_layer_settings(reinterpret_cast &>(requested_layer_settings), + reinterpret_cast &>(scb)); + } + + std::vector enabled_layer_settings; + for (auto const &layer_setting : requested_layer_settings) + { + enable_layer_setting(layer_setting, create_info->enabledLayerCount, create_info->ppEnabledLayerNames, enabled_layer_settings); + } + + if (!enabled_layer_settings.empty()) + { + // If layer settings are defined, then activate the sample's required layer settings during instance creation + vk::LayerSettingsCreateInfoEXT layer_settings_create_info_ext{.settingCount = static_cast(enabled_layer_settings.size()), + .pSettings = scb.add_chain_data(enabled_layer_settings).data()}; + scb.add_struct(layer_settings_create_info_ext); + } + } + else if (contains(create_info->enabledExtensionCount, create_info->ppEnabledExtensionNames, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)) + { + std::vector requested_validation_feature_enables; + request_validation_feature_enables(requested_validation_feature_enables); + + if (!requested_validation_feature_enables.empty()) + { + vk::ValidationFeaturesEXT validation_features_ext{ + .enabledValidationFeatureCount = static_cast(requested_validation_feature_enables.size()), + .pEnabledValidationFeatures = reinterpret_cast(scb.add_chain_data(requested_validation_feature_enables).data())}; + scb.add_struct(validation_features_ext); + }; + } +} + +template +inline uint32_t VulkanSample::get_api_version() const +{ + return VK_API_VERSION_1_1; } template inline typename VulkanSample::DebugReportCallbackCreateInfoType const *VulkanSample::get_debug_report_callback_create_info() const { #if defined(VKB_DEBUG) || defined(VKB_VALIDATION_LAYERS) - static vk::DebugReportCallbackCreateInfoEXT debug_report_callback_createInfo{.flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning, - .pfnCallback = vkb::core::debug_callback}; + static vk::DebugReportCallbackCreateInfoEXT debug_report_callback_create_info{.flags = vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::ePerformanceWarning, + .pfnCallback = vkb::core::debug_callback}; if constexpr (bindingType == vkb::BindingType::Cpp) { - return &debug_report_callback_createInfo; + return &debug_report_callback_create_info; } else { - return reinterpret_cast(&debug_report_callback_createInfo); + return reinterpret_cast(&debug_report_callback_create_info); } #else return nullptr; @@ -821,61 +905,6 @@ inline typename VulkanSample::InstanceCreateFlagsType VulkanSample< } } -template -inline void const *VulkanSample::get_instance_create_info_extensions(std::vector const &enabled_layers, - std::vector const &enabled_extensions) const -{ - void const *pNext = nullptr; - - if (contains(enabled_extensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) - { - pNext = get_debug_utils_messenger_create_info(); - } - else if (contains(enabled_extensions, VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) - { - pNext = get_debug_report_callback_create_info(); - } - - if (contains(enabled_extensions, VK_EXT_LAYER_SETTINGS_EXTENSION_NAME)) - { - std::vector requested_layer_settings; - request_layer_settings(requested_layer_settings); - - static std::vector enabled_layer_settings; - // since enabled_layer_settings is static, clear on every get_instance_create_info_extensions() call to support batch mode - enabled_layer_settings.clear(); - for (auto const &layer_setting : requested_layer_settings) - { - enable_layer_setting(layer_setting, enabled_layers, enabled_layer_settings); - } - - if (!enabled_layer_settings.empty()) - { - // If layer settings are defined, then activate the sample's required layer settings during instance creation - static vk::LayerSettingsCreateInfoEXT layer_settings_create_info_ext{.pNext = pNext, - .settingCount = static_cast(enabled_layer_settings.size()), - .pSettings = enabled_layer_settings.data()}; - pNext = &layer_settings_create_info_ext; - } - } - else if (contains(enabled_extensions, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)) - { - static std::vector requested_validation_feature_enables; - request_validation_feature_enables(requested_validation_feature_enables); - - if (!requested_validation_feature_enables.empty()) - { - static vk::ValidationFeaturesEXT validation_features_ext{ - .pNext = pNext, - .enabledValidationFeatureCount = static_cast(requested_validation_feature_enables.size()), - .pEnabledValidationFeatures = reinterpret_cast(requested_validation_feature_enables.data())}; - pNext = &validation_features_ext; - } - } - - return pNext; -} - template inline Configuration &VulkanSample::get_configuration() { @@ -1445,50 +1474,44 @@ inline void VulkanSample::request_layers(std::unordered_map -inline void VulkanSample::request_layer_settings(std::vector &requested_layer_settings) const +inline void VulkanSample::request_layer_settings(std::vector &requested_layer_settings, StructureChainBuilderType &scb) const { if constexpr (bindingType == vkb::BindingType::Cpp) { - request_layer_settings_impl(requested_layer_settings); + request_layer_settings_impl(requested_layer_settings, scb); } else { - request_layer_settings_impl(reinterpret_cast &>(requested_layer_settings)); + request_layer_settings_impl(reinterpret_cast &>(requested_layer_settings), reinterpret_cast &>(scb)); } } template -inline void VulkanSample::request_layer_settings_impl(std::vector &requested_layer_settings) const +inline void VulkanSample::request_layer_settings_impl(std::vector &requested_layer_settings, vkb::StructureChainBuilderCpp &scb) const { #if defined(VKB_VALIDATION_LAYERS_GPU_ASSISTED) - static const vk::Bool32 setting_validate_gpuav = true; - requested_layer_settings.push_back({"VK_LAYER_KHRONOS_validation", "gpuav_enable", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_gpuav}); + requested_layer_settings.push_back({"VK_LAYER_KHRONOS_validation", "gpuav_enable", vk::LayerSettingTypeEXT::eBool32, 1, &scb.add_chain_data(true)}); #endif #if defined(VKB_VALIDATION_LAYERS_BEST_PRACTICES) - static const vk::Bool32 setting_validate_best_practices = true; - static const vk::Bool32 setting_validate_best_practices_amd = true; - static const vk::Bool32 setting_validate_best_practices_arm = true; - static const vk::Bool32 setting_validate_best_practices_img = true; - static const vk::Bool32 setting_validate_best_practices_nvidia = true; + std::array &best_practices_values = scb.add_chain_data>({true, true, true, true, true}); requested_layer_settings.push_back( - {"VK_LAYER_KHRONOS_validation", "validate_best_practices", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices}); + {"VK_LAYER_KHRONOS_validation", "validate_best_practices", vk::LayerSettingTypeEXT::eBool32, 1, &best_practices_values[0]}); requested_layer_settings.push_back( - {"VK_LAYER_KHRONOS_validation", "validate_best_practices_amd", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_amd}); + {"VK_LAYER_KHRONOS_validation", "validate_best_practices_amd", vk::LayerSettingTypeEXT::eBool32, 1, &best_practices_values[1]}); requested_layer_settings.push_back( - {"VK_LAYER_KHRONOS_validation", "validate_best_practices_arm", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_arm}); + {"VK_LAYER_KHRONOS_validation", "validate_best_practices_arm", vk::LayerSettingTypeEXT::eBool32, 1, &best_practices_values[2]}); requested_layer_settings.push_back( - {"VK_LAYER_KHRONOS_validation", "validate_best_practices_img", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_img}); + {"VK_LAYER_KHRONOS_validation", "validate_best_practices_img", vk::LayerSettingTypeEXT::eBool32, 1, &best_practices_values[3]}); requested_layer_settings.push_back( - {"VK_LAYER_KHRONOS_validation", "validate_best_practices_nvidia", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_best_practices_nvidia}); + {"VK_LAYER_KHRONOS_validation", "validate_best_practices_nvidia", vk::LayerSettingTypeEXT::eBool32, 1, &best_practices_values[4]}); #endif #if defined(VKB_VALIDATION_LAYERS_SYNCHRONIZATION) - static const vk::Bool32 setting_validate_sync = true; - static const vk::Bool32 setting_validate_sync_heuristics = true; - requested_layer_settings.push_back({"VK_LAYER_KHRONOS_validation", "validate_sync", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_sync}); + std::array &synchronization_values = scb.add_chain_data>({true, true}); + requested_layer_settings.push_back({"VK_LAYER_KHRONOS_validation", "validate_sync", vk::LayerSettingTypeEXT::eBool32, 1, &synchronization_values[0]}); requested_layer_settings.push_back( - {"VK_LAYER_KHRONOS_validation", "syncval_shader_accesses_heuristic", vk::LayerSettingTypeEXT::eBool32, 1, &setting_validate_sync_heuristics}); + {"VK_LAYER_KHRONOS_validation", "syncval_shader_accesses_heuristic", vk::LayerSettingTypeEXT::eBool32, 1, &synchronization_values[1]}); #endif } diff --git a/samples/extensions/descriptor_indexing/descriptor_indexing.cpp b/samples/extensions/descriptor_indexing/descriptor_indexing.cpp index 6f8f60919a..283c969d0b 100644 --- a/samples/extensions/descriptor_indexing/descriptor_indexing.cpp +++ b/samples/extensions/descriptor_indexing/descriptor_indexing.cpp @@ -533,13 +533,10 @@ void DescriptorIndexing::request_instance_extensions(std::unordered_map &requested_layer_settings) const +void DescriptorIndexing::request_layer_settings(std::vector &requested_layer_settings, vkb::StructureChainBuilderC &scb) const { - // Make this static so layer setting reference remains valid after leaving the current scope - static const int32_t useMetalArgumentBuffers = 1; - - ApiVulkanSample::request_layer_settings(requested_layer_settings); - requested_layer_settings.push_back({"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &useMetalArgumentBuffers}); + ApiVulkanSample::request_layer_settings(requested_layer_settings, scb); + requested_layer_settings.push_back({"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &scb.add_chain_data(1)}); } #endif diff --git a/samples/extensions/descriptor_indexing/descriptor_indexing.h b/samples/extensions/descriptor_indexing/descriptor_indexing.h index c69cdc74a7..67788bb8ba 100644 --- a/samples/extensions/descriptor_indexing/descriptor_indexing.h +++ b/samples/extensions/descriptor_indexing/descriptor_indexing.h @@ -35,7 +35,7 @@ class DescriptorIndexing : public ApiVulkanSample bool prepare(const vkb::ApplicationOptions &options) override; #if defined(PLATFORM__MACOS) void request_instance_extensions(std::unordered_map &requested_extensions) const override; - void request_layer_settings(std::vector &requested_layer_settings) const override; + void request_layer_settings(std::vector &requested_layer_settings, vkb::StructureChainBuilderC &scb) const override; #endif void create_bindless_descriptors(); diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp index 1392664dcf..c67758c5ad 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.cpp +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.cpp @@ -120,13 +120,11 @@ void ShaderDebugPrintf::request_instance_extensions(std::unordered_map &requested_layer_settings) const +void ShaderDebugPrintf::request_layer_settings(std::vector &requested_layer_settings, vkb::StructureChainBuilderC &scb) const { - // Make this static so layer setting reference remains valid after leaving the current scope - static const VkBool32 printf_enable = VK_TRUE; - - ApiVulkanSample::request_layer_settings(requested_layer_settings); - requested_layer_settings.push_back({validation_layer_name, "printf_enable", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &printf_enable}); + ApiVulkanSample::request_layer_settings(requested_layer_settings, scb); + requested_layer_settings.push_back( + {validation_layer_name, "printf_enable", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &scb.add_chain_data(VK_TRUE)}); } void ShaderDebugPrintf::request_validation_feature_enables(std::vector &requested_layer_settings) const @@ -460,6 +458,18 @@ bool ShaderDebugPrintf::prepare(const vkb::ApplicationOptions &options) return true; } +void ShaderDebugPrintf::extend_instance_create_info(vkb::StructureChainBuilderC &scb) const +{ + ApiVulkanSample::extend_instance_create_info(scb); + + // Register a sample specific debug utils callback in addition to the one registered by the base class + VkDebugUtilsMessengerCreateInfoEXT debug_utils_messenger_create_info{.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, + .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, + .pfnUserCallback = debug_utils_message_callback}; + scb.add_struct(debug_utils_messenger_create_info); +} + VkDebugUtilsMessengerCreateInfoEXT const *ShaderDebugPrintf::get_debug_utils_messenger_create_info() const { // Register a sample specific debug utils callback in addition to the one registered by the base class diff --git a/samples/extensions/shader_debugprintf/shader_debugprintf.h b/samples/extensions/shader_debugprintf/shader_debugprintf.h index 6fe2b5aac7..9cc86a7fb8 100644 --- a/samples/extensions/shader_debugprintf/shader_debugprintf.h +++ b/samples/extensions/shader_debugprintf/shader_debugprintf.h @@ -82,7 +82,7 @@ class ShaderDebugPrintf : public ApiVulkanSample ~ShaderDebugPrintf(); void request_gpu_features(vkb::core::PhysicalDeviceC &gpu) override; void request_instance_extensions(std::unordered_map &requested_extensions) const override; - void request_layer_settings(std::vector &requested_layer_settings) const override; + void request_layer_settings(std::vector &requested_layer_settings, vkb::StructureChainBuilderC &scb) const override; void request_validation_feature_enables(std::vector &requested_layer_settings) const override; void build_command_buffers() override; void load_assets(); @@ -94,6 +94,7 @@ class ShaderDebugPrintf : public ApiVulkanSample void update_uniform_buffers(); void draw(); bool prepare(const vkb::ApplicationOptions &options) override; + virtual void extend_instance_create_info(vkb::StructureChainBuilderC &scb) const override; virtual VkDebugUtilsMessengerCreateInfoEXT const *get_debug_utils_messenger_create_info() const override; virtual void render(float delta_time) override; virtual void on_update_ui_overlay(vkb::Drawer &drawer) override; diff --git a/samples/performance/layout_transitions/layout_transitions.cpp b/samples/performance/layout_transitions/layout_transitions.cpp index 1f508b3378..96de111b17 100644 --- a/samples/performance/layout_transitions/layout_transitions.cpp +++ b/samples/performance/layout_transitions/layout_transitions.cpp @@ -84,13 +84,10 @@ void LayoutTransitions::request_instance_extensions(std::unordered_map &requested_layer_settings) const +void LayoutTransitions::request_layer_settings(std::vector &requested_layer_settings, vkb::StructureChainBuilderC &scb) const { - // Make this static so layer setting reference remains valid after leaving the current scope - static const int32_t disableMetalArgumentBuffers = 0; - - vkb::VulkanSampleC::request_layer_settings(requested_layer_settings); - requested_layer_settings.push_back({"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &disableMetalArgumentBuffers}); + vkb::VulkanSampleC::request_layer_settings(requested_layer_settings, scb); + requested_layer_settings.push_back({"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &scb.add_chain_data(0)}); } #endif diff --git a/samples/performance/layout_transitions/layout_transitions.h b/samples/performance/layout_transitions/layout_transitions.h index dd676d34a1..413b44b0a9 100644 --- a/samples/performance/layout_transitions/layout_transitions.h +++ b/samples/performance/layout_transitions/layout_transitions.h @@ -35,7 +35,8 @@ class LayoutTransitions : public vkb::VulkanSampleC bool prepare(const vkb::ApplicationOptions &options) override; #if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR void request_instance_extensions(std::unordered_map &requested_extensions) const override; - void request_layer_settings(std::vector &requested_layer_settings) const override; + void request_layer_settings(std::vector &requested_layer_settings, + vkb::StructureChainBuilderC &scb) const override; #endif private: diff --git a/samples/performance/pipeline_barriers/pipeline_barriers.cpp b/samples/performance/pipeline_barriers/pipeline_barriers.cpp index f01a88524c..871657dbc1 100644 --- a/samples/performance/pipeline_barriers/pipeline_barriers.cpp +++ b/samples/performance/pipeline_barriers/pipeline_barriers.cpp @@ -119,13 +119,11 @@ void PipelineBarriers::request_instance_extensions(std::unordered_map &requested_layer_settings) const +void PipelineBarriers::request_layer_settings(std::vector &requested_layer_settings, vbk::StructureChainBuilderC &scb) const { - // Make this static so layer setting reference remains valid after leaving the current scope - static const int32_t disableMetalArgumentBuffers = 0; - - vkb::VulkanSampleC::request_layer_settings(requested_layer_settings); - requested_layer_settings.push_back({"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &disableMetalArgumentBuffers}); + vkb::VulkanSampleC::request_layer_settings(requested_layer_settings, scb); + requested_layer_settings.push_back( + {"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &scb.add_chain_data(0)}); } #endif diff --git a/samples/performance/pipeline_barriers/pipeline_barriers.h b/samples/performance/pipeline_barriers/pipeline_barriers.h index ae81eeb105..6a1aa057cb 100644 --- a/samples/performance/pipeline_barriers/pipeline_barriers.h +++ b/samples/performance/pipeline_barriers/pipeline_barriers.h @@ -35,7 +35,8 @@ class PipelineBarriers : public vkb::VulkanSampleC bool prepare(const vkb::ApplicationOptions &options) override; #if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR void request_instance_extensions(std::unordered_map &requested_extensions) const override; - void request_layer_settings(std::vector &requested_layer_settings) const override; + void request_layer_settings(std::vector &requested_layer_settings, + vkb::StructureChainBuilderC &scb) const override; #endif private: diff --git a/samples/performance/subpasses/subpasses.cpp b/samples/performance/subpasses/subpasses.cpp index 3cc6cc55d6..294a1e0db6 100644 --- a/samples/performance/subpasses/subpasses.cpp +++ b/samples/performance/subpasses/subpasses.cpp @@ -176,13 +176,12 @@ void Subpasses::request_instance_extensions(std::unordered_map &requested_layer_settings) const +void Subpasses::request_layer_settings(std::vector &requested_layer_settings, + vkb::StructureChainBuilderC &scb) const { - // Make this static so layer setting reference remains valid after leaving the current scope - static const int32_t disableMetalArgumentBuffers = 0; - - vkb::VulkanSampleC::request_layer_settings(requested_layer_settings); - requested_layer_settings.push_back({"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &disableMetalArgumentBuffers}); + vkb::VulkanSampleC::request_layer_settings(requested_layer_settings, scb); + requested_layer_settings.push_back( + {"MoltenVK", "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", VK_LAYER_SETTING_TYPE_INT32_EXT, 1, &scb.add_chain_data(0)}); } #endif diff --git a/samples/performance/subpasses/subpasses.h b/samples/performance/subpasses/subpasses.h index f41f29ce64..223eae2137 100644 --- a/samples/performance/subpasses/subpasses.h +++ b/samples/performance/subpasses/subpasses.h @@ -36,7 +36,8 @@ class Subpasses : public vkb::VulkanSampleC bool prepare(const vkb::ApplicationOptions &options) override; #if defined(PLATFORM__MACOS) && TARGET_OS_IOS && TARGET_OS_SIMULATOR void request_instance_extensions(std::unordered_map &requested_extensions) const override; - void request_layer_settings(std::vector &requested_layer_settings) const override; + void request_layer_settings(std::vector &requested_layer_settings, + vkb::StructureChainBuilderC &scb) const override; #endif void update(float delta_time) override;