From 6f708e6a7851c7376e88166f59f618f97b7645b8 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 20 Jan 2025 20:12:17 +0000 Subject: [PATCH] Add instance extension hook --- generator/vk_layer/source/instance.cpp | 8 ++ generator/vk_layer/source/instance.hpp | 12 ++- layer_example/source/instance.cpp | 10 ++- layer_example/source/instance.hpp | 12 ++- layer_gpu_support/source/instance.cpp | 8 ++ layer_gpu_support/source/instance.hpp | 10 +++ layer_gpu_timeline/source/instance.cpp | 8 ++ layer_gpu_timeline/source/instance.hpp | 12 ++- source_common/framework/manual_functions.cpp | 95 +++++++++++--------- source_common/framework/manual_functions.hpp | 2 +- 10 files changed, 131 insertions(+), 46 deletions(-) diff --git a/generator/vk_layer/source/instance.cpp b/generator/vk_layer/source/instance.cpp index 0b62857..e0ce2ad 100644 --- a/generator/vk_layer/source/instance.cpp +++ b/generator/vk_layer/source/instance.cpp @@ -34,6 +34,14 @@ */ static std::unordered_map> g_instances; +/* See header for documentation. */ +const APIVersion Instance::minAPIVersion { 1, 1 }; + +/* See header for documentation. */ +const std::vector Instance::extraExtensions { + "VK_EXT_debug_utils" +}; + /* See header for documentation. */ void Instance::store( VkInstance handle, diff --git a/generator/vk_layer/source/instance.hpp b/generator/vk_layer/source/instance.hpp index fc6af6b..b6bdea1 100644 --- a/generator/vk_layer/source/instance.hpp +++ b/generator/vk_layer/source/instance.hpp @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: MIT * ---------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited + * Copyright (c) 2024-2025 Arm Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -131,4 +131,14 @@ class Instance * @brief The driver function dispatch table. */ InstanceDispatchTable driver {}; + + /** + * @brief The minimum API version needed by this layer. + */ + static const APIVersion minAPIVersion; + + /** + * @brief The minimum set of instance extensions needed by this layer. + */ + static const std::vector extraExtensions; }; diff --git a/layer_example/source/instance.cpp b/layer_example/source/instance.cpp index 0b62857..8fb5e88 100644 --- a/layer_example/source/instance.cpp +++ b/layer_example/source/instance.cpp @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: MIT * ---------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited + * Copyright (c) 2024-2025 Arm Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -34,6 +34,14 @@ */ static std::unordered_map> g_instances; +/* See header for documentation. */ +const APIVersion Instance::minAPIVersion { 1, 1 }; + +/* See header for documentation. */ +const std::vector Instance::extraExtensions { + "VK_EXT_debug_utils" +}; + /* See header for documentation. */ void Instance::store( VkInstance handle, diff --git a/layer_example/source/instance.hpp b/layer_example/source/instance.hpp index fc6af6b..b6bdea1 100644 --- a/layer_example/source/instance.hpp +++ b/layer_example/source/instance.hpp @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: MIT * ---------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited + * Copyright (c) 2024-2025 Arm Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -131,4 +131,14 @@ class Instance * @brief The driver function dispatch table. */ InstanceDispatchTable driver {}; + + /** + * @brief The minimum API version needed by this layer. + */ + static const APIVersion minAPIVersion; + + /** + * @brief The minimum set of instance extensions needed by this layer. + */ + static const std::vector extraExtensions; }; diff --git a/layer_gpu_support/source/instance.cpp b/layer_gpu_support/source/instance.cpp index add2605..8fb5e88 100644 --- a/layer_gpu_support/source/instance.cpp +++ b/layer_gpu_support/source/instance.cpp @@ -34,6 +34,14 @@ */ static std::unordered_map> g_instances; +/* See header for documentation. */ +const APIVersion Instance::minAPIVersion { 1, 1 }; + +/* See header for documentation. */ +const std::vector Instance::extraExtensions { + "VK_EXT_debug_utils" +}; + /* See header for documentation. */ void Instance::store( VkInstance handle, diff --git a/layer_gpu_support/source/instance.hpp b/layer_gpu_support/source/instance.hpp index 5791a44..081b26d 100644 --- a/layer_gpu_support/source/instance.hpp +++ b/layer_gpu_support/source/instance.hpp @@ -137,4 +137,14 @@ class Instance * @brief The layer configuration. */ const LayerConfig config; + + /** + * @brief The minimum API version needed by this layer. + */ + static const APIVersion minAPIVersion; + + /** + * @brief The minimum set of instance extensions needed by this layer. + */ + static const std::vector extraExtensions; }; diff --git a/layer_gpu_timeline/source/instance.cpp b/layer_gpu_timeline/source/instance.cpp index 0b62857..e0ce2ad 100644 --- a/layer_gpu_timeline/source/instance.cpp +++ b/layer_gpu_timeline/source/instance.cpp @@ -34,6 +34,14 @@ */ static std::unordered_map> g_instances; +/* See header for documentation. */ +const APIVersion Instance::minAPIVersion { 1, 1 }; + +/* See header for documentation. */ +const std::vector Instance::extraExtensions { + "VK_EXT_debug_utils" +}; + /* See header for documentation. */ void Instance::store( VkInstance handle, diff --git a/layer_gpu_timeline/source/instance.hpp b/layer_gpu_timeline/source/instance.hpp index fc6af6b..b6bdea1 100644 --- a/layer_gpu_timeline/source/instance.hpp +++ b/layer_gpu_timeline/source/instance.hpp @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: MIT * ---------------------------------------------------------------------------- - * Copyright (c) 2024 Arm Limited + * Copyright (c) 2024-2025 Arm Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -131,4 +131,14 @@ class Instance * @brief The driver function dispatch table. */ InstanceDispatchTable driver {}; + + /** + * @brief The minimum API version needed by this layer. + */ + static const APIVersion minAPIVersion; + + /** + * @brief The minimum set of instance extensions needed by this layer. + */ + static const std::vector extraExtensions; }; diff --git a/source_common/framework/manual_functions.cpp b/source_common/framework/manual_functions.cpp index 75b6b4f..2da9a90 100644 --- a/source_common/framework/manual_functions.cpp +++ b/source_common/framework/manual_functions.cpp @@ -299,7 +299,7 @@ APIVersion increaseAPIVersion( return maxVersion; } - LAYER_ERR( + LAYER_LOG( "Instance API version %u.%u (increased to layer minimum)", requiredVersion.first, requiredVersion.second); @@ -378,13 +378,13 @@ std::vector getDeviceExtensionList( /* See header for documentation. */ bool isInExtensionList( - const char* target, + std::string target, uint32_t extensionCount, const char* const* extensionList ) { for(uint32_t i = 0; i < extensionCount; i++) { - if (!strcmp(target, extensionList[i])) + if (target == extensionList[i]) { return true; } @@ -407,7 +407,33 @@ std::vector cloneExtensionList( return data; } -void enableTimelineSemaphores( +static void enableInstanceVkExtDebugUtils( + const std::vector& supportedExtensions, + std::vector& newExtensions +) { + const std::string target { "VK_EXT_debug_utils" }; + + // Test if the desired extension is supported. If supportedExtensions + // is empty then we didn't query and assume it is supported. + if (supportedExtensions.size() && !isIn(target, supportedExtensions)) + { + LAYER_ERR("Instance extension not available: %s", target.c_str()); + return; + } + + // If it is already enabled then do nothing + if (isIn(target, newExtensions)) + { + LAYER_LOG("Instance extension already enabled: %s", target.c_str()); + return; + } + + // Else add it to the list of enable extensions + LAYER_LOG("Instance extension added: %s", target.c_str()); + newExtensions.push_back(target.c_str()); +} + +static void enableDeviceVkKhrTimelineSemaphore( VkDeviceCreateInfo& createInfo, std::vector& supportedExtensions, std::vector& newEnabledExtensions, @@ -419,7 +445,7 @@ void enableTimelineSemaphores( bool isSupported = isIn(target, supportedExtensions); if (!isSupported) { - LAYER_LOG("WARNING: Cannot enable additional extension: %s", target); + LAYER_LOG("Device extension not available: %s", target); return; } @@ -704,14 +730,11 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default( auto* chainInfo = getChainInfo(pCreateInfo); auto fpGetInstanceProcAddr = chainInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; - // For now assume all layers need Vulkan 1.1 or newer - // TODO: Make this configurable per layer + // Work out what version we should use, promoting to meet layer requirement APIVersion appVersion = getApplicationAPIVersion(pCreateInfo); APIVersion maxVersion = getInstanceAPIVersion(fpGetInstanceProcAddr); - APIVersion reqVersion { 1, 1 }; - - APIVersion targetVersion = increaseAPIVersion( - appVersion, maxVersion, reqVersion); + APIVersion reqVersion = Instance::minAPIVersion; + APIVersion newVersion = increaseAPIVersion(appVersion, maxVersion, reqVersion); auto fpCreateInstanceRaw = fpGetInstanceProcAddr(nullptr, "vkCreateInstance"); auto fpCreateInstance = reinterpret_cast(fpCreateInstanceRaw); @@ -725,43 +748,33 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateInstance_default( VkApplicationInfo newAppInfo = *pCreateInfo->pApplicationInfo; // Write the new application info - newAppInfo.apiVersion = VK_MAKE_API_VERSION( - 0, targetVersion.first, targetVersion.second, 0); + newAppInfo.apiVersion = VK_MAKE_API_VERSION(0, newVersion.first, newVersion.second, 0); newCreateInfo.pApplicationInfo = &newAppInfo; - // Query extension state - const char* targetExt = "VK_EXT_debug_utils"; + // Create a copy of the extension list we can patch + std::vector newExtensions; + const auto start = pCreateInfo->ppEnabledExtensionNames; + const auto end = pCreateInfo->ppEnabledExtensionNames + pCreateInfo->enabledExtensionCount; + newExtensions.insert(newExtensions.end(), start, end); - // Assume common extensions are available (see comment at start of function) - bool targetSupported = true; - if (queryExtensions) + // Enable extra extensions + for (const auto& newExt : Instance::extraExtensions) { - targetSupported = isIn(targetExt, supportedExtensions); - if (!targetSupported) + if (newExt == "VK_EXT_debug_utils") + { + enableInstanceVkExtDebugUtils( + supportedExtensions, + newExtensions); + } + else { - LAYER_LOG("WARNING: Cannot enable extension: %s", targetExt); + LAYER_ERR("Unknown instance extension: %s", newExt.c_str()); } } - bool targetEnabled = isInExtensionList( - targetExt, - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); - - // Enable the extension if we need to - std::vector newExtList; - if (targetSupported && !targetEnabled) - { - LAYER_LOG("Enabling additional extension: %s", targetExt); - newExtList = cloneExtensionList( - pCreateInfo->enabledExtensionCount, - pCreateInfo->ppEnabledExtensionNames); - - newExtList.push_back(targetExt); - - newCreateInfo.enabledExtensionCount = newExtList.size(); - newCreateInfo.ppEnabledExtensionNames = newExtList.data(); - } + // Patch extension pointer and size after extending it + newCreateInfo.enabledExtensionCount = newExtensions.size(); + newCreateInfo.ppEnabledExtensionNames = newExtensions.data(); chainInfo->u.pLayerInfo = chainInfo->u.pLayerInfo->pNext; auto result = fpCreateInstance(&newCreateInfo, pAllocator, pInstance); @@ -842,7 +855,7 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateDevice_default( std::vector newEnabledExtensions; // Enable timeline semaphores - enableTimelineSemaphores( + enableDeviceVkKhrTimelineSemaphore( newCreateInfo, supportedExtensions, newEnabledExtensions, diff --git a/source_common/framework/manual_functions.hpp b/source_common/framework/manual_functions.hpp index 1c8bdd5..c53500c 100644 --- a/source_common/framework/manual_functions.hpp +++ b/source_common/framework/manual_functions.hpp @@ -194,7 +194,7 @@ std::vector getDeviceExtensionList( * @return @c true if @c target is found in @c extensionList. */ bool isInExtensionList( - const char* target, + std::string target, uint32_t extensionCount, const char* const* extensionList);