From 378076704cc08f251ba66e64aa0c5ab3b089047e Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 13:05:31 +0000 Subject: [PATCH 1/9] Cleanup build --- CMakeLists.txt | 3 + generator/generate_vulkan_layer.py | 8 +- .../vk_codegen/device_dispatch_table.txt | 20 ++-- .../vk_codegen/instance_dispatch_table.txt | 22 ++-- generator/vk_codegen/root_CMakeLists.txt | 1 + generator/vk_codegen/source_CMakeLists.txt | 27 +---- generator/vk_common/CMakeLists.txt | 38 ++----- generator/vk_common/entry_utils.hpp | 20 ++-- generator/vk_common/utils.hpp | 103 +----------------- generator/vk_layer/source/device.cpp | 3 +- generator/vk_layer/source/device.hpp | 76 +++++++------ generator/vk_layer/source/entry.cpp | 4 +- generator/vk_layer/source/instance.cpp | 3 +- generator/vk_layer/source/instance.hpp | 64 ++++++----- layer_example/CMakeLists.txt | 3 +- layer_example/source/CMakeLists.txt | 27 +---- layer_example/source/device.cpp | 3 +- layer_example/source/device.hpp | 76 +++++++------ layer_example/source/entry.cpp | 4 +- layer_example/source/instance.cpp | 3 +- layer_example/source/instance.hpp | 64 ++++++----- .../source/layer_device_functions.cpp | 3 +- .../source/layer_device_functions.hpp | 9 +- source_common/CMakeLists.txt | 4 + source_common/comms/test/CMakeLists.txt | 8 +- source_common/compiler_helper.cmake | 67 ++++++++++++ source_common/framework/CMakeLists.txt | 38 ++----- .../framework/device_dispatch_table.hpp | 20 ++-- source_common/framework/entry_utils.hpp | 21 ++-- .../framework/instance_dispatch_table.hpp | 22 ++-- source_common/framework/utils.hpp | 103 +----------------- source_common/utils/misc.hpp | 103 ++++++++++++++++++ 32 files changed, 456 insertions(+), 514 deletions(-) create mode 100644 source_common/compiler_helper.cmake create mode 100644 source_common/utils/misc.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b06e853..56904f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,9 @@ set(CMAKE_CXX_STANDARD 20) project(libGPULayers_UnitTests VERSION 1.0.0) +# Standard CMake components +include(source_common/compiler_helper.cmake) + # Build steps set(LGL_UNITTEST ON) diff --git a/generator/generate_vulkan_layer.py b/generator/generate_vulkan_layer.py index 422a947..d833fe5 100644 --- a/generator/generate_vulkan_layer.py +++ b/generator/generate_vulkan_layer.py @@ -429,17 +429,13 @@ def main(): print(f'ERROR: Layer name "{args.layer_name}" is invalid') return 1 - # If overwrite is set, remove output directory if it exists - if args.overwrite: - shutil.rmtree(args.output, ignore_errors=True) - - # Check that output directory is either empty or non-existent + # Check that output directory is either empty or over-writable outdir = args.output if os.path.exists(outdir): if not os.path.isdir(outdir): print(f'ERROR: Output location "{outdir}" is not a directory') return 1 - if len(os.listdir(outdir)) != 0: + if len(os.listdir(outdir)) != 0 and not args.overwrite: print(f'ERROR: Output directory "{outdir}" is not empty') return 1 diff --git a/generator/vk_codegen/device_dispatch_table.txt b/generator/vk_codegen/device_dispatch_table.txt index 0c5ddbf..e2302db 100644 --- a/generator/vk_codegen/device_dispatch_table.txt +++ b/generator/vk_codegen/device_dispatch_table.txt @@ -2,23 +2,25 @@ #include -#include "device_functions.hpp" +#include "framework/device_functions.hpp" +#include "utils/misc.hpp" + #if __has_include ("layer_device_functions.hpp") #include "layer_device_functions.hpp" #endif /** - * \brief Interception table lookup entry. + * @brief Interception table lookup entry. */ struct DeviceInterceptTableEntry { /** - * \brief The function entrypoint name. + * @brief The function entrypoint name. */ const char* name; /** - * \brief The layer function pointer. + * @brief The layer function pointer. */ PFN_vkVoidFunction function; }; @@ -26,7 +28,7 @@ struct DeviceInterceptTableEntry #define ENTRY(fnc) { STR(fnc), reinterpret_cast(layer_##fnc) } /** - * \brief The device dispatch table used to call the driver. + * @brief The device dispatch table used to call the driver. */ static const struct DeviceInterceptTableEntry deviceIntercepts[] = { {ITABLE_MEMBERS} @@ -44,11 +46,11 @@ struct DeviceDispatchTable { #define ENTRY(fnc) table.fnc = (PFN_##fnc)getProcAddr(device, STR(fnc)) /** - * \brief Initialize the device dispatch table with driver function pointers. + * @brief Initialize the device dispatch table with driver function pointers. * - * \param device The device handle. - * \param getProcAddr The function getter for the driver/next layer down. - * \param table The table to populate. + * @param device The device handle. + * @param getProcAddr The function getter for the driver/next layer down. + * @param table The table to populate. */ static inline void initDriverDeviceDispatchTable( VkDevice device, diff --git a/generator/vk_codegen/instance_dispatch_table.txt b/generator/vk_codegen/instance_dispatch_table.txt index 33a6569..70f7552 100644 --- a/generator/vk_codegen/instance_dispatch_table.txt +++ b/generator/vk_codegen/instance_dispatch_table.txt @@ -2,23 +2,25 @@ #include -#include "instance_functions.hpp" +#include "framework/instance_functions.hpp" +#include "utils/misc.hpp" + #if __has_include ("layer_instance_functions.hpp") #include "layer_instance_functions.hpp" #endif /** - * \brief Interception table lookup entry. + * @brief Interception table lookup entry. */ struct InstanceInterceptTableEntry { /** - * \brief The function entrypoint name. + * @brief The function entrypoint name. */ const char* name; /** - * \brief The layer function pointer. + * @brief The layer function pointer. */ PFN_vkVoidFunction function; }; @@ -26,7 +28,7 @@ struct InstanceInterceptTableEntry #define ENTRY(fnc) { STR(fnc), reinterpret_cast(layer_##fnc) } /** - * \brief The instance dispatch table used to call the driver. + * @brief The instance dispatch table used to call the driver. */ static const struct InstanceInterceptTableEntry instanceIntercepts[] = { {ITABLE_MEMBERS} @@ -35,7 +37,7 @@ static const struct InstanceInterceptTableEntry instanceIntercepts[] = { #undef ENTRY /** - * \brief The instance dispatch table used to call the driver. + * @brief The instance dispatch table used to call the driver. */ struct InstanceDispatchTable { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; @@ -46,11 +48,11 @@ struct InstanceDispatchTable { #define ENTRY(fnc) table.fnc = (PFN_##fnc)getProcAddr(instance, STR(fnc)) /** - * \brief Initialize the instance dispatch table with driver function pointers. + * @brief Initialize the instance dispatch table with driver function pointers. * - * \param instance The instance handle. - * \param getProcAddr The function getter for the driver/next layer down. - * \param table The table to populate. + * @param instance The instance handle. + * @param getProcAddr The function getter for the driver/next layer down. + * @param table The table to populate. */ static inline void initDriverInstanceDispatchTable( VkInstance instance, diff --git a/generator/vk_codegen/root_CMakeLists.txt b/generator/vk_codegen/root_CMakeLists.txt index 7c163de..d60f796 100644 --- a/generator/vk_codegen/root_CMakeLists.txt +++ b/generator/vk_codegen/root_CMakeLists.txt @@ -29,6 +29,7 @@ project({PROJECT_NAME} VERSION 1.0.0) # Common configuration set(LGL_LOG_TAG, "{LAYER_NAME}") +include(../source_common/compiler_helper.cmake) # Build steps add_subdirectory(source) diff --git a/generator/vk_codegen/source_CMakeLists.txt b/generator/vk_codegen/source_CMakeLists.txt index bd35809..78a4fe8 100644 --- a/generator/vk_codegen/source_CMakeLists.txt +++ b/generator/vk_codegen/source_CMakeLists.txt @@ -21,18 +21,6 @@ # SOFTWARE. # ----------------------------------------------------------------------------- -# Compiler accepts GNU-style command line options -set(is_gnu_fe1 "$") - -# Compiler accepts AppleClang-style command line options, which is also GNU-style -set(is_gnu_fe2 "$") - -# Compiler accepts GNU-style command line options -set(is_gnu_fe "$") - -# Compiler is upstream clang with the standard frontend -set(is_clang "$>") - # Set output file names if (CMAKE_BUILD_TYPE STREQUAL "Release") set(VK_LAYER {LAYER_NAME}_sym) @@ -59,7 +47,7 @@ add_library( target_include_directories( ${VK_LAYER} PRIVATE - ${PROJECT_SOURCE_DIR}/../source_common/framework + ${PROJECT_SOURCE_DIR}/../source_common ${CMAKE_CURRENT_BINARY_DIR} .) @@ -67,16 +55,7 @@ target_include_directories( ${VK_LAYER} SYSTEM PRIVATE ../../khronos/vulkan/include) -target_compile_options( - ${VK_LAYER} PRIVATE - -fvisibility=hidden - -fvisibility-inlines-hidden - -fno-exceptions - -fno-rtti - -Wall - -Wextra - -Wno-missing-field-initializers - $<${is_clang}:-Wdocumentation>) +lgl_set_build_options(${VK_LAYER}) target_compile_definitions( ${VK_LAYER} PRIVATE @@ -85,7 +64,7 @@ target_compile_definitions( target_link_libraries( ${VK_LAYER} - layer_common + lib_layer_framework $<$:log>) if (CMAKE_BUILD_TYPE STREQUAL "Release") diff --git a/generator/vk_common/CMakeLists.txt b/generator/vk_common/CMakeLists.txt index b1c968b..0ca2695 100644 --- a/generator/vk_common/CMakeLists.txt +++ b/generator/vk_common/CMakeLists.txt @@ -21,54 +21,32 @@ # SOFTWARE. # ----------------------------------------------------------------------------- -# Compiler accepts GNU-style command line options -set(is_gnu_fe1 "$") - -# Compiler accepts AppleClang-style command line options, which is also GNU-style -set(is_gnu_fe2 "$") - -# Compiler accepts GNU-style command line options -set(is_gnu_fe "$") - -# Compiler is upstream clang with the standard frontend -set(is_clang "$>") - -set(DIR_TARGET layer_common) +set(BUILD_TARGET lib_layer_framework) add_library( - ${DIR_TARGET} STATIC + ${BUILD_TARGET} STATIC device_functions.cpp instance_functions.cpp) target_include_directories( - ${DIR_TARGET} PRIVATE + ${BUILD_TARGET} PRIVATE # Note, this includes from the layer-specific tree ${PROJECT_SOURCE_DIR}/source - .) + ../) target_include_directories( - ${DIR_TARGET} SYSTEM PRIVATE + ${BUILD_TARGET} SYSTEM PRIVATE ../../khronos/vulkan/include) -target_compile_options( - ${DIR_TARGET} PRIVATE - -fvisibility=hidden - -fvisibility-inlines-hidden - -fno-exceptions - -fno-rtti - -fpic - -Wall - -Wextra - -Wno-missing-field-initializers - $<${is_clang}:-Wdocumentation>) +lgl_set_build_options(${BUILD_TARGET}) # TODO: Log tag needs to come from child project target_compile_definitions( - ${DIR_TARGET} PRIVATE + ${BUILD_TARGET} PRIVATE $<$:VK_USE_PLATFORM_ANDROID_KHR=1> $<$:LGL_LOG_TAG="${LGL_LOG_TAG}">) # TODO: Remove this? target_link_libraries( - ${DIR_TARGET} + ${BUILD_TARGET} $<$:log>) diff --git a/generator/vk_common/entry_utils.hpp b/generator/vk_common/entry_utils.hpp index f03d691..2f9872a 100644 --- a/generator/vk_common/entry_utils.hpp +++ b/generator/vk_common/entry_utils.hpp @@ -53,7 +53,7 @@ #endif /** - * \brief The layer configuration. + * @brief The layer configuration. */ #define LGL_VERSION VK_MAKE_VERSION(LGL_VER_MAJOR, LGL_VER_MINOR, LGL_VER_PATCH) @@ -62,37 +62,37 @@ static const std::array layerProps = { }; /** - * \brief Dispatch table lookup entry. + * @brief Dispatch table lookup entry. */ struct DispatchTableEntry { /** - * \brief The function entrypoint name. + * @brief The function entrypoint name. */ const char* name; /** - * \brief The function pointer. + * @brief The function pointer. */ PFN_vkVoidFunction function; }; /** - * \brief Utility macro to define a lookup for a core function. + * @brief Utility macro to define a lookup for a core function. */ #define VK_TABLE_ENTRY(func) \ { STR(func), reinterpret_cast(func) } /** - * \brief Utility macro to define a lookup for a layer-dispatch-only function. + * @brief Utility macro to define a lookup for a layer-dispatch-only function. */ #define VK_TABLE_ENTRYL(func) \ { STR(func), reinterpret_cast(layer_##func) } /** - * \brief Fetch the layer function for a given instance entrypoint name. + * @brief Fetch the layer function for a given instance entrypoint name. * - * \param name The layer entry point name. + * @param name The layer entry point name. * * \return The layer function pointer, or \c nullptr if the layer doesn't * intercept the function. @@ -126,9 +126,9 @@ static PFN_vkVoidFunction get_instance_layer_function( } /** - * \brief Fetch the layer function for a given device entrypoint name. + * @brief Fetch the layer function for a given device entrypoint name. * - * \param name The layer entry point name. + * @param name The layer entry point name. * * \return The layer function pointer, or \c nullptr if the layer doesn't intercept the function. */ diff --git a/generator/vk_common/utils.hpp b/generator/vk_common/utils.hpp index 34b4e50..9ddbe92 100644 --- a/generator/vk_common/utils.hpp +++ b/generator/vk_common/utils.hpp @@ -47,9 +47,9 @@ struct user_tag {}; /** - * \brief Convert a dispatchable API handle to the underlying dispatch key. + * @brief Convert a dispatchable API handle to the underlying dispatch key. * - * \param ptr The dispatchable handle from the API. + * @param ptr The dispatchable handle from the API. * * \return The dispatch key. */ @@ -60,22 +60,12 @@ static inline void* getDispatchKey( } /** - * \brief Macro to stringize a value. - */ -#define STR(x) #x - -/** - * \brief Macro to mark a variable as unused. - */ -#define UNUSED(x) ((void)x); - -/** - * \brief Enable to enable API entrypoint tracing to the log/logcat. + * @brief Enable to enable API entrypoint tracing to the log/logcat. */ #define CONFIG_TRACE 0 /** - * \brief Enable to enable layer logging to the log/logcat. + * @brief Enable to enable layer logging to the log/logcat. */ #define CONFIG_LOG 1 @@ -109,88 +99,3 @@ static inline void* getDispatchKey( #define LAYER_LOG(...) #define LAYER_ERR(...) #endif - -/** - * \brief Format a string using printf formatting template strings. - * - * \param format The template string. - * \param args The variadic values used to populate the template. - */ -template -std::string fmt_string( - const std::string& format, - Args ... args -) { - // Determine size, adding one for the trailing nul - int size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; - if (size <= 0) - { - assert(false); - return ""; - } - - // Create the return string - std::unique_ptr buf(new char[size]); - std::snprintf(buf.get(), size, format.c_str(), args ...); - return std::string(buf.get(), buf.get() + size - 1); -} - -/** - * \brief Test if an element exists in an iterable container. - * - * \param elem The element to search for. - * \param cont The container to search. - * - * \return \c true if the item was found, else \c false. - */ -template -bool isIn(const E& elem, const C& cont) -{ - return std::find(std::begin(cont), std::end(cont), elem) != std::end(cont); -} - -/** - * \brief Test if an element exists in a mappable container. - * - * \param elem The element to search for. - * \param cont The container to search. - * - * \return \c true if the item was found, else \c false. - */ -template -bool isInMap(const E& elem, const C& cont) -{ - return cont.find(elem) != cont.end(); -} - -/** - * \brief Get the current time in seconds since an arbitrary epoch. - * - * \return The current time. - */ -static inline double getTime() -{ - timeval tv; - gettimeofday(&tv, 0); - return static_cast(tv.tv_sec) + static_cast(tv.tv_usec) * 1.0e-6; -} - -/** - * \brief Get a displayable pointer. - * - * On 64-bit systems this strips the MTE tag. - * - * \return The displayable pointer - */ -static inline uintptr_t getDisplayPointer( - void* pointer -) { - uintptr_t dispPointer = reinterpret_cast(pointer); - - if constexpr(sizeof(uintptr_t) == 8) - { - dispPointer &= 0x00FFFFFFFFFFFFFFull; - } - - return dispPointer; -} diff --git a/generator/vk_layer/source/device.cpp b/generator/vk_layer/source/device.cpp index 633cc90..82371c7 100644 --- a/generator/vk_layer/source/device.cpp +++ b/generator/vk_layer/source/device.cpp @@ -29,7 +29,8 @@ #include #include -#include "utils.hpp" +#include "framework/utils.hpp" + #include "device.hpp" #include "instance.hpp" diff --git a/generator/vk_layer/source/device.hpp b/generator/vk_layer/source/device.hpp index 615e1b8..26adc01 100644 --- a/generator/vk_layer/source/device.hpp +++ b/generator/vk_layer/source/device.hpp @@ -25,88 +25,96 @@ /** * @file - * This module implements layer tracking for VkDevice objects. + * Declares the root class for layer management of managing VkDevice objects. * * Role summary * ============ * - * Devices represent the core context used by the application to connect to the underlying graphics - * driver. A device object is the dispatch root for the Vulkan driver, so device commands all take - * some form of dispatchable handle that can be resolved into a unique per-device key. For the - * driver this key would simply be a pointer directly to the driver-internal device object, but for - * our layer we use a device dispatch key as an index in to the map to find the layer's driver - * object. + * Devices represent the core context used by the application to connect to the + * underlying graphics driver. A device object is the dispatch root for the + * Vulkan driver, so device commands all take some form of dispatchable handle + * that can be resolved into a unique per-device key. For the driver this key + * would simply be a pointer directly to the driver-internal device object, but + * for our layer we use a device dispatch key as an index in to the map to find + * the layer's driver object. * * Key properties * ============== * - * Unlike EGL contexts, Vulkan devices are designed to be used concurrently by multiple application - * threads. An application can have multiple concurrent devices (although this is less common than - * with OpenGL ES applications), and use each device from multiple threads. + * Unlike EGL contexts, Vulkan devices are designed to be used concurrently by + * multiple application threads. An application can have multiple concurrent + * devices (although this is less common than with OpenGL ES applications), and + * use each device from multiple threads. + * + * Access to the layer driver structures must therefore be kept thread-safe. + * For sake of simplicity, we generally implement this by: + * - Holding a global lock whenever any thread is inside layer code. + * - Releasing the global lock whenever the layer calls a driver function. */ #pragma once #include +#include "framework/device_dispatch_table.hpp" + #include "instance.hpp" -#include "device_dispatch_table.hpp" /** - * \brief This class implements the layer state tracker for a single device. + * @brief This class implements the layer state tracker for a single device. */ class Device { public: /** - * \brief Store a new device into the global store of dispatchable devices. + * @brief Store a new device into the global store of dispatchable devices. * - * \param handle The dispatchable device handle to use as an indirect key. - * \param device The \c Device object to store. + * @param handle The dispatchable device handle to use as an indirect key. + * @param device The \c Device object to store. */ static void store( VkDevice handle, std::unique_ptr device); /** - * \brief Fetch a device from the global store of dispatchable devices. + * @brief Fetch a device from the global store of dispatchable devices. * - * \param handle The dispatchable device handle to use as an indirect lookup. + * @param handle The dispatchable device handle to use as an indirect lookup. */ static Device* retrieve( VkDevice handle); /** - * \brief Fetch a device from the global store of dispatchable devices. + * @brief Fetch a device from the global store of dispatchable devices. * - * \param handle The dispatchable queue handle to use as an indirect lookup. + * @param handle The dispatchable queue handle to use as an indirect lookup. */ static Device* retrieve( VkQueue handle); /** - * \brief Fetch a device from the global store of dispatchable devices. + * @brief Fetch a device from the global store of dispatchable devices. * - * \param handle The dispatchable command buffer handle to use as an indirect lookup. + * @param handle The dispatchable command buffer handle to use as an indirect lookup. */ static Device* retrieve( VkCommandBuffer handle); /** - * \brief Drop a device from the global store of dispatchable devices. + * @brief Drop a device from the global store of dispatchable devices. * - * \param device The device to drop. + * @param device The device to drop. */ static void destroy( Device* device); /** - * \brief Create a new layer device object. + * @brief Create a new layer device object. * - * \param instance The layer instance object this device is created with. - * \param physicalDevice The physical device this logical device is for. - * \param device The device handle this device is created with. - * \param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. + * @param instance The layer instance object this device is created with. + * @param physicalDevice The physical device this logical device is for. + * @param device The device handle this device is created with. + * @param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. */ Device( Instance* instance, @@ -115,28 +123,28 @@ class Device PFN_vkGetDeviceProcAddr nlayerGetProcAddress); /** - * \brief Destroy this layer device object. + * @brief Destroy this layer device object. */ ~Device(); public: /** - * \brief The instance this device is created with. + * @brief The instance this device is created with. */ const Instance* instance; /** - * \brief The physical device this device is created with. + * @brief The physical device this device is created with. */ const VkPhysicalDevice physicalDevice; /** - * \brief The device handle this device is created with. + * @brief The device handle this device is created with. */ const VkDevice device; /** - * \brief The driver function dispatch table. + * @brief The driver function dispatch table. */ - DeviceDispatchTable driver { 0 }; + DeviceDispatchTable driver {}; }; diff --git a/generator/vk_layer/source/entry.cpp b/generator/vk_layer/source/entry.cpp index 50e67da..dc340cd 100644 --- a/generator/vk_layer/source/entry.cpp +++ b/generator/vk_layer/source/entry.cpp @@ -35,8 +35,8 @@ #include #include -#include "utils.hpp" -#include "entry_utils.hpp" +#include "framework/utils.hpp" +#include "framework/entry_utils.hpp" std::mutex g_vulkanLock; diff --git a/generator/vk_layer/source/instance.cpp b/generator/vk_layer/source/instance.cpp index e6108cf..af4936f 100644 --- a/generator/vk_layer/source/instance.cpp +++ b/generator/vk_layer/source/instance.cpp @@ -25,7 +25,8 @@ #include -#include "utils.hpp" +#include "framework/utils.hpp" + #include "instance.hpp" static std::unordered_map> g_instances; diff --git a/generator/vk_layer/source/instance.hpp b/generator/vk_layer/source/instance.hpp index 0ce2b50..8319722 100644 --- a/generator/vk_layer/source/instance.hpp +++ b/generator/vk_layer/source/instance.hpp @@ -25,24 +25,32 @@ /** * @file - * This module implements layer tracking for VkInstance objects. + * Declares the root class for layer management of managing VkInstance objects. * * Role summary * ============ * - * Instances represent the core context used by the application to connect to the OS graphics - * subsystem prior to connection to a specific device instance. An instance object is the dispatch - * root for the Vulkan subsystem, so instance commands all take some form of dispatchable handle - * that can be resolved into a unique per-instance key. For the driver this key would simply be a - * pointer directly to the driver-internal instance object, but for our layer we use a instance - * dispatch key as an index in to the map to find the layer's instance object. + * Instances represent the core context used by the application to connect to + * the OS graphics subsystem prior to connection to a specific device instance. + * An instance object is the dispatch root for the Vulkan subsystem, so + * instance commands all take some form of dispatchable handle that can be + * resolved into a unique per-instance key. For the driver this key would + * simply be a pointer directly to the driver-internal instance object, but for + * our layer we use a instance dispatch key as an index in to the map to find + * the layer's instance object. * * Key properties * ============== * - * Unlike EGL contexts, Vulkan instances are designed to be used concurrently by multiple - * application threads. An application can have multiple concurrent instances (although this is less - * common than with OpenGL ES applications), and use each instance from multiple threads. + * Unlike EGL contexts, Vulkan instances are designed to be used concurrently + * by multiple application threads. An application can have multiple concurrent + * instances (although this is less common than with OpenGL ES applications), + * and use each instance from multiple threads. + * + * Access to the layer driver structures must therefore be kept thread-safe. + * For sake of simplicity, we generally implement this by: + * - Holding a global lock whenever any thread is inside layer code. + * - Releasing the global lock whenever the layer calls a driver function. */ #pragma once @@ -53,10 +61,10 @@ #include #include -#include "instance_dispatch_table.hpp" +#include "framework/instance_dispatch_table.hpp" /** - * \brief This class implements the layer state tracker for a single instance. + * @brief This class implements the layer state tracker for a single instance. * * These objects are relatively light-weight, as they are rarely used once a VkDevice has been * created, but we need to track the chain-of-ownership as the instance is the root object that @@ -66,44 +74,44 @@ class Instance { public: /** - * \brief Store a new instance into the global store of dispatchable instances. + * @brief Store a new instance into the global store of dispatchable instances. * - * \param handle The dispatchable instance handle to use as an indirect key. - * \param instance The \c Instance object to store. + * @param handle The dispatchable instance handle to use as an indirect key. + * @param instance The \c Instance object to store. */ static void store( VkInstance handle, std::unique_ptr& instance); /** - * \brief Fetch an instance from the global store of dispatchable instances. + * @brief Fetch an instance from the global store of dispatchable instances. * - * \param handle The dispatchable instance handle to use as an indirect lookup. + * @param handle The dispatchable instance handle to use as an indirect lookup. */ static Instance* retrieve( VkInstance handle); /** - * \brief Fetch an instance from the global store of dispatchable instances. + * @brief Fetch an instance from the global store of dispatchable instances. * - * \param handle The dispatchable physical device handle to use as an indirect lookup. + * @param handle The dispatchable physical device handle to use as an indirect lookup. */ static Instance* retrieve( VkPhysicalDevice handle); /** - * \brief Drop an instance from the global store of dispatchable instances. + * @brief Drop an instance from the global store of dispatchable instances. * - * \param instance The instance to drop. + * @param instance The instance to drop. */ static void destroy( Instance* instance); /** - * \brief Create a new layer instance object. + * @brief Create a new layer instance object. * - * \param instance The instance handle this instance is created with. - * \param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. + * @param instance The instance handle this instance is created with. + * @param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. */ Instance( VkInstance instance, @@ -111,17 +119,17 @@ class Instance public: /** - * \brief The instance handle this instance is created with. + * @brief The instance handle this instance is created with. */ VkInstance instance; /** - * \brief The next layer's \c vkGetInstanceProcAddr() function pointer. + * @brief The next layer's \c vkGetInstanceProcAddr() function pointer. */ PFN_vkGetInstanceProcAddr nlayerGetProcAddress; /** - * \brief The driver function dispatch table. + * @brief The driver function dispatch table. */ - InstanceDispatchTable driver { 0 }; + InstanceDispatchTable driver {}; }; diff --git a/layer_example/CMakeLists.txt b/layer_example/CMakeLists.txt index c4de27b..ab4a0d6 100644 --- a/layer_example/CMakeLists.txt +++ b/layer_example/CMakeLists.txt @@ -25,10 +25,11 @@ cmake_minimum_required(VERSION 3.17) set(CMAKE_CXX_STANDARD 20) -project(Example VERSION 1.0.0) +project(VkLayerExample VERSION 1.0.0) # Common configuration set(LGL_LOG_TAG, "VkLayerExample") +include(../source_common/compiler_helper.cmake) # Build steps add_subdirectory(source) diff --git a/layer_example/source/CMakeLists.txt b/layer_example/source/CMakeLists.txt index 975761c..4c891cc 100644 --- a/layer_example/source/CMakeLists.txt +++ b/layer_example/source/CMakeLists.txt @@ -21,18 +21,6 @@ # SOFTWARE. # ----------------------------------------------------------------------------- -# Compiler accepts GNU-style command line options -set(is_gnu_fe1 "$") - -# Compiler accepts AppleClang-style command line options, which is also GNU-style -set(is_gnu_fe2 "$") - -# Compiler accepts GNU-style command line options -set(is_gnu_fe "$") - -# Compiler is upstream clang with the standard frontend -set(is_clang "$>") - # Set output file names if (CMAKE_BUILD_TYPE STREQUAL "Release") set(VK_LAYER VkLayerExample_sym) @@ -60,7 +48,7 @@ add_library( target_include_directories( ${VK_LAYER} PRIVATE - ${PROJECT_SOURCE_DIR}/../source_common/framework + ${PROJECT_SOURCE_DIR}/../source_common ${CMAKE_CURRENT_BINARY_DIR} .) @@ -68,16 +56,7 @@ target_include_directories( ${VK_LAYER} SYSTEM PRIVATE ../../khronos/vulkan/include) -target_compile_options( - ${VK_LAYER} PRIVATE - -fvisibility=hidden - -fvisibility-inlines-hidden - -fno-exceptions - -fno-rtti - -Wall - -Wextra - -Wno-missing-field-initializers - $<${is_clang}:-Wdocumentation>) +lgl_set_build_options(${VK_LAYER}) target_compile_definitions( ${VK_LAYER} PRIVATE @@ -86,7 +65,7 @@ target_compile_definitions( target_link_libraries( ${VK_LAYER} - layer_common + lib_layer_framework $<$:log>) if (CMAKE_BUILD_TYPE STREQUAL "Release") diff --git a/layer_example/source/device.cpp b/layer_example/source/device.cpp index 633cc90..82371c7 100644 --- a/layer_example/source/device.cpp +++ b/layer_example/source/device.cpp @@ -29,7 +29,8 @@ #include #include -#include "utils.hpp" +#include "framework/utils.hpp" + #include "device.hpp" #include "instance.hpp" diff --git a/layer_example/source/device.hpp b/layer_example/source/device.hpp index 615e1b8..26adc01 100644 --- a/layer_example/source/device.hpp +++ b/layer_example/source/device.hpp @@ -25,88 +25,96 @@ /** * @file - * This module implements layer tracking for VkDevice objects. + * Declares the root class for layer management of managing VkDevice objects. * * Role summary * ============ * - * Devices represent the core context used by the application to connect to the underlying graphics - * driver. A device object is the dispatch root for the Vulkan driver, so device commands all take - * some form of dispatchable handle that can be resolved into a unique per-device key. For the - * driver this key would simply be a pointer directly to the driver-internal device object, but for - * our layer we use a device dispatch key as an index in to the map to find the layer's driver - * object. + * Devices represent the core context used by the application to connect to the + * underlying graphics driver. A device object is the dispatch root for the + * Vulkan driver, so device commands all take some form of dispatchable handle + * that can be resolved into a unique per-device key. For the driver this key + * would simply be a pointer directly to the driver-internal device object, but + * for our layer we use a device dispatch key as an index in to the map to find + * the layer's driver object. * * Key properties * ============== * - * Unlike EGL contexts, Vulkan devices are designed to be used concurrently by multiple application - * threads. An application can have multiple concurrent devices (although this is less common than - * with OpenGL ES applications), and use each device from multiple threads. + * Unlike EGL contexts, Vulkan devices are designed to be used concurrently by + * multiple application threads. An application can have multiple concurrent + * devices (although this is less common than with OpenGL ES applications), and + * use each device from multiple threads. + * + * Access to the layer driver structures must therefore be kept thread-safe. + * For sake of simplicity, we generally implement this by: + * - Holding a global lock whenever any thread is inside layer code. + * - Releasing the global lock whenever the layer calls a driver function. */ #pragma once #include +#include "framework/device_dispatch_table.hpp" + #include "instance.hpp" -#include "device_dispatch_table.hpp" /** - * \brief This class implements the layer state tracker for a single device. + * @brief This class implements the layer state tracker for a single device. */ class Device { public: /** - * \brief Store a new device into the global store of dispatchable devices. + * @brief Store a new device into the global store of dispatchable devices. * - * \param handle The dispatchable device handle to use as an indirect key. - * \param device The \c Device object to store. + * @param handle The dispatchable device handle to use as an indirect key. + * @param device The \c Device object to store. */ static void store( VkDevice handle, std::unique_ptr device); /** - * \brief Fetch a device from the global store of dispatchable devices. + * @brief Fetch a device from the global store of dispatchable devices. * - * \param handle The dispatchable device handle to use as an indirect lookup. + * @param handle The dispatchable device handle to use as an indirect lookup. */ static Device* retrieve( VkDevice handle); /** - * \brief Fetch a device from the global store of dispatchable devices. + * @brief Fetch a device from the global store of dispatchable devices. * - * \param handle The dispatchable queue handle to use as an indirect lookup. + * @param handle The dispatchable queue handle to use as an indirect lookup. */ static Device* retrieve( VkQueue handle); /** - * \brief Fetch a device from the global store of dispatchable devices. + * @brief Fetch a device from the global store of dispatchable devices. * - * \param handle The dispatchable command buffer handle to use as an indirect lookup. + * @param handle The dispatchable command buffer handle to use as an indirect lookup. */ static Device* retrieve( VkCommandBuffer handle); /** - * \brief Drop a device from the global store of dispatchable devices. + * @brief Drop a device from the global store of dispatchable devices. * - * \param device The device to drop. + * @param device The device to drop. */ static void destroy( Device* device); /** - * \brief Create a new layer device object. + * @brief Create a new layer device object. * - * \param instance The layer instance object this device is created with. - * \param physicalDevice The physical device this logical device is for. - * \param device The device handle this device is created with. - * \param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. + * @param instance The layer instance object this device is created with. + * @param physicalDevice The physical device this logical device is for. + * @param device The device handle this device is created with. + * @param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. */ Device( Instance* instance, @@ -115,28 +123,28 @@ class Device PFN_vkGetDeviceProcAddr nlayerGetProcAddress); /** - * \brief Destroy this layer device object. + * @brief Destroy this layer device object. */ ~Device(); public: /** - * \brief The instance this device is created with. + * @brief The instance this device is created with. */ const Instance* instance; /** - * \brief The physical device this device is created with. + * @brief The physical device this device is created with. */ const VkPhysicalDevice physicalDevice; /** - * \brief The device handle this device is created with. + * @brief The device handle this device is created with. */ const VkDevice device; /** - * \brief The driver function dispatch table. + * @brief The driver function dispatch table. */ - DeviceDispatchTable driver { 0 }; + DeviceDispatchTable driver {}; }; diff --git a/layer_example/source/entry.cpp b/layer_example/source/entry.cpp index 50e67da..dc340cd 100644 --- a/layer_example/source/entry.cpp +++ b/layer_example/source/entry.cpp @@ -35,8 +35,8 @@ #include #include -#include "utils.hpp" -#include "entry_utils.hpp" +#include "framework/utils.hpp" +#include "framework/entry_utils.hpp" std::mutex g_vulkanLock; diff --git a/layer_example/source/instance.cpp b/layer_example/source/instance.cpp index e6108cf..af4936f 100644 --- a/layer_example/source/instance.cpp +++ b/layer_example/source/instance.cpp @@ -25,7 +25,8 @@ #include -#include "utils.hpp" +#include "framework/utils.hpp" + #include "instance.hpp" static std::unordered_map> g_instances; diff --git a/layer_example/source/instance.hpp b/layer_example/source/instance.hpp index 0ce2b50..8319722 100644 --- a/layer_example/source/instance.hpp +++ b/layer_example/source/instance.hpp @@ -25,24 +25,32 @@ /** * @file - * This module implements layer tracking for VkInstance objects. + * Declares the root class for layer management of managing VkInstance objects. * * Role summary * ============ * - * Instances represent the core context used by the application to connect to the OS graphics - * subsystem prior to connection to a specific device instance. An instance object is the dispatch - * root for the Vulkan subsystem, so instance commands all take some form of dispatchable handle - * that can be resolved into a unique per-instance key. For the driver this key would simply be a - * pointer directly to the driver-internal instance object, but for our layer we use a instance - * dispatch key as an index in to the map to find the layer's instance object. + * Instances represent the core context used by the application to connect to + * the OS graphics subsystem prior to connection to a specific device instance. + * An instance object is the dispatch root for the Vulkan subsystem, so + * instance commands all take some form of dispatchable handle that can be + * resolved into a unique per-instance key. For the driver this key would + * simply be a pointer directly to the driver-internal instance object, but for + * our layer we use a instance dispatch key as an index in to the map to find + * the layer's instance object. * * Key properties * ============== * - * Unlike EGL contexts, Vulkan instances are designed to be used concurrently by multiple - * application threads. An application can have multiple concurrent instances (although this is less - * common than with OpenGL ES applications), and use each instance from multiple threads. + * Unlike EGL contexts, Vulkan instances are designed to be used concurrently + * by multiple application threads. An application can have multiple concurrent + * instances (although this is less common than with OpenGL ES applications), + * and use each instance from multiple threads. + * + * Access to the layer driver structures must therefore be kept thread-safe. + * For sake of simplicity, we generally implement this by: + * - Holding a global lock whenever any thread is inside layer code. + * - Releasing the global lock whenever the layer calls a driver function. */ #pragma once @@ -53,10 +61,10 @@ #include #include -#include "instance_dispatch_table.hpp" +#include "framework/instance_dispatch_table.hpp" /** - * \brief This class implements the layer state tracker for a single instance. + * @brief This class implements the layer state tracker for a single instance. * * These objects are relatively light-weight, as they are rarely used once a VkDevice has been * created, but we need to track the chain-of-ownership as the instance is the root object that @@ -66,44 +74,44 @@ class Instance { public: /** - * \brief Store a new instance into the global store of dispatchable instances. + * @brief Store a new instance into the global store of dispatchable instances. * - * \param handle The dispatchable instance handle to use as an indirect key. - * \param instance The \c Instance object to store. + * @param handle The dispatchable instance handle to use as an indirect key. + * @param instance The \c Instance object to store. */ static void store( VkInstance handle, std::unique_ptr& instance); /** - * \brief Fetch an instance from the global store of dispatchable instances. + * @brief Fetch an instance from the global store of dispatchable instances. * - * \param handle The dispatchable instance handle to use as an indirect lookup. + * @param handle The dispatchable instance handle to use as an indirect lookup. */ static Instance* retrieve( VkInstance handle); /** - * \brief Fetch an instance from the global store of dispatchable instances. + * @brief Fetch an instance from the global store of dispatchable instances. * - * \param handle The dispatchable physical device handle to use as an indirect lookup. + * @param handle The dispatchable physical device handle to use as an indirect lookup. */ static Instance* retrieve( VkPhysicalDevice handle); /** - * \brief Drop an instance from the global store of dispatchable instances. + * @brief Drop an instance from the global store of dispatchable instances. * - * \param instance The instance to drop. + * @param instance The instance to drop. */ static void destroy( Instance* instance); /** - * \brief Create a new layer instance object. + * @brief Create a new layer instance object. * - * \param instance The instance handle this instance is created with. - * \param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. + * @param instance The instance handle this instance is created with. + * @param nlayerGetProcAddress The vkGetProcAddress function in the driver/next layer down. */ Instance( VkInstance instance, @@ -111,17 +119,17 @@ class Instance public: /** - * \brief The instance handle this instance is created with. + * @brief The instance handle this instance is created with. */ VkInstance instance; /** - * \brief The next layer's \c vkGetInstanceProcAddr() function pointer. + * @brief The next layer's \c vkGetInstanceProcAddr() function pointer. */ PFN_vkGetInstanceProcAddr nlayerGetProcAddress; /** - * \brief The driver function dispatch table. + * @brief The driver function dispatch table. */ - InstanceDispatchTable driver { 0 }; + InstanceDispatchTable driver {}; }; diff --git a/layer_example/source/layer_device_functions.cpp b/layer_example/source/layer_device_functions.cpp index dc6e4d2..d1270b1 100644 --- a/layer_example/source/layer_device_functions.cpp +++ b/layer_example/source/layer_device_functions.cpp @@ -27,7 +27,8 @@ #include #include -#include "utils.hpp" +#include "framework/utils.hpp" + #include "device.hpp" #include "layer_device_functions.hpp" diff --git a/layer_example/source/layer_device_functions.hpp b/layer_example/source/layer_device_functions.hpp index adcacf0..56fb1c7 100644 --- a/layer_example/source/layer_device_functions.hpp +++ b/layer_example/source/layer_device_functions.hpp @@ -27,9 +27,10 @@ #include #include -#include "utils.hpp" +#include "framework/device_functions.hpp" +#include "framework/utils.hpp" + #include "device.hpp" -#include "device_functions.hpp" extern std::mutex g_vulkanLock; @@ -40,7 +41,6 @@ VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRenderPass( const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents); - /* See Vulkan API for documentation. */ template <> VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRenderPass2( @@ -48,7 +48,6 @@ VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRenderPass2( const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); - /* See Vulkan API for documentation. */ template <> VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRenderPass2KHR( @@ -56,14 +55,12 @@ VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRenderPass2KHR( const VkRenderPassBeginInfo* pRenderPassBegin, const VkSubpassBeginInfo* pSubpassBeginInfo); - /* See Vulkan API for documentation. */ template <> VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRendering( VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo); - /* See Vulkan API for documentation. */ template <> VKAPI_ATTR void VKAPI_CALL layer_vkCmdBeginRenderingKHR( diff --git a/source_common/CMakeLists.txt b/source_common/CMakeLists.txt index ca4c7df..1f37093 100644 --- a/source_common/CMakeLists.txt +++ b/source_common/CMakeLists.txt @@ -21,4 +21,8 @@ # SOFTWARE. # ----------------------------------------------------------------------------- +# Note: The framework component cannot be built as a common library, because it +# depends on per-layer implementations of the root intercept Instance and +# Device classes which get specialized for each use case. + add_subdirectory(comms) diff --git a/source_common/comms/test/CMakeLists.txt b/source_common/comms/test/CMakeLists.txt index f43357f..8970930 100644 --- a/source_common/comms/test/CMakeLists.txt +++ b/source_common/comms/test/CMakeLists.txt @@ -64,9 +64,11 @@ target_link_libraries( lib_layer_comms gtest_main) -add_test( - NAME ${TEST_BINARY} - COMMAND ${TEST_BINARY}) +# Exclude from ctest for now because it needs user to manually run the +# external server program before the test can pass +#add_test( +# NAME ${TEST_BINARY} +# COMMAND ${TEST_BINARY}) install( TARGETS ${TEST_BINARY} diff --git a/source_common/compiler_helper.cmake b/source_common/compiler_helper.cmake new file mode 100644 index 0000000..3859219 --- /dev/null +++ b/source_common/compiler_helper.cmake @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: MIT +# ----------------------------------------------------------------------------- +# Copyright (c) 2024 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 +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# ----------------------------------------------------------------------------- + +# Compiler accepts MSVC-style command line options +set(is_msvc_fe "$") + +# Compiler accepts GNU-style command line options +set(is_gnu_fe1 "$") + +# Compiler accepts AppleClang-style command line options, which is also GNU-style +set(is_gnu_fe2 "$") + +# Compiler accepts GNU-style command line options +set(is_gnu_fe "$") + +# Compiler is Visual Studio cl.exe +set(is_msvccl "$>") + +# Compiler is Visual Studio clangcl.exe +set(is_clangcl "$>") + +# Compiler is upstream clang with the standard frontend +set(is_clang "$>") + +# Utility macro to set standard compiler options +macro(lgl_set_build_options BUILD_TARGET_NAME) + + target_compile_options( + ${BUILD_TARGET_NAME} PRIVATE + # Minimized visibility warnings + $<${is_gnu_fe}:-fvisibility=hidden> + $<${is_gnu_fe}:-fvisibility-inlines-hidden> + + # Strict warnings + $<${is_gnu_fe}:-Wall> + $<${is_gnu_fe}:-Wextra> + $<${is_gnu_fe}:-Wpedantic> + $<${is_gnu_fe}:-Werror> + $<${is_gnu_fe}:-Wshadow> + $<${is_gnu_fe}:-Wdouble-promotion> + $<${is_clang}:-Wdocumentation> + + # Feature disabled + $<${is_gnu_fe}:-fno-exceptions> + $<${is_gnu_fe}:-fno-rtti>) + +endmacro() diff --git a/source_common/framework/CMakeLists.txt b/source_common/framework/CMakeLists.txt index b1c968b..0ca2695 100644 --- a/source_common/framework/CMakeLists.txt +++ b/source_common/framework/CMakeLists.txt @@ -21,54 +21,32 @@ # SOFTWARE. # ----------------------------------------------------------------------------- -# Compiler accepts GNU-style command line options -set(is_gnu_fe1 "$") - -# Compiler accepts AppleClang-style command line options, which is also GNU-style -set(is_gnu_fe2 "$") - -# Compiler accepts GNU-style command line options -set(is_gnu_fe "$") - -# Compiler is upstream clang with the standard frontend -set(is_clang "$>") - -set(DIR_TARGET layer_common) +set(BUILD_TARGET lib_layer_framework) add_library( - ${DIR_TARGET} STATIC + ${BUILD_TARGET} STATIC device_functions.cpp instance_functions.cpp) target_include_directories( - ${DIR_TARGET} PRIVATE + ${BUILD_TARGET} PRIVATE # Note, this includes from the layer-specific tree ${PROJECT_SOURCE_DIR}/source - .) + ../) target_include_directories( - ${DIR_TARGET} SYSTEM PRIVATE + ${BUILD_TARGET} SYSTEM PRIVATE ../../khronos/vulkan/include) -target_compile_options( - ${DIR_TARGET} PRIVATE - -fvisibility=hidden - -fvisibility-inlines-hidden - -fno-exceptions - -fno-rtti - -fpic - -Wall - -Wextra - -Wno-missing-field-initializers - $<${is_clang}:-Wdocumentation>) +lgl_set_build_options(${BUILD_TARGET}) # TODO: Log tag needs to come from child project target_compile_definitions( - ${DIR_TARGET} PRIVATE + ${BUILD_TARGET} PRIVATE $<$:VK_USE_PLATFORM_ANDROID_KHR=1> $<$:LGL_LOG_TAG="${LGL_LOG_TAG}">) # TODO: Remove this? target_link_libraries( - ${DIR_TARGET} + ${BUILD_TARGET} $<$:log>) diff --git a/source_common/framework/device_dispatch_table.hpp b/source_common/framework/device_dispatch_table.hpp index 562495a..cc16f1c 100644 --- a/source_common/framework/device_dispatch_table.hpp +++ b/source_common/framework/device_dispatch_table.hpp @@ -27,23 +27,25 @@ #include -#include "device_functions.hpp" +#include "framework/device_functions.hpp" +#include "utils/misc.hpp" + #if __has_include ("layer_device_functions.hpp") #include "layer_device_functions.hpp" #endif /** - * \brief Interception table lookup entry. + * @brief Interception table lookup entry. */ struct DeviceInterceptTableEntry { /** - * \brief The function entrypoint name. + * @brief The function entrypoint name. */ const char* name; /** - * \brief The layer function pointer. + * @brief The layer function pointer. */ PFN_vkVoidFunction function; }; @@ -51,7 +53,7 @@ struct DeviceInterceptTableEntry #define ENTRY(fnc) { STR(fnc), reinterpret_cast(layer_##fnc) } /** - * \brief The device dispatch table used to call the driver. + * @brief The device dispatch table used to call the driver. */ static const struct DeviceInterceptTableEntry deviceIntercepts[] = { ENTRY(vkAcquireNextImage2KHR), @@ -961,11 +963,11 @@ struct DeviceDispatchTable { #define ENTRY(fnc) table.fnc = (PFN_##fnc)getProcAddr(device, STR(fnc)) /** - * \brief Initialize the device dispatch table with driver function pointers. + * @brief Initialize the device dispatch table with driver function pointers. * - * \param device The device handle. - * \param getProcAddr The function getter for the driver/next layer down. - * \param table The table to populate. + * @param device The device handle. + * @param getProcAddr The function getter for the driver/next layer down. + * @param table The table to populate. */ static inline void initDriverDeviceDispatchTable( VkDevice device, diff --git a/source_common/framework/entry_utils.hpp b/source_common/framework/entry_utils.hpp index 395698c..2f9872a 100644 --- a/source_common/framework/entry_utils.hpp +++ b/source_common/framework/entry_utils.hpp @@ -43,7 +43,6 @@ #include "device_dispatch_table.hpp" #include "device_functions.hpp" -extern std::mutex g_vulkanLock; #define VK_LAYER_EXPORT __attribute__((visibility("default"))) @@ -54,7 +53,7 @@ extern std::mutex g_vulkanLock; #endif /** - * \brief The layer configuration. + * @brief The layer configuration. */ #define LGL_VERSION VK_MAKE_VERSION(LGL_VER_MAJOR, LGL_VER_MINOR, LGL_VER_PATCH) @@ -63,37 +62,37 @@ static const std::array layerProps = { }; /** - * \brief Dispatch table lookup entry. + * @brief Dispatch table lookup entry. */ struct DispatchTableEntry { /** - * \brief The function entrypoint name. + * @brief The function entrypoint name. */ const char* name; /** - * \brief The function pointer. + * @brief The function pointer. */ PFN_vkVoidFunction function; }; /** - * \brief Utility macro to define a lookup for a core function. + * @brief Utility macro to define a lookup for a core function. */ #define VK_TABLE_ENTRY(func) \ { STR(func), reinterpret_cast(func) } /** - * \brief Utility macro to define a lookup for a layer-dispatch-only function. + * @brief Utility macro to define a lookup for a layer-dispatch-only function. */ #define VK_TABLE_ENTRYL(func) \ { STR(func), reinterpret_cast(layer_##func) } /** - * \brief Fetch the layer function for a given instance entrypoint name. + * @brief Fetch the layer function for a given instance entrypoint name. * - * \param name The layer entry point name. + * @param name The layer entry point name. * * \return The layer function pointer, or \c nullptr if the layer doesn't * intercept the function. @@ -127,9 +126,9 @@ static PFN_vkVoidFunction get_instance_layer_function( } /** - * \brief Fetch the layer function for a given device entrypoint name. + * @brief Fetch the layer function for a given device entrypoint name. * - * \param name The layer entry point name. + * @param name The layer entry point name. * * \return The layer function pointer, or \c nullptr if the layer doesn't intercept the function. */ diff --git a/source_common/framework/instance_dispatch_table.hpp b/source_common/framework/instance_dispatch_table.hpp index 870fe7c..3b01941 100644 --- a/source_common/framework/instance_dispatch_table.hpp +++ b/source_common/framework/instance_dispatch_table.hpp @@ -27,23 +27,25 @@ #include -#include "instance_functions.hpp" +#include "framework/instance_functions.hpp" +#include "utils/misc.hpp" + #if __has_include ("layer_instance_functions.hpp") #include "layer_instance_functions.hpp" #endif /** - * \brief Interception table lookup entry. + * @brief Interception table lookup entry. */ struct InstanceInterceptTableEntry { /** - * \brief The function entrypoint name. + * @brief The function entrypoint name. */ const char* name; /** - * \brief The layer function pointer. + * @brief The layer function pointer. */ PFN_vkVoidFunction function; }; @@ -51,7 +53,7 @@ struct InstanceInterceptTableEntry #define ENTRY(fnc) { STR(fnc), reinterpret_cast(layer_##fnc) } /** - * \brief The instance dispatch table used to call the driver. + * @brief The instance dispatch table used to call the driver. */ static const struct InstanceInterceptTableEntry instanceIntercepts[] = { #if defined(VK_USE_PLATFORM_ANDROID_KHR) @@ -131,7 +133,7 @@ static const struct InstanceInterceptTableEntry instanceIntercepts[] = { #undef ENTRY /** - * \brief The instance dispatch table used to call the driver. + * @brief The instance dispatch table used to call the driver. */ struct InstanceDispatchTable { PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; @@ -212,11 +214,11 @@ struct InstanceDispatchTable { #define ENTRY(fnc) table.fnc = (PFN_##fnc)getProcAddr(instance, STR(fnc)) /** - * \brief Initialize the instance dispatch table with driver function pointers. + * @brief Initialize the instance dispatch table with driver function pointers. * - * \param instance The instance handle. - * \param getProcAddr The function getter for the driver/next layer down. - * \param table The table to populate. + * @param instance The instance handle. + * @param getProcAddr The function getter for the driver/next layer down. + * @param table The table to populate. */ static inline void initDriverInstanceDispatchTable( VkInstance instance, diff --git a/source_common/framework/utils.hpp b/source_common/framework/utils.hpp index 34b4e50..9ddbe92 100644 --- a/source_common/framework/utils.hpp +++ b/source_common/framework/utils.hpp @@ -47,9 +47,9 @@ struct user_tag {}; /** - * \brief Convert a dispatchable API handle to the underlying dispatch key. + * @brief Convert a dispatchable API handle to the underlying dispatch key. * - * \param ptr The dispatchable handle from the API. + * @param ptr The dispatchable handle from the API. * * \return The dispatch key. */ @@ -60,22 +60,12 @@ static inline void* getDispatchKey( } /** - * \brief Macro to stringize a value. - */ -#define STR(x) #x - -/** - * \brief Macro to mark a variable as unused. - */ -#define UNUSED(x) ((void)x); - -/** - * \brief Enable to enable API entrypoint tracing to the log/logcat. + * @brief Enable to enable API entrypoint tracing to the log/logcat. */ #define CONFIG_TRACE 0 /** - * \brief Enable to enable layer logging to the log/logcat. + * @brief Enable to enable layer logging to the log/logcat. */ #define CONFIG_LOG 1 @@ -109,88 +99,3 @@ static inline void* getDispatchKey( #define LAYER_LOG(...) #define LAYER_ERR(...) #endif - -/** - * \brief Format a string using printf formatting template strings. - * - * \param format The template string. - * \param args The variadic values used to populate the template. - */ -template -std::string fmt_string( - const std::string& format, - Args ... args -) { - // Determine size, adding one for the trailing nul - int size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; - if (size <= 0) - { - assert(false); - return ""; - } - - // Create the return string - std::unique_ptr buf(new char[size]); - std::snprintf(buf.get(), size, format.c_str(), args ...); - return std::string(buf.get(), buf.get() + size - 1); -} - -/** - * \brief Test if an element exists in an iterable container. - * - * \param elem The element to search for. - * \param cont The container to search. - * - * \return \c true if the item was found, else \c false. - */ -template -bool isIn(const E& elem, const C& cont) -{ - return std::find(std::begin(cont), std::end(cont), elem) != std::end(cont); -} - -/** - * \brief Test if an element exists in a mappable container. - * - * \param elem The element to search for. - * \param cont The container to search. - * - * \return \c true if the item was found, else \c false. - */ -template -bool isInMap(const E& elem, const C& cont) -{ - return cont.find(elem) != cont.end(); -} - -/** - * \brief Get the current time in seconds since an arbitrary epoch. - * - * \return The current time. - */ -static inline double getTime() -{ - timeval tv; - gettimeofday(&tv, 0); - return static_cast(tv.tv_sec) + static_cast(tv.tv_usec) * 1.0e-6; -} - -/** - * \brief Get a displayable pointer. - * - * On 64-bit systems this strips the MTE tag. - * - * \return The displayable pointer - */ -static inline uintptr_t getDisplayPointer( - void* pointer -) { - uintptr_t dispPointer = reinterpret_cast(pointer); - - if constexpr(sizeof(uintptr_t) == 8) - { - dispPointer &= 0x00FFFFFFFFFFFFFFull; - } - - return dispPointer; -} diff --git a/source_common/utils/misc.hpp b/source_common/utils/misc.hpp new file mode 100644 index 0000000..d80d627 --- /dev/null +++ b/source_common/utils/misc.hpp @@ -0,0 +1,103 @@ +/* + * This confidential and proprietary software may be used only as + * authorised by a licensing agreement from Arm Limited. + * Copyright 2022-2024 Arm Ltd. All Rights Reserved. + * The entire notice above must be reproduced on all authorised + * copies and copies may only be made to the extent permitted + * by a licensing agreement from Arm Limited. + */ + +/** + * @file + * This module implements miscellaneous utility functions. + */ + +#include +#include + +/** + * @brief Macro to stringize a value. + */ +#define STR(x) #x + +/** + * @brief Macro to mark a variable as unused. + */ +#define UNUSED(x) ((void)x); + +/** + * @brief Format a string using printf formatting template strings. + * + * @param format The template string. + * @param args The variadic values used to populate the template. + */ +template +std::string fmt_string( + const std::string& format, + Args ... args +) { + // Determine size, adding one for the trailing nul + int size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; + if (size <= 0) + { + assert(false); + return ""; + } + + // Create the return string + std::unique_ptr buf(new char[size]); + std::snprintf(buf.get(), size, format.c_str(), args ...); + return std::string(buf.get(), buf.get() + size - 1); +} + +/** + * @brief Test if an element exists in an iterable container. + * + * @param elem The element to search for. + * @param cont The container to search. + * + * @return @c true if the item was found, else @c false. + */ +template +bool isIn( + const E& elem, + const C& cont +) { + return std::find(std::begin(cont), std::end(cont), elem) != std::end(cont); +} + +/** + * @brief Test if an element exists in a mappable container. + * + * @param elem The element to search for. + * @param cont The container to search. + * + * @return @c true if the item was found, else @c false. + */ +template +bool isInMap( + const E& elem, + const C& cont +) { + return cont.find(elem) != cont.end(); +} + +/** + * @brief Get a displayable pointer. + * + * On 64-bit systems this strips the MTE tag. + * + * @return The displayable pointer + */ +static inline uintptr_t getDisplayPointer( + void* pointer +) { + uintptr_t dispPointer = reinterpret_cast(pointer); + + if constexpr(sizeof(uintptr_t) == 8) + { + dispPointer &= 0x00FFFFFFFFFFFFFFull; + } + + return dispPointer; +} From 4afcf6e1abe655ae7c04c9db378e42d1570531b8 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 13:56:08 +0000 Subject: [PATCH 2/9] Fix missing header --- source_common/utils/misc.hpp | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/source_common/utils/misc.hpp b/source_common/utils/misc.hpp index d80d627..b55192c 100644 --- a/source_common/utils/misc.hpp +++ b/source_common/utils/misc.hpp @@ -1,10 +1,26 @@ /* - * This confidential and proprietary software may be used only as - * authorised by a licensing agreement from Arm Limited. - * Copyright 2022-2024 Arm Ltd. All Rights Reserved. - * The entire notice above must be reproduced on all authorised - * copies and copies may only be made to the extent permitted - * by a licensing agreement from Arm Limited. + * SPDX-License-Identifier: MIT + * ---------------------------------------------------------------------------- + * Copyright (c) 2022-2024 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 + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * ---------------------------------------------------------------------------- */ /** @@ -12,6 +28,8 @@ * This module implements miscellaneous utility functions. */ +#pragma once + #include #include From 5e75b60e9bb3a205b56139f8fab0b63a79984a39 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:06:30 +0000 Subject: [PATCH 3/9] Fix GCC shadowing warnings --- generator/vk_layer/source/device.cpp | 12 ++++++------ generator/vk_layer/source/instance.cpp | 8 ++++---- source_common/CMakeLists.txt | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/generator/vk_layer/source/device.cpp b/generator/vk_layer/source/device.cpp index 82371c7..580e339 100644 --- a/generator/vk_layer/source/device.cpp +++ b/generator/vk_layer/source/device.cpp @@ -81,13 +81,13 @@ void Device::destroy( /* See header for documentation. */ Device::Device( - Instance* instance, - VkPhysicalDevice physicalDevice, - VkDevice device, + Instance* _instance, + VkPhysicalDevice _physicalDevice, + VkDevice _device, PFN_vkGetDeviceProcAddr nlayerGetProcAddress -): instance(instance), - physicalDevice(physicalDevice), - device(device) +): instance(_instance), + physicalDevice(_physicalDevice), + device(_device) { initDriverDeviceDispatchTable(device, nlayerGetProcAddress, driver); } diff --git a/generator/vk_layer/source/instance.cpp b/generator/vk_layer/source/instance.cpp index af4936f..6ac278e 100644 --- a/generator/vk_layer/source/instance.cpp +++ b/generator/vk_layer/source/instance.cpp @@ -67,10 +67,10 @@ void Instance::destroy( /* See header for documentation. */ Instance::Instance( - VkInstance instance, - PFN_vkGetInstanceProcAddr nlayerGetProcAddress) : - instance(instance), - nlayerGetProcAddress(nlayerGetProcAddress) + VkInstance _instance, + PFN_vkGetInstanceProcAddr _nlayerGetProcAddress) : + instance(_instance), + nlayerGetProcAddress(_nlayerGetProcAddress) { initDriverInstanceDispatchTable(instance, nlayerGetProcAddress, driver); } diff --git a/source_common/CMakeLists.txt b/source_common/CMakeLists.txt index 1f37093..a408717 100644 --- a/source_common/CMakeLists.txt +++ b/source_common/CMakeLists.txt @@ -26,3 +26,4 @@ # Device classes which get specialized for each use case. add_subdirectory(comms) +add_subdirectory(trackers) From baa30017c138361b9cc24f36a0d175afdbe68909 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:09:52 +0000 Subject: [PATCH 4/9] Drop trackers for now --- source_common/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/source_common/CMakeLists.txt b/source_common/CMakeLists.txt index a408717..1f37093 100644 --- a/source_common/CMakeLists.txt +++ b/source_common/CMakeLists.txt @@ -26,4 +26,3 @@ # Device classes which get specialized for each use case. add_subdirectory(comms) -add_subdirectory(trackers) From ca32911c79243a810033c288f9bff075721ac3ac Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:13:15 +0000 Subject: [PATCH 5/9] Update generated code --- layer_example/source/device.cpp | 12 ++++++------ layer_example/source/instance.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/layer_example/source/device.cpp b/layer_example/source/device.cpp index 82371c7..580e339 100644 --- a/layer_example/source/device.cpp +++ b/layer_example/source/device.cpp @@ -81,13 +81,13 @@ void Device::destroy( /* See header for documentation. */ Device::Device( - Instance* instance, - VkPhysicalDevice physicalDevice, - VkDevice device, + Instance* _instance, + VkPhysicalDevice _physicalDevice, + VkDevice _device, PFN_vkGetDeviceProcAddr nlayerGetProcAddress -): instance(instance), - physicalDevice(physicalDevice), - device(device) +): instance(_instance), + physicalDevice(_physicalDevice), + device(_device) { initDriverDeviceDispatchTable(device, nlayerGetProcAddress, driver); } diff --git a/layer_example/source/instance.cpp b/layer_example/source/instance.cpp index af4936f..6ac278e 100644 --- a/layer_example/source/instance.cpp +++ b/layer_example/source/instance.cpp @@ -67,10 +67,10 @@ void Instance::destroy( /* See header for documentation. */ Instance::Instance( - VkInstance instance, - PFN_vkGetInstanceProcAddr nlayerGetProcAddress) : - instance(instance), - nlayerGetProcAddress(nlayerGetProcAddress) + VkInstance _instance, + PFN_vkGetInstanceProcAddr _nlayerGetProcAddress) : + instance(_instance), + nlayerGetProcAddress(_nlayerGetProcAddress) { initDriverInstanceDispatchTable(instance, nlayerGetProcAddress, driver); } From 955804112f098a65510da4a9e76583903710f3e0 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:18:53 +0000 Subject: [PATCH 6/9] Add lock extern declaration --- generator/vk_common/entry_utils.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/generator/vk_common/entry_utils.hpp b/generator/vk_common/entry_utils.hpp index 2f9872a..b7fd6e3 100644 --- a/generator/vk_common/entry_utils.hpp +++ b/generator/vk_common/entry_utils.hpp @@ -43,6 +43,7 @@ #include "device_dispatch_table.hpp" #include "device_functions.hpp" +extern std::mutex g_vulkanLock; #define VK_LAYER_EXPORT __attribute__((visibility("default"))) From 45775c1cc37ac176dcad3d07ec5238f18b8392ac Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:21:54 +0000 Subject: [PATCH 7/9] Add lock extern declaration --- source_common/framework/entry_utils.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/source_common/framework/entry_utils.hpp b/source_common/framework/entry_utils.hpp index 2f9872a..b7fd6e3 100644 --- a/source_common/framework/entry_utils.hpp +++ b/source_common/framework/entry_utils.hpp @@ -43,6 +43,7 @@ #include "device_dispatch_table.hpp" #include "device_functions.hpp" +extern std::mutex g_vulkanLock; #define VK_LAYER_EXPORT __attribute__((visibility("default"))) From 249e967b2b2778b41fdece0717c5ca65f7d7604b Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:24:25 +0000 Subject: [PATCH 8/9] Make GHA test builds regen common code --- .github/workflows/build_test.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build_test.yaml b/.github/workflows/build_test.yaml index 3299fdb..245cf5e 100644 --- a/.github/workflows/build_test.yaml +++ b/.github/workflows/build_test.yaml @@ -82,6 +82,10 @@ jobs: - name: Generate layer_test run: | python3 ./generator/generate_vulkan_common.py + mkdir layer_example/build_rel + cd layer_example/build_rel + cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .. + make -j4 build-ubuntu-x64-clang-new-project: name: Ubuntu x64 generate new layer @@ -94,6 +98,7 @@ jobs: - name: Generate layer_test run: | + python3 ./generator/generate_vulkan_common.py python3 ./generator/generate_vulkan_layer.py --project-name Test --layer-name VkLayerTest --output layer_test mkdir layer_test/build_rel cd layer_test/build_rel From 4daa6e2bbcec7545c5f9a2466dd78fc516533916 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Mon, 2 Dec 2024 14:36:04 +0000 Subject: [PATCH 9/9] Fix typos --- generator/vk_layer/source/device.hpp | 4 ++-- generator/vk_layer/source/instance.hpp | 4 ++-- layer_example/source/device.hpp | 4 ++-- layer_example/source/instance.hpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/generator/vk_layer/source/device.hpp b/generator/vk_layer/source/device.hpp index 26adc01..d6ecad7 100644 --- a/generator/vk_layer/source/device.hpp +++ b/generator/vk_layer/source/device.hpp @@ -25,7 +25,7 @@ /** * @file - * Declares the root class for layer management of managing VkDevice objects. + * Declares the root class for layer management of VkDevice objects. * * Role summary * ============ @@ -70,7 +70,7 @@ class Device * @brief Store a new device into the global store of dispatchable devices. * * @param handle The dispatchable device handle to use as an indirect key. - * @param device The \c Device object to store. + * @param device The @c Device object to store. */ static void store( VkDevice handle, diff --git a/generator/vk_layer/source/instance.hpp b/generator/vk_layer/source/instance.hpp index 8319722..cfda54e 100644 --- a/generator/vk_layer/source/instance.hpp +++ b/generator/vk_layer/source/instance.hpp @@ -25,7 +25,7 @@ /** * @file - * Declares the root class for layer management of managing VkInstance objects. + * Declares the root class for layer management of VkInstance objects. * * Role summary * ============ @@ -77,7 +77,7 @@ class Instance * @brief Store a new instance into the global store of dispatchable instances. * * @param handle The dispatchable instance handle to use as an indirect key. - * @param instance The \c Instance object to store. + * @param instance The @c Instance object to store. */ static void store( VkInstance handle, diff --git a/layer_example/source/device.hpp b/layer_example/source/device.hpp index 26adc01..d6ecad7 100644 --- a/layer_example/source/device.hpp +++ b/layer_example/source/device.hpp @@ -25,7 +25,7 @@ /** * @file - * Declares the root class for layer management of managing VkDevice objects. + * Declares the root class for layer management of VkDevice objects. * * Role summary * ============ @@ -70,7 +70,7 @@ class Device * @brief Store a new device into the global store of dispatchable devices. * * @param handle The dispatchable device handle to use as an indirect key. - * @param device The \c Device object to store. + * @param device The @c Device object to store. */ static void store( VkDevice handle, diff --git a/layer_example/source/instance.hpp b/layer_example/source/instance.hpp index 8319722..cfda54e 100644 --- a/layer_example/source/instance.hpp +++ b/layer_example/source/instance.hpp @@ -25,7 +25,7 @@ /** * @file - * Declares the root class for layer management of managing VkInstance objects. + * Declares the root class for layer management of VkInstance objects. * * Role summary * ============ @@ -77,7 +77,7 @@ class Instance * @brief Store a new instance into the global store of dispatchable instances. * * @param handle The dispatchable instance handle to use as an indirect key. - * @param instance The \c Instance object to store. + * @param instance The @c Instance object to store. */ static void store( VkInstance handle,