From ed2d4d1250d4590ad49c3f52a69e5d1a0986a93f Mon Sep 17 00:00:00 2001 From: Christophe Date: Tue, 15 Aug 2023 18:32:53 +0200 Subject: [PATCH] layer: Add minimum setting reflection --- include/vulkan/layer/vk_layer_settings.h | 9 ++-- include/vulkan/layer/vk_layer_settings_ext.h | 51 +++++--------------- src/layer/CMakeLists.txt | 1 + src/layer/layer_settings_manager.cpp | 8 +-- src/layer/layer_settings_manager.hpp | 4 +- src/layer/vk_layer_settings.cpp | 9 +++- src/layer/vk_layer_settings_interface.cpp | 42 ++++++++++++++++ tests/layer/test_setting_api.cpp | 29 ++++++++++- 8 files changed, 102 insertions(+), 51 deletions(-) create mode 100644 src/layer/vk_layer_settings_interface.cpp diff --git a/include/vulkan/layer/vk_layer_settings.h b/include/vulkan/layer/vk_layer_settings.h index c9e55fb..f45942a 100644 --- a/include/vulkan/layer/vk_layer_settings.h +++ b/include/vulkan/layer/vk_layer_settings.h @@ -17,12 +17,15 @@ extern "C" { VK_DEFINE_HANDLE(VlLayerSettingSet) -typedef void *(*VL_LAYER_SETTING_LOG_CALLBACK)(const char *pSettingName, const char *pMessage); +typedef void (VKAPI_PTR *VlLayerSettingLogCallback)(const char *pSettingName, const char *pMessage); + +void vlRegistryLayerSettingsProperties(const char *pLayerName, + uint32_t propertyCount, VkLayerSettingPropertiesEXT *pProperties); // Create a layer setting set. If 'pCallback' is set to NULL, the messages are outputed to stderr. VkResult vlCreateLayerSettingSet(const char *pLayerName, const VkLayerSettingsCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VL_LAYER_SETTING_LOG_CALLBACK pCallback, VlLayerSettingSet *pLayerSettingSet); + const VkAllocationCallbacks *pAllocator, VlLayerSettingLogCallback pCallback, + VlLayerSettingSet *pLayerSettingSet); void vlDestroyLayerSettingSet(VlLayerSettingSet layerSettingSet, const VkAllocationCallbacks *pAllocator); diff --git a/include/vulkan/layer/vk_layer_settings_ext.h b/include/vulkan/layer/vk_layer_settings_ext.h index 8e91f07..a93ee22 100644 --- a/include/vulkan/layer/vk_layer_settings_ext.h +++ b/include/vulkan/layer/vk_layer_settings_ext.h @@ -15,53 +15,14 @@ extern "C" { #include -// VK_EXT_layer_settings -// -// Name String -// VK_EXT_layer_settings -// -// Extension Type -// Instance extension -// -// Revision -// 1 -// -// Extension and Version Dependencies -// Requires Vulkan 1.0 -// -// Contact -// Christophe Riccio christophe-lunarg -// -// Contributors -// Christophe Riccio -// Mark Lobodzinski -// -// Description -// This extension provides a mechanism for configuring programmatically through -// the Vulkan API the behavior of layers. -// -// This extension provides the [VkLayerSettingsCreateInfoEXT] struct that can be -// included in the [pNext] chain of the [VkInstanceCreateInfo] -// structure passed as the [pCreateInfo] parameter of [vkCreateInstance]. -// -// The structure contains an array of [VkLayerSettingEXT] structure -// values that configure specific features of layers. -// -// Note -// The [VK_EXT_layer_settings] extension subsumes all the functionality provided in the [VK_EXT_validation_flags] extension -// and the [VK_EXT_validation_features] extension. - #define VK_EXT_layer_settings 1 #define VK_EXT_LAYER_SETTINGS_SPEC_VERSION 1 #define VK_EXT_LAYER_SETTINGS_EXTENSION_NAME "VK_EXT_layer_settings" - -// This extension is exclusively used by VVL, and is NOT intended as a deliverable. -// The value of the VK_STRUCTURE_TYPE is arbitrary. The only requirement, -// is that it must not conflict with existing sTypes. // // NOTE: VK_STRUCTURE_TYPE_MAX_ENUM - 1 is used by the intel driver. // NOTE: VK_STRUCTURE_TYPE_MAX_ENUM - 42 is used by the validation layers #define VK_STRUCTURE_TYPE_LAYER_SETTINGS_EXT ((VkStructureType)(VK_STRUCTURE_TYPE_MAX_ENUM - 43)) +#define VK_STRUCTURE_TYPE_LAYER_SETTING_PROPERTIES_EXT ((VkStructureType)(VK_STRUCTURE_TYPE_MAX_ENUM - 44)) typedef enum VkLayerSettingTypeEXT { VK_LAYER_SETTING_TYPE_BOOL32_EXT = 0, @@ -96,6 +57,16 @@ typedef struct VkLayerSettingsCreateInfoEXT { const VkLayerSettingEXT *pSettings; } VkLayerSettingsCreateInfoEXT; +typedef struct VkLayerSettingPropertiesEXT { + VkStructureType sType; + const void *pNext; + char key[VK_MAX_DESCRIPTION_SIZE]; + VkLayerSettingTypeEXT type; +} VkLayerSettingPropertiesEXT; + +VkResult vkEnumerateInstanceLayerSettingsEXT(const char *pLayerName, + uint32_t *pPropertyCount, VkLayerSettingPropertiesEXT *pProperties); + #ifdef __cplusplus } #endif diff --git a/src/layer/CMakeLists.txt b/src/layer/CMakeLists.txt index e28e0a1..c40822f 100644 --- a/src/layer/CMakeLists.txt +++ b/src/layer/CMakeLists.txt @@ -13,6 +13,7 @@ target_compile_features(VulkanLayerSettings PRIVATE cxx_std_17) target_sources(VulkanLayerSettings PRIVATE vk_layer_settings.cpp vk_layer_settings_helper.cpp + vk_layer_settings_interface.cpp layer_settings_manager.cpp layer_settings_manager.hpp layer_settings_util.cpp diff --git a/src/layer/layer_settings_manager.cpp b/src/layer/layer_settings_manager.cpp index a9a6010..fc932c0 100644 --- a/src/layer/layer_settings_manager.cpp +++ b/src/layer/layer_settings_manager.cpp @@ -104,8 +104,8 @@ static void AddWorkaroundLayerNames(std::vector &layer_names) { namespace vl { LayerSettings::LayerSettings(const char *pLayerName, const VkLayerSettingsCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VL_LAYER_SETTING_LOG_CALLBACK callback) - : layer_name(pLayerName), create_info(pCreateInfo), callback(callback) { + const VkAllocationCallbacks *pAllocator, VlLayerSettingLogCallback pCallback) + : layer_name(pLayerName), create_info(pCreateInfo), pCallback(pCallback) { (void)pAllocator; assert(pLayerName != nullptr); @@ -243,10 +243,10 @@ void LayerSettings::Log(const char *pSettingName, const char * pMessage) { this->last_log_setting = pSettingName; this->last_log_message = pMessage; - if (this->callback == nullptr) { + if (this->pCallback == nullptr) { fprintf(stderr, "LAYER SETTING (%s) error: %s\n", this->last_log_setting.c_str(), this->last_log_message.c_str()); } else { - this->callback(this->last_log_setting.c_str(), this->last_log_message.c_str()); + this->pCallback(this->last_log_setting.c_str(), this->last_log_message.c_str()); } } diff --git a/src/layer/layer_settings_manager.hpp b/src/layer/layer_settings_manager.hpp index 7c09439..5503f90 100644 --- a/src/layer/layer_settings_manager.hpp +++ b/src/layer/layer_settings_manager.hpp @@ -18,7 +18,7 @@ namespace vl { class LayerSettings { public: LayerSettings(const char *pLayerName, const VkLayerSettingsCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VL_LAYER_SETTING_LOG_CALLBACK callback); + const VkAllocationCallbacks *pAllocator, VlLayerSettingLogCallback pCallback); ~LayerSettings(); bool HasEnvSetting(const char *pSettingName); @@ -53,7 +53,7 @@ namespace vl { std::string layer_name; const VkLayerSettingsCreateInfoEXT *create_info{nullptr}; - VL_LAYER_SETTING_LOG_CALLBACK callback{nullptr}; + VlLayerSettingLogCallback pCallback{nullptr}; }; }// namespace vl diff --git a/src/layer/vk_layer_settings.cpp b/src/layer/vk_layer_settings.cpp index e6b4977..917dce3 100644 --- a/src/layer/vk_layer_settings.cpp +++ b/src/layer/vk_layer_settings.cpp @@ -17,6 +17,13 @@ #include #include #include +#include + +std::unordered_map > layer_settings_properties; + +void vlRegistryLayerSettingsProperties(const char *pLayerName, uint32_t propertyCount, VkLayerSettingPropertiesEXT *pProperties) { + layer_settings_properties.insert(std::pair(pLayerName, std::pair(propertyCount, pProperties))); +} // This is used only for unit tests in test_layer_setting_file void test_helper_SetLayerSetting(VlLayerSettingSet layerSettingSet, const char *pSettingName, const char *pValue) { @@ -30,7 +37,7 @@ void test_helper_SetLayerSetting(VlLayerSettingSet layerSettingSet, const char * } VkResult vlCreateLayerSettingSet(const char *pLayerName, const VkLayerSettingsCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, VL_LAYER_SETTING_LOG_CALLBACK pCallback, + const VkAllocationCallbacks *pAllocator, VlLayerSettingLogCallback pCallback, VlLayerSettingSet *pLayerSettingSet) { (void)pAllocator; diff --git a/src/layer/vk_layer_settings_interface.cpp b/src/layer/vk_layer_settings_interface.cpp new file mode 100644 index 0000000..1bd169a --- /dev/null +++ b/src/layer/vk_layer_settings_interface.cpp @@ -0,0 +1,42 @@ +// Copyright 2023 The Khronos Group Inc. +// Copyright 2023 Valve Corporation +// Copyright 2023 LunarG, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Author(s): +// - Christophe Riccio + +#include "vulkan/layer/vk_layer_settings_ext.h" +#include +#include +#include +#include + +#if defined(__GNUC__) && __GNUC__ >= 4 +#define LAYER_EXPORT __attribute__((visibility("default"))) +#else +#define LAYER_EXPORT +#endif + +extern std::unordered_map > layer_settings_properties; + +// Keep synchronized with VkLayer_khronos_profiles.def / VkLayer_khronos_profiles.map +extern "C" { + +LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerSettingsEXT( + const char* pLayerName, uint32_t* pPropertyCount, VkLayerSettingPropertiesEXT* pProperties) { + + assert(pPropertyCount != nullptr); + + if (*pPropertyCount > 0 && pProperties != nullptr) { + *pPropertyCount = std::min(*pPropertyCount, layer_settings_properties[pLayerName].first); + memcpy(pProperties, layer_settings_properties[pLayerName].second, sizeof(VkLayerSettingPropertiesEXT) * *pPropertyCount); + } else { + *pPropertyCount = layer_settings_properties[pLayerName].first; + } + + return VK_SUCCESS; +} + +} // extern "C" diff --git a/tests/layer/test_setting_api.cpp b/tests/layer/test_setting_api.cpp index 249dbdb..1aafcd1 100644 --- a/tests/layer/test_setting_api.cpp +++ b/tests/layer/test_setting_api.cpp @@ -9,7 +9,34 @@ #include #include "vulkan/layer/vk_layer_settings.h" -#include + +TEST(test_layer_setting_api, vkEnumerateInstanceLayerSettingsEXT) { + + VkLayerSettingPropertiesEXT properties[] = { + {VK_STRUCTURE_TYPE_LAYER_SETTING_PROPERTIES_EXT, nullptr, "settingA", VK_LAYER_SETTING_TYPE_BOOL32_EXT}, + {VK_STRUCTURE_TYPE_LAYER_SETTING_PROPERTIES_EXT, nullptr, "settingB", VK_LAYER_SETTING_TYPE_UINT32_EXT} + }; + + vlRegistryLayerSettingsProperties("VK_LAYER_LUNARG_test", static_cast(std::size(properties)), &properties[0]); + + uint32_t result_count = 0; + vkEnumerateInstanceLayerSettingsEXT("VK_LAYER_LUNARG_test", &result_count, nullptr); + + EXPECT_EQ(static_cast(std::size(properties)), result_count); + + std::vector results(static_cast(result_count)); + vkEnumerateInstanceLayerSettingsEXT("VK_LAYER_LUNARG_test", &result_count, &results[0]); + + EXPECT_EQ(properties[0].sType, results[0].sType); + EXPECT_EQ(properties[0].pNext, results[0].pNext); + EXPECT_STREQ(properties[0].key, results[0].key); + EXPECT_EQ(properties[0].type, results[0].type); + + EXPECT_EQ(properties[1].sType, results[1].sType); + EXPECT_EQ(properties[1].pNext, results[1].pNext); + EXPECT_STREQ(properties[1].key, results[1].key); + EXPECT_EQ(properties[1].type, results[1].type); +} TEST(test_layer_setting_api, vlHasLayerSetting_NotFound) { VlLayerSettingSet layerSettingSet = VK_NULL_HANDLE;