if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(loader_common_options INTERFACE -Wno-stringop-truncation -Wno-stringop-overflow)
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.1)
+ target_compile_options(loader_common_options INTERFACE -Wshadow=local) #only added in GCC 7
+ endif()
endif()
if(UNIX)
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
-# Application Interface to Loader
+# Application Interface to Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
-<!-- Copyright © 2015-2022 LunarG, Inc. -->
+<!-- Copyright © 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
-## Table of Contents
+## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Interfacing with Vulkan Functions](#interfacing-with-vulkan-functions)
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
-# Debugging The Vulkan Desktop Loader
+# Debugging The Vulkan Desktop Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
-<!-- Copyright © 2015-2022 LunarG, Inc. -->
+<!-- Copyright © 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
-## Table of Contents
+## Table of Contents <!-- omit from toc -->
- [Debugging Issues](#debugging-issues)
- [Loader Logging](#loader-logging)
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
-# Driver interface to the Vulkan Loader
+# Driver interface to the Vulkan Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
-<!-- Copyright © 2015-2022 LunarG, Inc. -->
+<!-- Copyright © 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
-## Table of Contents
+## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Driver Discovery](#driver-discovery)
- [Driver Discovery on macOS](#driver-discovery-on-macos)
- [Example macOS Driver Search Path](#example-macos-driver-search-path)
- [Additional Settings For Driver Debugging](#additional-settings-for-driver-debugging)
+ - [Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension](#driver-discovery-using-thevk_lunarg_direct_driver_loading-extension)
+ - [How to use `VK_LUNARG_direct_driver_loading`](#how-to-use-vk_lunarg_direct_driver_loading)
+ - [Interactions with other driver discovery mechanisms](#interactions-with-other-driver-discovery-mechanisms)
+ - [Limitations of `VK_LUNARG_direct_driver_loading`](#limitations-of-vk_lunarg_direct_driver_loading)
- [Using Pre-Production ICDs or Software Drivers](#using-pre-production-icds-or-software-drivers)
- [Driver Discovery on Android](#driver-discovery-on-android)
- [Driver Manifest File Format](#driver-manifest-file-format)
It is recommended that `LD_BIND_NOW` along with `VK_LOADER_DEBUG=error,warn`
to expose any issues.
+### Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension
+
+The `VK_LUNARG_direct_driver_loading` extension allows for applications to
+provide a driver or drivers to the Loader during vkCreateInstance.
+This allows drivers to be included with an application without requiring
+installation and is capable of being used in any execution environment, such as
+a process running with elevated privileges.
+
+When calling `vkEnumeratePhysicalDevices` with the
+`VK_LUNARG_direct_driver_loading` extension enabled, the `VkPhysicalDevice`s
+from system installed drivers and environment variable specified drivers will
+appear before any `VkPhysicalDevice`s that originate from drivers from the
+`VkDirectDriverLoadingListLUNARG::pDrivers` list.
+
+#### How to use `VK_LUNARG_direct_driver_loading`
+
+To use this extension, it must first be enabled on the VkInstance.
+This requires enabling the `VK_LUNARG_direct_driver_loading` extension through
+the `enabledExtensionCount` and `ppEnabledExtensionNames`members of
+`VkInstanceCreateInfo`.
+
+```c
+const char* extensions[] = {VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME, <other extensions>};
+VkInstanceCreateInfo instance_create_info = {};
+instance_create_info.enabledExtensionCount = <size of extension list>;
+instance_create_info.ppEnabledExtensionNames = extensions;
+```
+
+The `VkDirectDriverLoadingInfoLUNARG` structure contains a
+`VkDirectDriverLoadingFlagsLUNARG` member (reserved for future use) and a
+`PFN_vkGetInstanceProcAddrLUNARG` member which provides the loader with the
+function pointer for the driver's `vkGetInstanceProcAddr`.
+
+The `VkDirectDriverLoadingListLUNARG` structure contains a count and pointer
+members which provide the size of and pointer to an application provided array of
+`VkDirectDriverLoadingInfoLUNARG` structures.
+
+Creating those structures looks like the following
+```c
+VkDirectDriverLoadingInfoLUNARG direct_loading_info = {};
+direct_loading_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG
+direct_loading_info.pfnGetInstanceProcAddr = <put the PFN_vkGetInstanceProcAddr of the driver here>
+
+VkDirectDriverLoadingListLUNARG direct_driver_list = {};
+direct_driver_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+direct_driver_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG; // or VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG
+direct_driver_list.driverCount = 1;
+direct_driver_list.pDrivers = &direct_loading_info; // can include multiple drivers here if so desired
+```
+
+The `VkDirectDriverLoadingListLUNARG` structure contains the enum
+`VkDirectDriverLoadingModeLUNARG`.
+There are two modes:
+* `VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG` - specifies that the only drivers
+to be loaded will come from the `VkDirectDriverLoadingListLUNARG` structure.
+* `VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG` - specifies that drivers
+from the `VkDirectDriverLoadingModeLUNARG` structure will be used in addition to
+any system installed drivers and environment variable specified drivers.
+
+
+
+Then, the `VkDirectDriverLoadingListLUNARG` structure *must* be appended to the
+`pNext` chain of `VkInstanceCreateInfo`.
+
+```c
+instance_create_info.pNext = (const void*)&direct_driver_list;
+```
+
+Finally, create the instance like normal.
+
+#### Interactions with other driver discovery mechanisms
+
+If the `VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG` mode is specified in the
+`VkDirectDriverLoadingListLUNARG` structure, then no system installed drivers
+are loaded.
+This applies equally to all platforms.
+Additionally, the following environment variables have no effect:
+
+* `VK_DRIVER_FILES`
+* `VK_ICD_FILENAMES`
+* `VK_ADD_DRIVER_FILES`
+* `VK_LOADER_DRIVERS_SELECT`
+* `VK_LOADER_DRIVERS_DISABLE`
+
+Exclusive mode will also disable MacOS bundle manifest discovery of drivers.
+
+#### Limitations of `VK_LUNARG_direct_driver_loading`
+
+Because `VkDirectDriverLoadingListLUNARG` is provided to the loader at instance
+creation, there is no mechanism for the loader to query the list of instance
+extensions that originate from `VkDirectDriverLoadingListLUNARG` drivers during
+`vkEnumerateInstanceExtensionProperties`.
+Applications can instead manually load the `vkEnumerateInstanceExtensionProperties`
+function pointer directly from the drivers the application provides to the loader
+using the `pfnGetInstanceProcAddrLUNARG` for each driver.
+Then the application can call each driver's
+`vkEnumerateInstanceExtensionProperties` and append non-duplicate entriees to the
+list from the loader's `vkEnumerateInstanceExtensionProperties` to get the full
+list of supported instance extensions.
+Alternatively, because the Application is providing drivers, it is reasonable for
+the application to already know which instance extensions are available with the
+provided drivers, preventing the need to manually query them.
+
+However, there are limitations.
+If there are any active implicit layers which intercept
+`vkEnumerateInstanceExtensionProperties` to remove unsupported extensions, then
+those layers will not be able to remove unsupported extensions from drivers that
+are provided by the application.
+This is due to `vkEnumerateInstanceExtensionProperties` not having a mechanism
+to extend it.
+
### Using Pre-Production ICDs or Software Drivers
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
-# Architecture of the Vulkan Loader Interfaces
+# Architecture of the Vulkan Loader Interfaces <!-- omit from toc -->
[![Creative Commons][3]][4]
-<!-- Copyright © 2015-2022 LunarG, Inc. -->
+<!-- Copyright © 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
-## Table of Contents
+## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Who Should Read This Document](#who-should-read-this-document)
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
-# Layer Interface to the Loader
+# Layer Interface to the Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
-<!-- Copyright © 2015-2022 LunarG, Inc. -->
+<!-- Copyright © 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
-## Table of Contents
+## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Layer Discovery](#layer-discovery)
- [Layer Disable Filtering](#layer-disable-filtering)
- [Layer Special Case Disable](#layer-special-case-disable)
- [Layer Disable Warning](#layer-disable-warning)
+ - [`VK_INSTANCE_LAYERS`](#vk_instance_layers)
- [Exception for Elevated Privileges](#exception-for-elevated-privileges)
- [Layer Version Negotiation](#layer-version-negotiation)
- [Layer Call Chains and Distributed Dispatch](#layer-call-chains-and-distributed-dispatch)
- [Versioning and Activation Interactions](#versioning-and-activation-interactions)
- [Layer Manifest File Format](#layer-manifest-file-format)
- [Layer Manifest File Version History](#layer-manifest-file-version-history)
+ - [Layer Manifest File Version 1.2.1](#layer-manifest-file-version-121)
- [Layer Manifest File Version 1.2.0](#layer-manifest-file-version-120)
- [Layer Manifest File Version 1.1.2](#layer-manifest-file-version-112)
- [Layer Manifest File Version 1.1.1](#layer-manifest-file-version-111)
`~all~` or `~explicit~` could cause application breakage if the application is
relying on features provided by one or more explicit layers.
-##### VK_INSTANCE_LAYERS
+##### `VK_INSTANCE_LAYERS`
The original `VK_INSTANCE_LAYERS` can be viewed as a special case of the new
`VK_LOADER_LAYERS_ENABLE`.
/*
*
- * Copyright (c) 2014-2022 The Khronos Group Inc.
- * Copyright (c) 2014-2022 Valve Corporation
- * Copyright (c) 2014-2022 LunarG, Inc.
+ * Copyright (c) 2014-2023 The Khronos Group Inc.
+ * Copyright (c) 2014-2023 Valve Corporation
+ * Copyright (c) 2014-2023 LunarG, Inc.
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
loader_add_to_ext_list(inst, inst_exts, sizeof(portability_enumeration_extension_info) / sizeof(VkExtensionProperties),
portability_enumeration_extension_info);
+ static const VkExtensionProperties direct_driver_loading_extension_info[] = {
+ {VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME, VK_LUNARG_DIRECT_DRIVER_LOADING_SPEC_VERSION}};
+
+ // Add VK_LUNARG_direct_driver_loading
+ loader_add_to_ext_list(inst, inst_exts, sizeof(direct_driver_loading_extension_info) / sizeof(VkExtensionProperties),
+ direct_driver_loading_extension_info);
out:
return res;
}
void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
if (0 != icd_tramp_list->capacity) {
for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
- loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
+ if (icd_tramp_list->scanned_list[i].handle) {
+ loader_platform_close_library(icd_tramp_list->scanned_list[i].handle);
+ icd_tramp_list->scanned_list[i].handle = NULL;
+ }
loader_instance_heap_free(inst, icd_tramp_list->scanned_list[i].lib_name);
}
loader_instance_heap_free(inst, icd_tramp_list->scanned_list);
- icd_tramp_list->capacity = 0;
- icd_tramp_list->count = 0;
- icd_tramp_list->scanned_list = NULL;
}
+ icd_tramp_list->capacity = 0;
+ icd_tramp_list->count = 0;
+ icd_tramp_list->scanned_list = NULL;
}
-static VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
- VkResult err = VK_SUCCESS;
+VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list) {
+ VkResult res = VK_SUCCESS;
loader_scanned_icd_clear(inst, icd_tramp_list);
icd_tramp_list->capacity = 8 * sizeof(struct loader_scanned_icd);
icd_tramp_list->scanned_list = loader_instance_heap_alloc(inst, icd_tramp_list->capacity, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == icd_tramp_list->scanned_list) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"loader_scanned_icd_init: Realloc failed for layer list when attempting to add new layer");
- err = VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
}
- return err;
+ return res;
+}
+
+VkResult loader_add_direct_driver(const struct loader_instance *inst, uint32_t index,
+ const VkDirectDriverLoadingInfoLUNARG *pDriver, struct loader_icd_tramp_list *icd_tramp_list) {
+ // Assume pDriver is valid, since there is no real way to check it. Calling code should make sure the pointer to the array of
+ // VkDirectDriverLoadingInfoLUNARG structures is non-null.
+ if (NULL == pDriver->pfnGetInstanceProcAddr) {
+ loader_log(
+ inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index %d contains a NULL pointer for the "
+ "pfnGetInstanceProcAddr member, skipping.",
+ index);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ PFN_vkGetInstanceProcAddr fp_get_proc_addr = pDriver->pfnGetInstanceProcAddr;
+ PFN_vkCreateInstance fp_create_inst = NULL;
+ PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props = NULL;
+ PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL;
+ PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version = NULL;
+#if defined(VK_USE_PLATFORM_WIN32_KHR)
+ PFN_vk_icdEnumerateAdapterPhysicalDevices fp_enum_dxgi_adapter_phys_devs = NULL;
+#endif
+ struct loader_scanned_icd *new_scanned_icd;
+ uint32_t interface_version = 0;
+
+ // Try to get the negotiate ICD interface version function
+ fp_negotiate_icd_version = (PFN_vk_icdNegotiateLoaderICDInterfaceVersion)pDriver->pfnGetInstanceProcAddr(
+ NULL, "vk_icdNegotiateLoaderICDInterfaceVersion");
+
+ if (NULL == fp_negotiate_icd_version) {
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: Could not get 'vk_icdNegotiateLoaderICDInterfaceVersion' from "
+ "VkDirectDriverLoadingInfoLUNARG structure at "
+ "index %d, skipping.",
+ index);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (!loader_get_icd_interface_version(fp_negotiate_icd_version, &interface_version)) {
+ loader_log(
+ inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index %d supports interface version %d, "
+ "which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading "
+ "extension, skipping.",
+ index, interface_version);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (interface_version < 7) {
+ loader_log(
+ inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index %d supports interface version %d, "
+ "which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading "
+ "extension, skipping.",
+ index, interface_version);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ fp_create_inst = (PFN_vkCreateInstance)pDriver->pfnGetInstanceProcAddr(NULL, "vkCreateInstance");
+ if (NULL == fp_create_inst) {
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: Could not get 'vkCreateInstance' from VkDirectDriverLoadingInfoLUNARG structure at "
+ "index %d, skipping.",
+ index);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ fp_get_inst_ext_props =
+ (PFN_vkEnumerateInstanceExtensionProperties)pDriver->pfnGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
+ if (NULL == fp_get_inst_ext_props) {
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
+ "VkDirectDriverLoadingInfoLUNARG structure at index %d, skipping.",
+ index);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ fp_get_phys_dev_proc_addr =
+ (PFN_vk_icdGetPhysicalDeviceProcAddr)pDriver->pfnGetInstanceProcAddr(NULL, "vk_icdGetPhysicalDeviceProcAddr");
+#if defined(VK_USE_PLATFORM_WIN32_KHR)
+ // Query "vk_icdEnumerateAdapterPhysicalDevices" with vk_icdGetInstanceProcAddr if the library reports interface version
+ // 7 or greater, otherwise fallback to loading it from the platform dynamic linker
+ fp_enum_dxgi_adapter_phys_devs =
+ (PFN_vk_icdEnumerateAdapterPhysicalDevices)pDriver->pfnGetInstanceProcAddr(NULL, "vk_icdEnumerateAdapterPhysicalDevices");
+#endif
+
+ // check for enough capacity
+ if ((icd_tramp_list->count * sizeof(struct loader_scanned_icd)) >= icd_tramp_list->capacity) {
+ void *new_ptr = loader_instance_heap_realloc(inst, icd_tramp_list->scanned_list, icd_tramp_list->capacity,
+ icd_tramp_list->capacity * 2, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL == new_ptr) {
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_add_direct_driver: Realloc failed on icd library list for ICD %s");
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ icd_tramp_list->scanned_list = new_ptr;
+
+ // double capacity
+ icd_tramp_list->capacity *= 2;
+ }
+
+ // Driver must be 1.1 to support version 7
+ uint32_t api_version = VK_API_VERSION_1_1;
+ PFN_vkEnumerateInstanceVersion icd_enumerate_instance_version =
+ (PFN_vkEnumerateInstanceVersion)pDriver->pfnGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
+
+ if (icd_enumerate_instance_version) {
+ VkResult res = icd_enumerate_instance_version(&api_version);
+ if (res != VK_SUCCESS) {
+ return res;
+ }
+ }
+
+ new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
+ new_scanned_icd->handle = NULL;
+ new_scanned_icd->api_version = api_version;
+ new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr;
+ new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr;
+ new_scanned_icd->EnumerateInstanceExtensionProperties = fp_get_inst_ext_props;
+ new_scanned_icd->CreateInstance = fp_create_inst;
+#if defined(VK_USE_PLATFORM_WIN32_KHR)
+ new_scanned_icd->EnumerateAdapterPhysicalDevices = fp_enum_dxgi_adapter_phys_devs;
+#endif
+ new_scanned_icd->interface_version = interface_version;
+
+ new_scanned_icd->lib_name = NULL;
+ icd_tramp_list->count++;
+
+ loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_add_direct_driver: Adding driver found in index %d of "
+ "VkDirectDriverLoadingListLUNARG::pDrivers structure. pfnGetInstanceProcAddr was set to %p",
+ index, pDriver->pfnGetInstanceProcAddr);
+
+ return VK_SUCCESS;
+}
+
+// Search through VkInstanceCreateInfo's pNext chain for any drivers from the direct driver loading extension and load them.
+VkResult loader_scan_for_direct_drivers(const struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
+ struct loader_icd_tramp_list *icd_tramp_list, bool *direct_driver_loading_exclusive_mode) {
+ if (NULL == pCreateInfo) {
+ // Don't do this logic unless we are being called from vkCreateInstance, when pCreateInfo will be non-null
+ return VK_SUCCESS;
+ }
+ bool direct_driver_loading_enabled = false;
+ // Try to if VK_LUNARG_direct_driver_loading is enabled and if we are using it exclusively
+ // Skip this step if inst is NULL, aka when this function is being called before instance creation
+ if (inst != NULL && pCreateInfo->ppEnabledExtensionNames && pCreateInfo->enabledExtensionCount > 0) {
+ // Look through the enabled extension list, make sure VK_LUNARG_direct_driver_loading is present
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME) == 0) {
+ direct_driver_loading_enabled = true;
+ break;
+ }
+ }
+ }
+ const VkDirectDriverLoadingListLUNARG *ddl_list = NULL;
+ // Find the VkDirectDriverLoadingListLUNARG struct in the pNext chain of vkInstanceCreateInfo
+ const VkBaseOutStructure *chain = pCreateInfo->pNext;
+ while (chain) {
+ if (chain->sType == VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG) {
+ ddl_list = (VkDirectDriverLoadingListLUNARG *)chain;
+ break;
+ }
+ chain = (const VkBaseOutStructure *)chain->pNext;
+ }
+ if (NULL == ddl_list) {
+ if (direct_driver_loading_enabled) {
+ loader_log(
+ inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the pNext chain of "
+ "VkInstanceCreateInfo did not contain the "
+ "VkDirectDriverLoadingListLUNARG structure.");
+ }
+ // Always want to exit early if there was no VkDirectDriverLoadingListLUNARG in the pNext chain
+ return VK_SUCCESS;
+ }
+
+ if (!direct_driver_loading_enabled) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the "
+ "VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was "
+ "not enabled.");
+ return VK_SUCCESS;
+ }
+ // If we are using exclusive mode, skip looking for any more drivers from system or environment variables
+ if (ddl_list->mode == VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG) {
+ *direct_driver_loading_exclusive_mode = true;
+ loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified "
+ "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment "
+ "variable driver search mechanisms.");
+ }
+ if (NULL == ddl_list->pDrivers) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
+ "VkInstanceCreateInfo has a NULL pDrivers member.");
+ return VK_SUCCESS;
+ }
+ if (ddl_list->driverCount == 0) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
+ "VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value "
+ "of zero.");
+ return VK_SUCCESS;
+ }
+ // Go through all VkDirectDriverLoadingInfoLUNARG entries and add each driver
+ // Because icd_tramp's are prepended, this will result in the drivers appearing at the end
+ for (uint32_t i = 0; i < ddl_list->driverCount; i++) {
+ VkResult res = loader_add_direct_driver(inst, i, &ddl_list->pDrivers[i], icd_tramp_list);
+ if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
+ return res;
+ }
+ }
+
+ return VK_SUCCESS;
}
static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
return;
}
- memset(&scanned_icds, 0, sizeof(scanned_icds));
- VkResult result = loader_icd_scan(NULL, &scanned_icds, NULL);
+ VkResult result = loader_icd_scan(NULL, &scanned_icds, NULL, NULL);
if (result != VK_SUCCESS) {
loader_scanned_icd_clear(NULL, &scanned_icds);
}
// Vulkan result
// (on result == VK_SUCCESS) a list of icds that were discovered
VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
- bool *skipped_portability_drivers) {
+ const VkInstanceCreateInfo *pCreateInfo, bool *skipped_portability_drivers) {
struct loader_data_files manifest_files;
VkResult res = VK_SUCCESS;
bool lockedMutex = false;
// a failure occurs before allocating the manifest filename_list.
memset(&manifest_files, 0, sizeof(struct loader_data_files));
+ // Set up the ICD Trampoline list so elements can be written into it.
+ res = loader_scanned_icd_init(inst, icd_tramp_list);
+ if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
+ return res;
+ }
+
+ bool direct_driver_loading_exclusive_mode = false;
+ res = loader_scan_for_direct_drivers(inst, pCreateInfo, icd_tramp_list, &direct_driver_loading_exclusive_mode);
+ if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
+ goto out;
+ }
+ if (direct_driver_loading_exclusive_mode) {
+ // Make sure to jump over the system & env-var driver discovery mechanisms if exclusive mode is set, even if no drivers
+ // were successfully found through the direct driver loading mechanism
+ goto out;
+ }
+
// Parse the filter environment variables to determine if we have any special behavior
res = parse_generic_filter_environment_var(inst, VK_DRIVERS_SELECT_ENV_VAR, &select_filter);
if (VK_SUCCESS != res) {
goto out;
}
- res = loader_scanned_icd_init(inst, icd_tramp_list);
- if (VK_SUCCESS != res) {
- goto out;
- }
-
// Get a list of manifest files for ICDs
res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
- if (VK_SUCCESS != res || manifest_files.count == 0) {
+ if (VK_SUCCESS != res) {
goto out;
}
return (PFN_vkVoidFunction)terminator_CreateDevice;
}
- // The VK_EXT_debug_utils functions need a special case here so the terminators can still be found from vkGetInstanceProcAddr
- // This is because VK_EXT_debug_utils is an instance level extension with device level functions, and is 'supported' by the
- // loader. There needs to be a terminator in case a driver doesn't support VK_EXT_debug_utils.
+ // The VK_EXT_debug_utils functions need a special case here so the terminators can still be found from
+ // vkGetInstanceProcAddr This is because VK_EXT_debug_utils is an instance level extension with device level functions, and
+ // is 'supported' by the loader. There needs to be a terminator in case a driver doesn't support VK_EXT_debug_utils.
if (!strcmp(pName, "vkSetDebugUtilsObjectNameEXT")) {
return (PFN_vkVoidFunction)terminator_SetDebugUtilsObjectNameEXT;
}
}
#endif // LOADER_ENABLE_LINUX_SORT
-// Look for physical_device in the provided phys_devs list, return true if found and put the index into out_idx, otherwise return
-// false
+// Look for physical_device in the provided phys_devs list, return true if found and put the index into out_idx, otherwise
+// return false
bool find_phys_dev(VkPhysicalDevice physical_device, uint32_t phys_devs_count, struct loader_physical_device_term **phys_devs,
uint32_t *out_idx) {
if (NULL == phys_devs) return false;
return VK_SUCCESS;
}
- // Exit in case something is already present - this shouldn't happen but better to be safe than overwrite existing data since
- // this code has been refactored a half dozen times.
+ // Exit in case something is already present - this shouldn't happen but better to be safe than overwrite existing data
+ // since this code has been refactored a half dozen times.
if (NULL != new_phys_devs[idx]) {
return VK_SUCCESS;
}
loader_preload_icds();
// Scan/discover all ICD libraries
- res = loader_icd_scan(NULL, &icd_tramp_list, NULL);
+ res = loader_icd_scan(NULL, &icd_tramp_list, NULL, NULL);
// EnumerateInstanceExtensionProperties can't return anything other than OOM or VK_ERROR_LAYER_NOT_PRESENT
if ((VK_SUCCESS != res && icd_tramp_list.count > 0) || res == VK_ERROR_OUT_OF_HOST_MEMORY) {
goto out;
/*
*
- * Copyright (c) 2014-2022 The Khronos Group Inc.
- * Copyright (c) 2014-2022 Valve Corporation
- * Copyright (c) 2014-2022 LunarG, Inc.
+ * Copyright (c) 2014-2023 The Khronos Group Inc.
+ * Copyright (c) 2014-2023 Valve Corporation
+ * Copyright (c) 2014-2023 LunarG, Inc.
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
void loader_destroy_layer_list(const struct loader_instance *inst, struct loader_device *device,
struct loader_layer_list *layer_list);
void loader_delete_layer_list_and_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list);
+VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
- bool *skipped_portability_drivers);
+ const VkInstanceCreateInfo *pCreateInfo, bool *skipped_portability_drivers);
void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term,
const VkAllocationCallbacks *pAllocator);
VkResult loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
/*
*
- * Copyright (c) 2015-2022 The Khronos Group Inc.
- * Copyright (c) 2015-2022 Valve Corporation
- * Copyright (c) 2015-2022 LunarG, Inc.
+ * Copyright (c) 2015-2023 The Khronos Group Inc.
+ * Copyright (c) 2015-2023 Valve Corporation
+ * Copyright (c) 2015-2023 LunarG, Inc.
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
}
}
- // Scan/discover all ICD libraries
- memset(&ptr_instance->icd_tramp_list, 0, sizeof(ptr_instance->icd_tramp_list));
+ // Scan/discover all System and Environment Variable ICD libraries
bool skipped_portability_drivers = false;
- res = loader_icd_scan(ptr_instance, &ptr_instance->icd_tramp_list, &skipped_portability_drivers);
+ res = loader_icd_scan(ptr_instance, &ptr_instance->icd_tramp_list, pCreateInfo, &skipped_portability_drivers);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
goto out;
- } else if (ptr_instance->icd_tramp_list.count == 0) {
+ }
+
+ if (ptr_instance->icd_tramp_list.count == 0) {
// No drivers found
if (skipped_portability_drivers) {
loader_log(
loader_instance_heap_free(ptr_instance, ptr_instance);
loader_platform_thread_unlock_mutex(&loader_lock);
- // Unload preloaded layers, so if vkEnumerateInstanceExtensionProperties or vkCreateInstance is called again, the ICD's are up
- // to date
+ // Unload preloaded layers, so if vkEnumerateInstanceExtensionProperties or vkCreateInstance is called again, the ICD's are
+ // up to date
loader_unload_preloaded_icds();
}
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
- loader_log(
- NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
- "vkGetPhysicalDeviceProperties: Invalid physicalDevice [VUID-vkGetPhysicalDeviceProperties-physicalDevice-parameter]");
+ loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
+ "vkGetPhysicalDeviceProperties: Invalid physicalDevice "
+ "[VUID-vkGetPhysicalDeviceProperties-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
disp = loader_get_instance_layer_dispatch(physicalDevice);
uint32_t stride) {
const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
if (NULL == disp) {
- loader_log(
- NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
- "vkCmdDrawIndexedIndirectCount: Invalid commandBuffer [VUID-vkCmdDrawIndexedIndirectCount-commandBuffer-parameter]");
+ loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
+ "vkCmdDrawIndexedIndirectCount: Invalid commandBuffer "
+ "[VUID-vkCmdDrawIndexedIndirectCount-commandBuffer-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
disp->CmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride);
vkGetDeviceMemoryOpaqueCaptureAddress(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo *pInfo) {
const VkLayerDispatchTable *disp = loader_get_dispatch(device);
if (NULL == disp) {
- loader_log(
- NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
- "vkGetDeviceMemoryOpaqueCaptureAddress: Invalid device [VUID-vkGetDeviceMemoryOpaqueCaptureAddress-device-parameter]");
+ loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
+ "vkGetDeviceMemoryOpaqueCaptureAddress: Invalid device "
+ "[VUID-vkGetDeviceMemoryOpaqueCaptureAddress-device-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
return disp->GetDeviceMemoryOpaqueCaptureAddress(device, pInfo);
There are many utilities that the test framework and tests have access to. These include:
* Including common C and C++ headers
* `FRAMEWORK_EXPORT` - macro used for exporting shared library funtions
-* Environment Variable helpers: `get_env_var`, `set_env_var`, `remove_env_var`
+* Environment Variable Wrapper: `EnvVarWrapper` for creating, setting, getting, and removing environment variables in a RAII manner
* Windows API error handling helpers
* filesystem abstractions:
* `fs::path` - wrapper around std::string that has a similar API to C++17's `filesystem::path` library
/*
- * Copyright (c) 2021-2022 The Khronos Group Inc.
- * Copyright (c) 2021-2022 Valve Corporation
- * Copyright (c) 2021-2022 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
return VK_SUCCESS;
}
+// Forward declarations for trampolines
+extern "C" {
+#if TEST_ICD_EXPOSE_VERSION_7
+FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
+#if TEST_ICD_EXPORT_ICD_GPDPA
+FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName);
+#endif
+#if defined(WIN32) && TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
+FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
+ uint32_t* pPhysicalDeviceCount,
+ VkPhysicalDevice* pPhysicalDevices);
+#endif
+#endif
+}
+
//// trampolines
PFN_vkVoidFunction get_instance_func_ver_1_1(VkInstance instance, const char* pName) {
}
PFN_vkVoidFunction get_instance_func(VkInstance instance, const char* pName) {
- if (string_eq(pName, "vkEnumerateInstanceExtensionProperties"))
- return to_vkVoidFunction(test_vkEnumerateInstanceExtensionProperties);
- if (string_eq(pName, "vkEnumerateInstanceLayerProperties")) return to_vkVoidFunction(test_vkEnumerateInstanceLayerProperties);
- if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_vkCreateInstance);
if (string_eq(pName, "vkDestroyInstance")) return to_vkVoidFunction(test_vkDestroyInstance);
if (string_eq(pName, "vkEnumeratePhysicalDevices")) return to_vkVoidFunction(test_vkEnumeratePhysicalDevices);
}
PFN_vkVoidFunction base_get_instance_proc_addr(VkInstance instance, const char* pName) {
+ if (pName == nullptr) return nullptr;
+ if (instance == NULL) {
#if TEST_ICD_EXPOSE_VERSION_7
- if (string_eq(pName, "vk_icdNegotiateLoaderICDInterfaceVersion"))
- return to_vkVoidFunction(test_vk_icdNegotiateLoaderICDInterfaceVersion);
- if (string_eq(pName, "vk_icdGetPhysicalDeviceProcAddr")) return to_vkVoidFunction(get_physical_device_func);
-#if defined(WIN32)
- if (string_eq(pName, "vk_icdEnumerateAdapterPhysicalDevices"))
- return to_vkVoidFunction(test_vk_icdEnumerateAdapterPhysicalDevices);
+ if (string_eq(pName, "vk_icdNegotiateLoaderICDInterfaceVersion"))
+ return icd.exposes_vk_icdNegotiateLoaderICDInterfaceVersion
+ ? to_vkVoidFunction(vk_icdNegotiateLoaderICDInterfaceVersion)
+ : NULL;
+#if TEST_ICD_EXPORT_ICD_GPDPA
+ if (string_eq(pName, "vk_icdGetPhysicalDeviceProcAddr"))
+ return icd.exposes_vk_icdGetPhysicalDeviceProcAddr ? to_vkVoidFunction(vk_icdGetPhysicalDeviceProcAddr) : NULL;
+#endif
+#if defined(WIN32) && TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
+ if (string_eq(pName, "vk_icdEnumerateAdapterPhysicalDevices"))
+ return icd.exposes_vk_icdEnumerateAdapterPhysicalDevices ? to_vkVoidFunction(vk_icdEnumerateAdapterPhysicalDevices)
+ : NULL;
#endif // defined(WIN32)
#endif // TEST_ICD_EXPOSE_VERSION_7
- if (pName == nullptr) return nullptr;
- if (instance == NULL) {
if (string_eq(pName, "vkGetInstanceProcAddr")) return to_vkVoidFunction(test_vkGetInstanceProcAddr);
if (string_eq(pName, "vkEnumerateInstanceExtensionProperties"))
- return to_vkVoidFunction(test_vkEnumerateInstanceExtensionProperties);
+ return icd.exposes_vkEnumerateInstanceExtensionProperties
+ ? to_vkVoidFunction(test_vkEnumerateInstanceExtensionProperties)
+ : NULL;
if (string_eq(pName, "vkEnumerateInstanceLayerProperties"))
return to_vkVoidFunction(test_vkEnumerateInstanceLayerProperties);
if (string_eq(pName, "vkEnumerateInstanceVersion")) return to_vkVoidFunction(test_vkEnumerateInstanceVersion);
+ if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_vkCreateInstance);
}
if (string_eq(pName, "vkGetDeviceProcAddr")) return to_vkVoidFunction(test_vkGetDeviceProcAddr);
// Exported functions
extern "C" {
#if TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION
-extern FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
+FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
return test_vk_icdNegotiateLoaderICDInterfaceVersion(pSupportedVersion);
}
#endif // TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION
/*
- * Copyright (c) 2021-2022 The Khronos Group Inc.
- * Copyright (c) 2021-2022 Valve Corporation
- * Copyright (c) 2021-2022 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
struct TestICD {
fs::path manifest_file_path;
+ BUILDER_VALUE(TestICD, bool, exposes_vk_icdNegotiateLoaderICDInterfaceVersion, true)
+ BUILDER_VALUE(TestICD, bool, exposes_vkEnumerateInstanceExtensionProperties, true)
+ BUILDER_VALUE(TestICD, bool, exposes_vkCreateInstance, true)
+ BUILDER_VALUE(TestICD, bool, exposes_vk_icdGetPhysicalDeviceProcAddr, true)
+#if defined(WIN32)
+ BUILDER_VALUE(TestICD, bool, exposes_vk_icdEnumerateAdapterPhysicalDevices, true)
+#endif
+
CalledICDGIPA called_vk_icd_gipa = CalledICDGIPA::not_called;
CalledNegotiateInterface called_negotiate_interface = CalledNegotiateInterface::not_called;
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
return env_log.find_prefix_then_postfix(prefix, postfix);
}
-PlatformShimWrapper::PlatformShimWrapper(std::vector<fs::FolderManager>* folders, bool enable_log) noexcept {
+PlatformShimWrapper::PlatformShimWrapper(std::vector<fs::FolderManager>* folders, bool enable_log) noexcept
+ : loader_logging{"VK_LOADER_DEBUG"} {
#if defined(WIN32) || defined(__APPLE__)
shim_library = LibraryWrapper(SHIM_LIBRARY_NAME);
PFN_get_platform_shim get_platform_shim_func = shim_library.get_symbol(GET_PLATFORM_SHIM_STR);
platform_shim->reset();
if (enable_log) {
- set_env_var("VK_LOADER_DEBUG", "all");
+ loader_logging.set_new_value("all");
}
}
FrameworkEnvironment::FrameworkEnvironment() noexcept : FrameworkEnvironment(true, true) {}
FrameworkEnvironment::FrameworkEnvironment(bool enable_log) noexcept : FrameworkEnvironment(enable_log, true) {}
FrameworkEnvironment::FrameworkEnvironment(bool enable_log, bool set_default_search_paths) noexcept
- : platform_shim(&folders, enable_log), vulkan_functions() {
+ : platform_shim(&folders, enable_log),
+ vulkan_functions(),
+ env_var_vk_icd_filenames("VK_DRIVER_FILES"),
+ add_env_var_vk_icd_filenames("VK_ADD_DRIVER_FILES"),
+ env_var_vk_layer_paths("VK_LAYER_PATH"),
+ add_env_var_vk_layer_paths("VK_ADD_LAYER_PATH") {
// This order is important, it matches the enum ManifestLocation, used to index the folders vector
folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("null_dir"));
folders.emplace_back(FRAMEWORK_BUILD_DIRECTORY, std::string("icd_manifests"));
#endif
}
-void FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
+TestICDHandle& FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
size_t cur_icd_index = icds.size();
fs::FolderManager* folder = &get_folder(ManifestLocation::driver);
if (icd_details.discovery_type == ManifestDiscoveryType::env_var ||
if (icd_details.discovery_type == ManifestDiscoveryType::macos_bundle) {
folder = &get_folder(ManifestLocation::macos_bundle);
}
+ if (icd_details.discovery_type == ManifestDiscoveryType::null_dir ||
+ icd_details.discovery_type == ManifestDiscoveryType::none) {
+ folder = &get_folder(ManifestLocation::null);
+ }
if (!icd_details.is_fake) {
fs::path new_driver_name = fs::path(icd_details.icd_manifest.lib_path).stem() + "_" + std::to_string(cur_icd_index) +
fs::path(icd_details.icd_manifest.lib_path).extension();
icds.back().reset_icd();
icd_details.icd_manifest.lib_path = new_driver_location.str();
}
- std::string full_json_name = icd_details.json_name;
- if (!icd_details.disable_icd_inc) {
- full_json_name += "_" + std::to_string(cur_icd_index);
- }
- full_json_name += ".json";
-
- icds.back().manifest_path = folder->write_manifest(full_json_name, icd_details.icd_manifest.get_manifest_str());
- switch (icd_details.discovery_type) {
- default:
- case (ManifestDiscoveryType::generic):
- platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path);
- break;
- case (ManifestDiscoveryType::env_var):
- if (!env_var_vk_icd_filenames.empty()) {
- env_var_vk_icd_filenames += OS_ENV_VAR_LIST_SEPARATOR;
- }
- env_var_vk_icd_filenames += (folder->location() / full_json_name).str();
- set_env_var("VK_DRIVER_FILES", env_var_vk_icd_filenames);
- break;
- case (ManifestDiscoveryType::add_env_var):
- if (!add_env_var_vk_icd_filenames.empty()) {
- add_env_var_vk_icd_filenames += OS_ENV_VAR_LIST_SEPARATOR;
- }
- add_env_var_vk_icd_filenames += (folder->location() / full_json_name).str();
- set_env_var("VK_ADD_DRIVER_FILES", add_env_var_vk_icd_filenames);
- break;
- case (ManifestDiscoveryType::macos_bundle):
- platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path);
- case (ManifestDiscoveryType::none):
- break;
+ if (icd_details.discovery_type != ManifestDiscoveryType::none) {
+ std::string full_json_name = icd_details.json_name;
+ if (!icd_details.disable_icd_inc) {
+ full_json_name += "_" + std::to_string(cur_icd_index);
+ }
+ full_json_name += ".json";
+ icds.back().manifest_path = folder->write_manifest(full_json_name, icd_details.icd_manifest.get_manifest_str());
+ switch (icd_details.discovery_type) {
+ default:
+ case (ManifestDiscoveryType::generic):
+ platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path);
+ break;
+ case (ManifestDiscoveryType::env_var):
+ env_var_vk_icd_filenames.add_to_list((folder->location() / full_json_name).str());
+ break;
+ case (ManifestDiscoveryType::add_env_var):
+ add_env_var_vk_icd_filenames.add_to_list((folder->location() / full_json_name).str());
+ break;
+ case (ManifestDiscoveryType::macos_bundle):
+ platform_shim->add_manifest(ManifestCategory::icd, icds.back().manifest_path);
+ case (ManifestDiscoveryType::null_dir):
+ break;
#ifdef _WIN32
- case (ManifestDiscoveryType::windows_app_package):
- platform_shim->set_app_package_path(folder->location());
- break;
+ case (ManifestDiscoveryType::windows_app_package):
+ platform_shim->set_app_package_path(folder->location());
+ break;
#endif
+ }
}
+ return icds.back();
}
void FrameworkEnvironment::add_implicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept {
break;
case (ManifestDiscoveryType::env_var):
fs_ptr = &get_folder(ManifestLocation::explicit_layer_env_var);
- if (!env_var_vk_layer_paths.empty()) {
- env_var_vk_layer_paths += OS_ENV_VAR_LIST_SEPARATOR;
- }
if (layer_details.is_dir) {
- env_var_vk_layer_paths += fs_ptr->location().str();
+ env_var_vk_layer_paths.add_to_list(fs_ptr->location().str());
} else {
- env_var_vk_layer_paths += fs_ptr->location().str() + OS_ENV_VAR_LIST_SEPARATOR + layer_details.json_name;
+ env_var_vk_layer_paths.add_to_list(fs_ptr->location().str());
+ env_var_vk_layer_paths.add_to_list(layer_details.json_name);
}
- env_var_vk_layer_paths += fs_ptr->location().str();
- set_env_var("VK_LAYER_PATH", env_var_vk_layer_paths);
break;
case (ManifestDiscoveryType::add_env_var):
fs_ptr = &get_folder(ManifestLocation::explicit_layer_add_env_var);
- if (!add_env_var_vk_layer_paths.empty()) {
- add_env_var_vk_layer_paths += OS_ENV_VAR_LIST_SEPARATOR;
- }
- add_env_var_vk_layer_paths += fs_ptr->location().str();
- set_env_var("VK_ADD_LAYER_PATH", add_env_var_vk_layer_paths);
+ add_env_var_vk_layer_paths.add_to_list(fs_ptr->location().str());
break;
case (ManifestDiscoveryType::override_folder):
fs_ptr = &get_folder(ManifestLocation::override_layer);
fs_ptr = &(get_folder(ManifestLocation::macos_bundle));
break;
case (ManifestDiscoveryType::none):
+ case (ManifestDiscoveryType::null_dir):
+ fs_ptr = &(get_folder(ManifestLocation::null));
break;
}
auto& folder = *fs_ptr;
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
LibraryWrapper shim_library;
PlatformShim* platform_shim;
+ EnvVarWrapper loader_logging;
};
struct TestICDHandle {
fs::path manifest_path;
};
+// Controls whether to create a manifest and where to put it
enum class ManifestDiscoveryType {
generic, // put the manifest in the regular locations
- none, // don't add to regular locations - eg D3DKMT
+ none, // Do not write the manifest anywhere (for Direct Driver Loading)
+ null_dir, // put the manifest in the 'null_dir' which the loader does not search in (D3DKMT for instance)
env_var, // use the corresponding env-var for it
add_env_var, // use the corresponding add-env-var for it
override_folder, // add to a special folder for the override layer to use
FrameworkEnvironment(bool enable_log) noexcept;
FrameworkEnvironment(bool enable_log, bool enable_default_search_paths) noexcept;
- void add_icd(TestICDDetails icd_details) noexcept;
+ TestICDHandle& add_icd(TestICDDetails icd_details) noexcept;
void add_implicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept;
void add_implicit_layer(TestLayerDetails layer_details) noexcept;
void add_explicit_layer(ManifestLayer layer_manifest, const std::string& json_name) noexcept;
std::vector<TestICDHandle> icds;
std::vector<TestLayerHandle> layers;
- std::string env_var_vk_icd_filenames;
- std::string add_env_var_vk_icd_filenames;
+ EnvVarWrapper env_var_vk_icd_filenames; //"VK_DRIVER_FILES"
+ EnvVarWrapper add_env_var_vk_icd_filenames; //"VK_ADD_DRIVER_FILES"
- std::string env_var_vk_layer_paths;
- std::string add_env_var_vk_layer_paths;
+ EnvVarWrapper env_var_vk_layer_paths; //"VK_LAYER_PATH"
+ EnvVarWrapper add_env_var_vk_layer_paths; //"VK_ADD_LAYER_PATH"
private:
void add_layer_impl(TestLayerDetails layer_details, ManifestCategory category);
// defaults to Metal on macOS and XCB on linux if not provided
// Returns an assertion failure if the surface failed to be created
testing::AssertionResult create_surface(InstWrapper& inst, VkSurfaceKHR& out_surface, const char* api_selection = nullptr);
-
-struct EnvVarCleaner {
- std::string env_var;
- EnvVarCleaner(std::string env_var) noexcept : env_var(env_var) {}
- ~EnvVarCleaner() noexcept { remove_env_var(env_var); }
-
- // delete copy operators
- EnvVarCleaner(const EnvVarCleaner&) = delete;
- EnvVarCleaner& operator=(const EnvVarCleaner&) = delete;
-};
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
LocalFree(lpMsgBuf);
}
-void set_env_var(std::string const& name, std::string const& value) {
- BOOL ret = SetEnvironmentVariableW(widen(name).c_str(), widen(value).c_str());
+void EnvVarWrapper::set_env_var() {
+ BOOL ret = SetEnvironmentVariableW(widen(name).c_str(), widen(cur_value).c_str());
if (ret == 0) {
print_error_message(ERROR_SETENV_FAILED, "SetEnvironmentVariableW");
}
}
-void remove_env_var(std::string const& name) { SetEnvironmentVariableW(widen(name).c_str(), nullptr); }
+void EnvVarWrapper::remove_env_var() const { SetEnvironmentVariableW(widen(name).c_str(), nullptr); }
std::string get_env_var(std::string const& name, bool report_failure) {
std::wstring name_utf16 = widen(name);
DWORD value_size = GetEnvironmentVariableW(name_utf16.c_str(), nullptr, 0);
}
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-void set_env_var(std::string const& name, std::string const& value) { setenv(name.c_str(), value.c_str(), 1); }
-void remove_env_var(std::string const& name) { unsetenv(name.c_str()); }
+void EnvVarWrapper::set_env_var() { setenv(name.c_str(), cur_value.c_str(), 1); }
+void EnvVarWrapper::remove_env_var() const { unsetenv(name.c_str()); }
std::string get_env_var(std::string const& name, bool report_failure) {
char* ret = getenv(name.c_str());
if (ret == nullptr) {
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
#endif
/*
- * Common Environment Variable operations
- * These operate on the actual environemnt, they are not shims.
- * set_env_var - sets the env-var with `name` to `value`.
- * remove_env_var - unsets the env-var `name`. Different than set_env_var(name, "");
- * get_env_var - returns a std::string of `name`. if report_failure is true, then it will log to stderr that it didn't find the
- * env-var
+ * Wrapper around Environment Variables with common operations
+ * Since Environment Variables leak between tests, there needs to be RAII code to remove them during test cleanup
+
*/
+// Wrapper to set & remove env-vars automatically
+struct EnvVarWrapper {
+ // Constructor which does NOT set the env-var
+ EnvVarWrapper(std::string const& name) noexcept : name(name) {}
+ // Constructor which DOES set the env-var
+ EnvVarWrapper(std::string const& name, std::string const& value) noexcept : name(name), cur_value(value) { set_env_var(); }
+ ~EnvVarWrapper() noexcept { remove_env_var(); }
+
+ // delete copy operators
+ EnvVarWrapper(const EnvVarWrapper&) = delete;
+ EnvVarWrapper& operator=(const EnvVarWrapper&) = delete;
+
+ void set_new_value(std::string const& value) {
+ cur_value = value;
+ set_env_var();
+ }
+ void add_to_list(std::string const& list_item) {
+ if (!cur_value.empty()) {
+ cur_value += OS_ENV_VAR_LIST_SEPARATOR;
+ }
+ cur_value += list_item;
+ set_env_var();
+ }
+ void remove_value() const { remove_env_var(); }
+ const char* get() const { return name.c_str(); }
+ const char* value() const { return cur_value.c_str(); }
+
+ private:
+ std::string name;
+ std::string cur_value;
+
#if defined(WIN32)
-void set_env_var(std::string const& name, std::string const& value);
-void remove_env_var(std::string const& name);
-std::string get_env_var(std::string const& name, bool report_failure = true);
+ void set_env_var();
+ void remove_env_var() const;
+ // Environment variable list separator - not for filesystem paths
+ const char OS_ENV_VAR_LIST_SEPARATOR = ';';
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-void set_env_var(std::string const& name, std::string const& value);
-void remove_env_var(std::string const& name);
+ void set_env_var();
+ void remove_env_var() const;
+ // Environment variable list separator - not for filesystem paths
+ const char OS_ENV_VAR_LIST_SEPARATOR = ':';
+#endif
+};
+
+// get_env_var() - returns a std::string of `name`. if report_failure is true, then it will log to stderr that it didn't find the
+// env-var
+// NOTE: This is only intended for test framework code, all test code MUST use EnvVarWrapper
+#if defined(WIN32)
+std::string get_env_var(std::string const& name, bool report_failure = true);
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
std::string get_env_var(std::string const& name, bool report_failure = true);
#endif
struct ManifestICD; // forward declaration for FolderManager::write
struct ManifestLayer; // forward declaration for FolderManager::write
-#ifdef _WIN32
-// Environment variable list separator - not for filesystem paths
-const char OS_ENV_VAR_LIST_SEPARATOR = ';';
-#else
-// Environment variable list separator - not for filesystem paths
-const char OS_ENV_VAR_LIST_SEPARATOR = ':';
-#endif
-
namespace fs {
std::string make_native(std::string const&);
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
- auto driver_files = get_env_var("VK_DRIVER_FILES");
- driver_files += OS_ENV_VAR_LIST_SEPARATOR;
- driver_files += (fs::path("totally_made_up") / "path_to_fake" / "jason_file.json").str();
- set_env_var("VK_DRIVER_FILES", driver_files);
- EnvVarCleaner cleaner("VK_DRIVER_FILES");
+ env.env_var_vk_icd_filenames.add_to_list((fs::path("totally_made_up") / "path_to_fake" / "jason_file.json").str());
size_t fail_index = 0;
VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) {
// Test failure during vkCreateInstance and vkCreateDevice to make sure we don't
// leak memory if one of the out-of-memory conditions trigger.
+// Includes drivers with several instance extensions, drivers that will fail to load, directly loaded drivers
TEST(Allocation, CreateInstanceDeviceIntentionalAllocFail) {
FrameworkEnvironment env{};
uint32_t num_physical_devices = 4;
env.add_icd(TestICDDetails(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE).set_is_fake(true));
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+
+ VkDirectDriverLoadingInfoLUNARG ddl_info{};
+ ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_info.pfnGetInstanceProcAddr = direct_driver_icd.icd_library.get_symbol("vk_icdGetInstanceProcAddr");
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = 1;
+ ddl_list.pDrivers = &ddl_info;
+
const char* layer_name = "VK_LAYER_ImplicitAllocFail";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
VkInstance instance;
InstanceCreateInfo inst_create_info{};
+ inst_create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst_create_info.instance_info.pNext = reinterpret_cast<const void*>(&ddl_list);
result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance);
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
ASSERT_TRUE(tracker.empty());
// leak memory if one of the out-of-memory conditions trigger.
TEST(Allocation, CreateInstanceDeviceWithDXGIDriverIntentionalAllocFail) {
FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_discovery_type(ManifestDiscoveryType::none));
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_discovery_type(ManifestDiscoveryType::null_dir));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
for (uint32_t i = 0; i < 2; i++) {
/*
- * Copyright (c) 2021-2022 The Khronos Group Inc.
- * Copyright (c) 2021-2022 Valve Corporation
- * Copyright (c) 2021-2022 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
#include "test_environment.h"
-class EnvVarICDOverrideSetup : public ::testing::Test {
- protected:
- virtual void SetUp() {
- remove_env_var("VK_ICD_FILENAMES");
- remove_env_var("VK_DRIVER_FILES");
- remove_env_var("VK_ADD_DRIVER_FILES");
- }
-
- virtual void TearDown() {
- remove_env_var("VK_ICD_FILENAMES");
- remove_env_var("VK_DRIVER_FILES");
- remove_env_var("VK_ADD_DRIVER_FILES");
- }
-};
-
// Don't support vk_icdNegotiateLoaderICDInterfaceVersion
// Loader calls vk_icdGetInstanceProcAddr second
// does not support vk_icdGetInstanceProcAddr
// so that the test app can find them. Include some badly specified elements as well.
// Need to redirect the 'home' directory
fs::path HOME = "/home/fake_home";
- set_env_var("HOME", HOME.str());
- set_env_var("XDG_CONFIG_DIRS", ":/tmp/goober:::::/tmp/goober/::::");
- set_env_var("XDG_CONFIG_HOME", ":/tmp/goober:::::/tmp/goober2/::::");
- set_env_var("XDG_DATA_DIRS", "::::/tmp/goober3:/tmp/goober4/with spaces:::");
- set_env_var("XDG_DATA_HOME", "::::/tmp/goober3:/tmp/goober4/with spaces:::");
+ EnvVarWrapper home_env_var{"HOME", HOME.str()};
+ EnvVarWrapper xdg_config_dirs_env_var{"XDG_CONFIG_DIRS", ":/tmp/goober:::::/tmp/goober/::::"};
+ EnvVarWrapper xdg_config_home_env_var{"XDG_CONFIG_HOME", ":/tmp/goober:::::/tmp/goober2/::::"};
+ EnvVarWrapper xdg_data_dirs_env_var{"XDG_DATA_DIRS", "::::/tmp/goober3:/tmp/goober4/with spaces:::"};
+ EnvVarWrapper xdg_data_home_env_var{"XDG_DATA_HOME", "::::/tmp/goober3:/tmp/goober4/with spaces:::"};
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
- auto check_paths = [](DebugUtilsLogger const& debug_log, ManifestCategory category, fs::path const& HOME) {
+ auto check_paths = [](DebugUtilsLogger const& debug_log, ManifestCategory category) {
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober/vulkan") / category_path_name(category)).str()));
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober2/vulkan") / category_path_name(category)).str()));
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober3/vulkan") / category_path_name(category)).str()));
EXPECT_TRUE(debug_log.find((fs::path("/tmp/goober4/with spaces/vulkan") / category_path_name(category)).str()));
};
- check_paths(env.debug_log, ManifestCategory::icd, HOME);
- check_paths(env.debug_log, ManifestCategory::implicit_layer, HOME);
- check_paths(env.debug_log, ManifestCategory::explicit_layer, HOME);
+ check_paths(env.debug_log, ManifestCategory::icd);
+ check_paths(env.debug_log, ManifestCategory::implicit_layer);
+ check_paths(env.debug_log, ManifestCategory::explicit_layer);
}
// Check that a json file in the paths don't cause the loader to crash
TEST(EnvVarICDOverrideSetup, XDGContainsJsonFile) {
// Set up a layer path that includes default and user-specified locations,
// so that the test app can find them. Include some badly specified elements as well.
// Need to redirect the 'home' directory
- set_env_var("XDG_CONFIG_DIRS", "bad_file.json");
+ EnvVarWrapper xdg_config_dirs_env_var{"XDG_CONFIG_DIRS", "bad_file.json"};
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
// so that the test app can find them. Include some badly specified elements as well.
// Need to redirect the 'home' directory
fs::path HOME = "/home/fake_home";
- set_env_var("HOME", HOME.str());
+ EnvVarWrapper home_env_var{"HOME", HOME.str()};
std::string vk_layer_path = ":/tmp/carol::::/:";
vk_layer_path += (HOME / "/ with spaces/:::::/tandy:").str();
- set_env_var("VK_LAYER_PATH", vk_layer_path);
- EnvVarCleaner layer_path_cleaner("VK_LAYER_PATH");
+ EnvVarWrapper layer_path_env_var{"VK_LAYER_PATH", vk_layer_path};
InstWrapper inst1{env.vulkan_functions};
inst1.create_info.add_layer(layer_name);
FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
// so that the test app can find them. Include some badly specified elements as well.
// Need to redirect the 'home' directory
fs::path HOME = "/home/fake_home";
- set_env_var("HOME", HOME.str());
+ EnvVarWrapper home_env_var{"HOME", HOME.str()};
std::string vk_layer_path = ":/tmp/carol::::/:";
vk_layer_path += (HOME / "/ with spaces/:::::/tandy:").str();
- set_env_var("VK_ADD_LAYER_PATH", vk_layer_path);
- EnvVarCleaner add_layer_path_cleaner("VK_ADD_LAYER_PATH");
+ EnvVarWrapper add_layer_path_env_var{"VK_ADD_LAYER_PATH", vk_layer_path};
InstWrapper inst1{env.vulkan_functions};
inst1.create_info.add_layer(layer_name);
// Test that the driver filter select will only enable driver manifest files that match the filter
TEST(EnvVarICDOverrideSetup, FilterSelectDriver) {
FrameworkEnvironment env{};
- const char* filter_select_env_var = "VK_LOADER_DRIVERS_SELECT";
+ EnvVarWrapper filter_select_env_var{"VK_LOADER_DRIVERS_SELECT"};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_disable_icd_inc(true).set_json_name("ABC_ICD"));
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_2}.set_disable_icd_inc(true).set_json_name("BCD_ICD"));
// Match full-name
env.debug_log.clear();
- set_env_var(filter_select_env_var, "ABC_ICD.json");
+ filter_select_env_var.set_new_value("ABC_ICD.json");
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Match prefix
env.debug_log.clear();
- set_env_var(filter_select_env_var, "ABC*");
+ filter_select_env_var.set_new_value("ABC*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Match suffix
env.debug_log.clear();
- set_env_var(filter_select_env_var, "*C_ICD.json");
+ filter_select_env_var.set_new_value("*C_ICD.json");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Match sub-string
env.debug_log.clear();
- set_env_var(filter_select_env_var, "*BC*");
+ filter_select_env_var.set_new_value("*BC*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Match all with star '*'
env.debug_log.clear();
- set_env_var(filter_select_env_var, "*");
+ filter_select_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
// Match all with special name
env.debug_log.clear();
- set_env_var(filter_select_env_var, "~all~");
+ filter_select_env_var.set_new_value("~all~");
InstWrapper inst7{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
// Test that the driver filter disable disables driver manifest files that match the filter
TEST(EnvVarICDOverrideSetup, FilterDisableDriver) {
FrameworkEnvironment env{};
- const char* filter_disable_env_var = "VK_LOADER_DRIVERS_DISABLE";
- EnvVarCleaner filter_disable_cleaner(filter_disable_env_var);
+ EnvVarWrapper filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE"};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_disable_icd_inc(true).set_json_name("ABC_ICD"));
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_2}.set_disable_icd_inc(true).set_json_name("BCD_ICD"));
// Match full-name
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "ABC_ICD.json");
+ filter_disable_env_var.set_new_value("ABC_ICD.json");
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Match prefix
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "ABC_*");
+ filter_disable_env_var.set_new_value("ABC_*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Match suffix
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "*C_ICD.json");
+ filter_disable_env_var.set_new_value("*C_ICD.json");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Match substring
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "*BC*");
+ filter_disable_env_var.set_new_value("*BC*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Match all with star '*'
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "*");
+ filter_disable_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
// Match all with special name
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "~all~");
+ filter_disable_env_var.set_new_value("~all~");
InstWrapper inst7{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
// appropriate drivers are enabled and disabled
TEST(EnvVarICDOverrideSetup, FilterSelectAndDisableDriver) {
FrameworkEnvironment env{};
- const char* filter_select_env_var = "VK_LOADER_DRIVERS_SELECT";
- const char* filter_disable_env_var = "VK_LOADER_DRIVERS_DISABLE";
- EnvVarCleaner filter_select_cleaner(filter_select_env_var);
- EnvVarCleaner filter_disable_cleaner(filter_disable_env_var);
+ EnvVarWrapper filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE"};
+ EnvVarWrapper filter_select_env_var{"VK_LOADER_DRIVERS_SELECT"};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_disable_icd_inc(true).set_json_name("ABC_ICD"));
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_2}.set_disable_icd_inc(true).set_json_name("BCD_ICD"));
// Disable two, but enable one
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "*BC*");
- set_env_var(filter_select_env_var, "BCD*");
+ filter_disable_env_var.set_new_value("*BC*");
+ filter_select_env_var.set_new_value("BCD*");
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Disable all, but enable two
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "*");
- set_env_var(filter_select_env_var, "*BC*");
+ filter_disable_env_var.set_new_value("*");
+ filter_select_env_var.set_new_value("*BC*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Disable all, but enable all
env.debug_log.clear();
- set_env_var(filter_disable_env_var, "*");
- set_env_var(filter_select_env_var, "*");
+ filter_disable_env_var.set_new_value("*");
+ filter_select_env_var.set_new_value("*");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
/*
- * Copyright (c) 2021-2022 The Khronos Group Inc.
- * Copyright (c) 2021-2022 Valve Corporation
- * Copyright (c) 2021-2022 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
FrameworkEnvironment env;
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
const char* implicit_layer_name = "VK_LAYER_ImplicitTestLayer";
- const char* enable_env_var = "ENABLE_ME";
- const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
- EnvVarCleaner disable_cleaner(disable_env_var);
+ EnvVarWrapper enable_env_var{"ENABLE_ME"};
+ EnvVarWrapper disable_env_var{"DISABLE_ME"};
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment(disable_env_var)
- .set_enable_environment(enable_env_var)),
+ .set_disable_environment(disable_env_var.get())
+ .set_enable_environment(enable_env_var.get())),
"implicit_test_layer.json");
uint32_t count = 0;
CheckLogForLayerString(env, implicit_layer_name, false);
// set enable env-var to 0, no layer should be found
- set_env_var(enable_env_var, "0");
+ enable_env_var.set_new_value("0");
CheckLogForLayerString(env, implicit_layer_name, false);
// set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ enable_env_var.set_new_value("1");
CheckLogForLayerString(env, implicit_layer_name, true);
// remove enable env var, so we can check what happens when only disable is present
- remove_env_var(enable_env_var);
+ enable_env_var.remove_value();
// set disable env-var to 0, layer should not load
- set_env_var(disable_env_var, "0");
+ disable_env_var.set_new_value("0");
CheckLogForLayerString(env, implicit_layer_name, false);
// set disable env-var to 1, layer should not load
- set_env_var(disable_env_var, "1");
+ disable_env_var.set_new_value("1");
CheckLogForLayerString(env, implicit_layer_name, false);
// set both enable and disable env-var, layer should not load
- set_env_var(enable_env_var, "1");
- set_env_var(disable_env_var, "1");
+ enable_env_var.set_new_value("1");
+ disable_env_var.set_new_value("1");
CheckLogForLayerString(env, implicit_layer_name, false);
}
FrameworkEnvironment env;
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
const char* implicit_layer_name = "ImplicitTestLayer";
- const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner disable_cleaner(disable_env_var);
+ EnvVarWrapper disable_env_var{"DISABLE_ME"};
+
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment(disable_env_var)),
+ .set_disable_environment(disable_env_var.get())),
"implicit_test_layer.json");
uint32_t count = 0;
CheckLogForLayerString(env, implicit_layer_name, true);
// set disable env-var to 0, layer should load
- set_env_var(disable_env_var, "0");
+ disable_env_var.set_new_value("0");
CheckLogForLayerString(env, implicit_layer_name, false);
// set disable env-var to 1, layer should not load
- set_env_var(disable_env_var, "1");
+ disable_env_var.set_new_value("1");
CheckLogForLayerString(env, implicit_layer_name, false);
{
FrameworkEnvironment env;
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
const char* implicit_layer_name = "ImplicitTestLayer";
- const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner disable_cleaner(disable_env_var);
+ EnvVarWrapper disable_env_var{"DISABLE_ME"};
env.add_implicit_layer(
ManifestLayer{}
.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment(disable_env_var)
+ .set_disable_environment(disable_env_var.get())
.add_pre_instance_function(ManifestLayer::LayerDescription::FunctionOverride{}
.set_vk_func("vkEnumerateInstanceLayerProperties")
.set_override_name("test_preinst_vkEnumerateInstanceLayerProperties"))),
ASSERT_EQ(count, layer_props);
// set disable env-var to 1, layer should not load
- set_env_var(disable_env_var, "1");
+ disable_env_var.set_new_value("1");
count = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
FrameworkEnvironment env;
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
const char* implicit_layer_name = "ImplicitTestLayer";
- const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner disable_cleaner(disable_env_var);
+ EnvVarWrapper disable_env_var{"DISABLE_ME"};
env.add_implicit_layer(ManifestLayer{}
.set_file_format_version(ManifestVersion(1, 1, 2))
.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment(disable_env_var)
+ .set_disable_environment(disable_env_var.get())
.add_pre_instance_function(
ManifestLayer::LayerDescription::FunctionOverride{}
.set_vk_func("vkEnumerateInstanceExtensionProperties")
ASSERT_EQ(count, ext_props);
// set disable env-var to 1, layer should not load
- set_env_var(disable_env_var, "1");
+ disable_env_var.set_new_value("1");
count = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr));
env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 3);
const char* implicit_layer_name = "ImplicitTestLayer";
- const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner disable_cleaner(disable_env_var);
+ EnvVarWrapper disable_env_var{"DISABLE_ME"};
env.add_implicit_layer(
ManifestLayer{}
.set_name(implicit_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_api_version(VK_MAKE_API_VERSION(0, 1, 2, 3))
- .set_disable_environment(disable_env_var)
+ .set_disable_environment(disable_env_var.get())
.add_pre_instance_function(ManifestLayer::LayerDescription::FunctionOverride{}
.set_vk_func("vkEnumerateInstanceVersion")
.set_override_name("test_preinst_vkEnumerateInstanceVersion"))),
ASSERT_EQ(version, layer_version);
// set disable env-var to 1, layer should not load
- set_env_var(disable_env_var, "1");
+ disable_env_var.set_new_value("1");
version = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceVersion(&version));
env.get_test_icd().physical_devices.push_back({});
const char* implicit_layer_name = "ImplicitTestLayer";
- const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner disable_cleaner(disable_env_var);
+ EnvVarWrapper disable_env_var{"DISABLE_ME"};
env.add_implicit_layer(ManifestLayer{}
.set_file_format_version(ManifestVersion(1, 0, 0))
.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_1)
- .set_disable_environment(disable_env_var)
+ .set_disable_environment(disable_env_var.get())
.add_function(ManifestLayer::LayerDescription::FunctionOverride{}
.set_vk_func("vkGetInstanceProcAddr")
.set_override_name("test_override_vkGetInstanceProcAddr"))),
{
// set disable env-var to 1, layer should not load
- set_env_var(disable_env_var, "1");
+ disable_env_var.set_new_value("1");
InstWrapper inst2{env.vulkan_functions};
inst2.CheckCreate();
}
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
implicit_json_name_3);
- EnvVarCleaner layers_enable_cleaner("VK_LOADER_LAYERS_ENABLE");
- EnvVarCleaner layer_1_enable_cleaner(enable_layer_name_1);
+ EnvVarWrapper layers_enable_env_var{"VK_LOADER_LAYERS_ENABLE"};
+ EnvVarWrapper layer_1_enable_env_var{enable_layer_name_1};
// First, test an instance/device without the layer forced on.
InstWrapper inst1{env.vulkan_functions};
// Now force on one layer with its full name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", implicit_layer_name_1);
+ layers_enable_env_var.set_new_value(implicit_layer_name_1);
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Match prefix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "VK_LAYER_LUNARG_*");
+ layers_enable_env_var.set_new_value("VK_LAYER_LUNARG_*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Match suffix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second_layer");
+ layers_enable_env_var.set_new_value("*Second_layer");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Match substring
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Match all with star '*'
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+ layers_enable_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
// Match all with special name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "~all~");
+ layers_enable_env_var.set_new_value("~all~");
InstWrapper inst7{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
// Match substring, but enable the other layer manually
// ------------------------------------------
env.debug_log.clear();
- set_env_var(enable_layer_name_1, "1");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layer_1_enable_env_var.set_new_value("1");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst8{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst8.create_info, env.debug_log);
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
implicit_json_name_3);
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
// First, test an instance/device
InstWrapper inst1{env.vulkan_functions};
// Now force off one layer with its full name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", implicit_layer_name_1);
+ layers_disable_env_var.set_new_value(implicit_layer_name_1);
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Match prefix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "VK_LAYER_LUNARG_*");
+ layers_disable_env_var.set_new_value("VK_LAYER_LUNARG_*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Match suffix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second_layer");
+ layers_disable_env_var.set_new_value("*Second_layer");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Match substring
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second*");
+ layers_disable_env_var.set_new_value("*Second*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Match all with star '*'
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+ layers_disable_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
// Match all with special name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~all~");
+ layers_disable_env_var.set_new_value("~all~");
InstWrapper inst7{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
implicit_json_name_2);
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
- EnvVarCleaner layer_1_enable_cleaner(enable_layer_name_1);
- EnvVarCleaner layer_2_enable_cleaner(enable_layer_name_2);
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
+ EnvVarWrapper layer_1_enable_env_var{enable_layer_name_1};
+ EnvVarWrapper layer_2_enable_env_var{enable_layer_name_2};
// First, test an instance/device
InstWrapper inst1{env.vulkan_functions};
// Set the layers enable env-var
// ------------------------------------------
env.debug_log.clear();
- set_env_var(enable_layer_name_1, "1");
- set_env_var(enable_layer_name_2, "1");
+ layer_1_enable_env_var.set_new_value("1");
+ layer_2_enable_env_var.set_new_value("1");
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Now force off one layer with its full name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", implicit_layer_name_1);
+ layers_disable_env_var.set_new_value(implicit_layer_name_1);
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Now force off both layers
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~implicit~");
+ layers_disable_env_var.set_new_value("~implicit~");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
implicit_json_name_3);
- EnvVarCleaner layers_enable_cleaner("VK_LOADER_LAYERS_ENABLE");
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
+ EnvVarWrapper layers_enable_env_var{"VK_LOADER_LAYERS_ENABLE"};
// Disable 2 but enable 1
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second*");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*test_layer");
+ layers_disable_env_var.set_new_value("*Second*");
+ layers_enable_env_var.set_new_value("*test_layer");
InstWrapper inst1{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
// Disable all but enable 2
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("*");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Disable all but enable 2
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~all~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("~all~");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Disable implicit but enable 2
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~implicit~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("~implicit~");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Disable explicit but enable 2 (should still be everything)
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~explicit~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("~explicit~");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Disable implicit but enable all
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~implicit~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+ layers_disable_env_var.set_new_value("~implicit~");
+ layers_enable_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
EXPECT_TRUE(string_eq(layer_props.layerName, regular_layer_name));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 3> extensions;
+ std::array<VkExtensionProperties, 4> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ EXPECT_EQ(extension_count, 4U); // debug report & debug utils & portability enumeration & direct driver loading
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 3U);
+ EXPECT_EQ(extension_count, 4U); // debug report & debug utils & portability enumeration & direct driver loading
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_layer(meta_layer_name);
EXPECT_TRUE(check_permutation({regular_layer_name, meta_layer_name}, layer_props));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 3> extensions;
+ std::array<VkExtensionProperties, 4> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ EXPECT_EQ(extension_count, 4U); // debug report, debug utils, portability enumeration, direct driver loading
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 3U);
+ EXPECT_EQ(extension_count, 4U); // debug report, debug utils, portability enumeration, direct driver loading
}
{ // don't enable the layer, shouldn't find any layers when calling vkEnumerateDeviceLayerProperties
InstWrapper inst{env.vulkan_functions};
EXPECT_TRUE(string_eq(layer_props.layerName, regular_layer_name));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 3> extensions;
+ std::array<VkExtensionProperties, 4> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ EXPECT_EQ(extension_count, 4U); // debug report & debug utils & portability enumeration
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 3U);
+ EXPECT_EQ(extension_count, 4U); // debug report, debug utils, portability enumeration, direct driver loading
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_layer(meta_layer_name);
EXPECT_TRUE(check_permutation({regular_layer_name, meta_layer_name, meta_meta_layer_name}, layer_props));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 3> extensions;
+ std::array<VkExtensionProperties, 4> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ EXPECT_EQ(extension_count, 4U); // debug report & debug utils & portability enumeration & direct driver loading
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 3U);
+ EXPECT_EQ(extension_count, 4U); // debug report, debug utils, portability enumeration, direct driver loading
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_layer(meta_layer_name);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
ASSERT_FALSE(env.debug_log.find(std::string("Insert instance layer \"") + env_var_layer_name));
- ASSERT_TRUE(
- env.debug_log.find("Ignoring VK_LAYER_PATH. The Override layer is active and has override paths set, which takes priority. "
- "VK_LAYER_PATH is set to " +
- env.env_var_vk_layer_paths));
+ ASSERT_TRUE(env.debug_log.find(
+ std::string("Ignoring VK_LAYER_PATH. The Override layer is active and has override paths set, which takes priority. "
+ "VK_LAYER_PATH is set to ") +
+ env.env_var_vk_layer_paths.value()));
env.layers.clear();
- remove_env_var("VK_LAYER_PATH");
}
// Make sure that implicit layers not in the override paths aren't found by mistake
ManifestLayer::LayerDescription{}.set_name(regular_layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
"regular_test_layer.json");
- auto& layer = env.get_test_layer(0);
- layer.set_create_instance_callback([](TestLayer& layer) -> VkResult {
+ auto& layer_handle = env.get_test_layer(0);
+ layer_handle.set_create_instance_callback([](TestLayer& layer) -> VkResult {
uint32_t phys_dev_count = 0;
VkResult res = layer.instance_dispatch_table.EnumeratePhysicalDevices(layer.instance_handle, &phys_dev_count, nullptr);
if (res != VK_SUCCESS || phys_dev_count > 1) {
ManifestLayer::LayerDescription{}.set_name(regular_layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
"regular_test_layer.json");
- auto& layer = env.get_test_layer(0);
- layer.set_create_instance_callback([](TestLayer& layer) -> VkResult {
+ auto& layer_handle = env.get_test_layer(0);
+ layer_handle.set_create_instance_callback([](TestLayer& layer) -> VkResult {
uint32_t phys_dev_count = 1;
VkPhysicalDevice phys_dev{};
layer.instance_dispatch_table.EnumeratePhysicalDevices(layer.instance_handle, &phys_dev_count, &phys_dev);
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
ASSERT_EQ(count, 1U);
// set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
uint32_t extension_count = 0;
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- ASSERT_EQ(extension_count, 3U); // debug_utils, debug_report, and portability enumeration
+ ASSERT_EQ(extension_count, 4U); // debug_utils, debug_report, portability enumeration, direct driver loading
// Make sure the extensions that are implemented only in the test layers is not present.
ASSERT_FALSE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(
ManifestLayer{}.add_layer(
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 4U); // the instance extension, debug_utils, debug_report, and portability enumeration
+ ASSERT_EQ(extension_count,
+ 5U); // the instance extension, debug_utils, debug_report, portability enumeration, direct driver loading
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- ASSERT_EQ(extension_count, 4U);
+ ASSERT_EQ(extension_count, 5U);
// Make sure the extensions that are implemented only in the test layers is not present.
ASSERT_TRUE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 4U); // the instance extension, debug_utils, debug_report, and portability enumeration
+ ASSERT_EQ(extension_count,
+ 5U); // the instance extension, debug_utils, debug_report, portability enumeration, direct driver loading
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- ASSERT_EQ(extension_count, 4U);
+ ASSERT_EQ(extension_count, 5U);
// Make sure the extensions that are implemented only in the test layers is not present.
ASSERT_FALSE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(
ManifestLayer{}.add_layer(
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 5U); // the two instance extension plus debug_utils, debug_report, portability enumeration
+ ASSERT_EQ(extension_count,
+ 6U); // the two instance extension plus debug_utils, debug_report, portability enumeration, direct driver loading
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- ASSERT_EQ(extension_count, 5U);
+ ASSERT_EQ(extension_count, 6U);
// Make sure the extensions that are implemented only in the test layers is not present.
ASSERT_TRUE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // debug utils, debug report, portability enumeration
+ ASSERT_EQ(extension_count, 4U); // debug utils, debug report, portability enumeration, direct driver loading
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- ASSERT_EQ(extension_count, 3U);
+ ASSERT_EQ(extension_count, 4U); // debug report, debug utils, portability enumeration, direct driver loading
// Make sure the extensions are not present
for (const auto& ext : extension_props) {
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // debug utils, debug report, portability enumeration
+ ASSERT_EQ(extension_count, 4U); // debug utils, debug report, portability enumeration
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- ASSERT_EQ(extension_count, 3U);
+ ASSERT_EQ(extension_count, 4U);
// Make sure the extensions are not present
for (const auto& ext : extension_props) {
ASSERT_FALSE(string_eq(ext.extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
- EnvVarCleaner enable_cleaner(enable_env_var);
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
InstWrapper inst{env.vulkan_functions};
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
InstWrapper inst{env.vulkan_functions};
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
InstWrapper inst{env.vulkan_functions};
const char* implicit_layer_name = "VK_LAYER_LUNARG_wrap_objects";
const char* enable_env_var = "ENABLE_ME";
const char* disable_env_var = "DISABLE_ME";
- EnvVarCleaner enable_cleaner(enable_env_var);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
- set_env_var(enable_env_var, "1");
+ // set enable env-var, layer should load
+ EnvVarWrapper wrap_enable_env_var{enable_env_var, "1"};
CheckLogForLayerString(env, implicit_layer_name, true);
InstWrapper inst{env.vulkan_functions};
handle_assert_null(pfn_GetSwapchainStatusBefore);
// Now setup the instance layer
- set_env_var("VK_INSTANCE_LAYERS", explicit_layer_name);
- EnvVarCleaner instance_layers_cleaner("VK_INSTANCE_LAYERS");
+ EnvVarWrapper instance_layers_env_var{"VK_INSTANCE_LAYERS", explicit_layer_name};
// Now, test an instance/device with the layer forced on. The extensions should be present and
// the function pointers should be valid.
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
explicit_json_name_3);
- EnvVarCleaner layers_enable_cleaner("VK_LOADER_LAYERS_ENABLE");
+ EnvVarWrapper layers_enable_env_var{"VK_LOADER_LAYERS_ENABLE"};
// First, test an instance/device without the layer forced on.
InstWrapper inst1{env.vulkan_functions};
// Now force on one layer with its full name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", explicit_layer_name_1);
+ layers_enable_env_var.set_new_value(explicit_layer_name_1);
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Match prefix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "VK_LAYER_LUNARG_*");
+ layers_enable_env_var.set_new_value("VK_LAYER_LUNARG_*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Match suffix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second_layer");
+ layers_enable_env_var.set_new_value("*Second_layer");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Match substring
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Match all with star '*'
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+ layers_enable_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
// Match all with special name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", "~all~");
+ layers_enable_env_var.set_new_value("~all~");
InstWrapper inst7{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
explicit_json_name_3);
- EnvVarCleaner layers_enable_cleaner("VK_LOADER_LAYERS_ENABLE");
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
// First, test an instance/device without the layer forced on.
InstWrapper inst1{env.vulkan_functions};
// Now force on one layer with its full name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", explicit_layer_name_1);
+ layers_disable_env_var.set_new_value(explicit_layer_name_1);
InstWrapper inst2{env.vulkan_functions};
inst2.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Match prefix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "VK_LAYER_LUNARG_*");
+ layers_disable_env_var.set_new_value("VK_LAYER_LUNARG_*");
InstWrapper inst3{env.vulkan_functions};
inst3.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Match suffix
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second_layer");
+ layers_disable_env_var.set_new_value("*Second_layer");
InstWrapper inst4{env.vulkan_functions};
inst4.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Match substring
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second*");
+ layers_disable_env_var.set_new_value("*Second*");
InstWrapper inst5{env.vulkan_functions};
inst5.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Match all with star '*'
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+ layers_disable_env_var.set_new_value("*");
InstWrapper inst6{env.vulkan_functions};
inst6.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Match all with special name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~all~");
+ layers_disable_env_var.set_new_value("~all~");
InstWrapper inst7{env.vulkan_functions};
inst7.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Match explicit special name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~explicit~");
+ layers_disable_env_var.set_new_value("~explicit~");
InstWrapper inst8{env.vulkan_functions};
inst8.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// No match implicit special name
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~implicit~");
+ layers_disable_env_var.set_new_value("~implicit~");
InstWrapper inst9{env.vulkan_functions};
inst9.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
explicit_json_name_3);
- EnvVarCleaner layers_enable_cleaner("VK_LOADER_LAYERS_ENABLE");
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_enable_env_var{"VK_LOADER_LAYERS_ENABLE"};
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
// First, test an instance/device without the layer forced on.
InstWrapper inst1{env.vulkan_functions};
// Disable 2 but enable 1
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second*");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*test_layer");
+ layers_disable_env_var.set_new_value("*Second*");
+ layers_enable_env_var.set_new_value("*test_layer");
InstWrapper inst2{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
// Disable all but enable 2
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("*");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst3{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
// Disable all but enable 2
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~all~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("~all~");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst4{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
// Disable explicit but enable 2
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~explicit~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("~explicit~");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst5{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
// Disable implicit but enable 2 (should still be everything)
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~implicit~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+ layers_disable_env_var.set_new_value("~implicit~");
+ layers_enable_env_var.set_new_value("*Second*");
InstWrapper inst6{env.vulkan_functions};
inst6.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
// Disable explicit but enable all
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "~explicit~");
- set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+ layers_disable_env_var.set_new_value("~explicit~");
+ layers_enable_env_var.set_new_value("*");
InstWrapper inst7{env.vulkan_functions};
inst7.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
explicit_json_name_2);
- EnvVarCleaner instance_layers_cleaner("VK_INSTANCE_LAYERS");
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_enable_env_var{"VK_INSTANCE_LAYERS"};
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
// First, test an instance/device without the layer forced on.
InstWrapper inst1{env.vulkan_functions};
// Enable the non-default enabled layer with VK_INSTANCE_LAYERS
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_INSTANCE_LAYERS", explicit_layer_name_2);
+ layers_enable_env_var.set_new_value(explicit_layer_name_2);
InstWrapper inst2{env.vulkan_functions};
inst2.create_info.add_layer(explicit_layer_name_1);
// Try to disable all
// ------------------------------------------
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+ layers_disable_env_var.set_new_value("*");
InstWrapper inst3{env.vulkan_functions};
inst3.create_info.add_layer(explicit_layer_name_1);
explicit_json_name_1);
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", explicit_layer_name_1);
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE", explicit_layer_name_1};
uint32_t count = 0;
env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr);
"meta_test_layer.json");
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", explicit_layer_name_1);
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE", explicit_layer_name_1};
uint32_t count = 0;
env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr);
"meta_test_layer.json");
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_DISABLE", lunarg_meta_layer_name);
- EnvVarCleaner layers_disable_cleaner("VK_LOADER_LAYERS_DISABLE");
+ EnvVarWrapper layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE", lunarg_meta_layer_name};
uint32_t count = 0;
env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr);
"meta_test_layer.json");
env.debug_log.clear();
- set_env_var("VK_LOADER_LAYERS_ENABLE", explicit_layer_name_1);
- EnvVarCleaner layers_enable_cleaner("VK_LOADER_LAYERS_ENABLE");
+ EnvVarWrapper layers_enable_env_var{"VK_LOADER_LAYERS_ENABLE", explicit_layer_name_1};
uint32_t count = 0;
env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr);
/*
- * Copyright (c) 2021-2022 The Khronos Group Inc.
- * Copyright (c) 2021-2022 Valve Corporation
- * Copyright (c) 2021-2022 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
env.reset_icd().add_instance_extensions({first_ext, second_ext});
{ // One Pass
- uint32_t extension_count = 5;
- std::array<VkExtensionProperties, 5> extensions;
+ uint32_t extension_count = 6;
+ std::array<VkExtensionProperties, 6> extensions;
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 5U); // return debug report & debug utils & portability enumeration + our two extensions
+ ASSERT_EQ(extension_count, 6U); // default extensions + our two extensions
// loader always adds the debug report & debug utils extensions
ASSERT_TRUE(first_ext.extensionName == extensions[0].extensionName);
}
{ // Two Pass
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 5> extensions;
+ std::array<VkExtensionProperties, 6> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 5U); // return debug report & debug utils + our two extensions
+ ASSERT_EQ(extension_count, 6U); // return default extensions + our extension
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 5U);
+ ASSERT_EQ(extension_count, 6U);
// loader always adds the debug report & debug utils extensions
ASSERT_TRUE(first_ext.extensionName == extensions[0].extensionName);
ASSERT_TRUE(second_ext.extensionName == extensions[1].extensionName);
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 2> extensions;
+ std::array<VkExtensionProperties, 4> extensions;
{ // use nullptr for null string
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ ASSERT_EQ(extension_count, 4U); // return debug report & debug utils & portability enumeration & direct driver loading
extension_count = 1; // artificially remove one extension
ASSERT_EQ(VK_INCOMPLETE,
}
{ // use "" for null string
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ ASSERT_EQ(extension_count, 4U); // return debug report & debug utils & portability enumeration & direct driver loading
extension_count = 1; // artificially remove one extension
ASSERT_EQ(VK_INCOMPLETE,
{
uint32_t extension_count = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
+ ASSERT_EQ(extension_count, 4U); // debug report & debug utils & portability enumeration & direct driver loading
- std::array<VkExtensionProperties, 3> extensions;
+ std::array<VkExtensionProperties, 4> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 3U);
+ ASSERT_EQ(extension_count, 4U); // debug report & debug utils & portability enumeration & direct driver loading
// loader always adds the debug report & debug utils extensions
ASSERT_TRUE(string_eq(extensions[0].extensionName, "VK_EXT_debug_report"));
ASSERT_TRUE(string_eq(extensions[1].extensionName, "VK_EXT_debug_utils"));
ASSERT_TRUE(string_eq(extensions[2].extensionName, "VK_KHR_portability_enumeration"));
+ ASSERT_TRUE(string_eq(extensions[3].extensionName, "VK_LUNARG_direct_driver_loading"));
}
{ // Disable unknown instance extension filtering
- set_env_var("VK_LOADER_DISABLE_INST_EXT_FILTER", "1");
+ EnvVarWrapper disable_inst_ext_filter_env_var{"VK_LOADER_DISABLE_INST_EXT_FILTER", "1"};
uint32_t extension_count = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
- ASSERT_EQ(extension_count, 5U);
+ ASSERT_EQ(extension_count, 6U);
- std::array<VkExtensionProperties, 5> extensions;
+ std::array<VkExtensionProperties, 6> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 5U);
+ ASSERT_EQ(extension_count, 6U);
ASSERT_EQ(extensions[0], first_ext.get());
ASSERT_EQ(extensions[1], second_ext.get());
ASSERT_TRUE(string_eq(extensions[2].extensionName, "VK_EXT_debug_report"));
ASSERT_TRUE(string_eq(extensions[3].extensionName, "VK_EXT_debug_utils"));
ASSERT_TRUE(string_eq(extensions[4].extensionName, "VK_KHR_portability_enumeration"));
+ ASSERT_TRUE(string_eq(extensions[5].extensionName, "VK_LUNARG_direct_driver_loading"));
}
}
TEST(SortedPhysicalDevices, DevicesSortedDisabled) {
FrameworkEnvironment env{};
- set_env_var("VK_LOADER_DISABLE_SELECT", "1");
- EnvVarCleaner disable_select_cleaner("VK_LOADER_DISABLE_SELECT");
+ EnvVarWrapper disable_select_env_var{"VK_LOADER_DISABLE_SELECT", "1"};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_0));
env.get_test_icd(0).add_instance_extension({VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME});
TEST(SortedPhysicalDevices, DeviceGroupsSortedDisabled) {
FrameworkEnvironment env{};
- set_env_var("VK_LOADER_DISABLE_SELECT", "1");
- EnvVarCleaner disable_select_cleaner("VK_LOADER_DISABLE_SELECT");
+ EnvVarWrapper disable_select_env_var{"VK_LOADER_DISABLE_SELECT", "1"};
// ICD 0: Vulkan 1.1
// PhysDev 0: pd0, Discrete, Vulkan 1.1, Bus 7
{
// check that enumerating instance extensions work with a portability driver present
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 5> extensions;
+ std::array<VkExtensionProperties, 6> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 5U); // return debug report & debug utils + our two extensions
+ // loader always adds the debug report, debug utils extensions, portability enumeration, direct driver loading
+ ASSERT_EQ(extension_count, 6U);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 5U);
- // loader always adds the debug report & debug utils extensions
+ ASSERT_EQ(extension_count, 6U);
+ // loader always adds the debug report, debug utils extensions, portability enumeration, direct driver loading
ASSERT_TRUE(first_ext.extensionName == extensions[0].extensionName);
ASSERT_TRUE(second_ext.extensionName == extensions[1].extensionName);
ASSERT_TRUE(string_eq("VK_EXT_debug_report", extensions[2].extensionName));
ASSERT_TRUE(string_eq("VK_EXT_debug_utils", extensions[3].extensionName));
ASSERT_TRUE(string_eq("VK_KHR_portability_enumeration", extensions[4].extensionName));
+ ASSERT_TRUE(string_eq("VK_LUNARG_direct_driver_loading", extensions[5].extensionName));
}
const char* layer_name = "TestLayer";
auto null_path = env.get_folder(ManifestLocation::null).location() / "test_icd_0.json";
env.platform_shim->add_manifest(ManifestCategory::icd, null_path.str());
- env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::none));
+ env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::null_dir));
auto& driver = env.get_test_icd();
driver.physical_devices.emplace_back("physical_device_0");
driver.adapterLUID = _LUID{10, 1000};
// Check that valid symlinks do not cause the loader to crash when directly in an XDG env-var
TEST(ManifestDiscovery, ValidSymlinkInXDGEnvVar) {
FrameworkEnvironment env{true, false};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::none));
+ env.add_icd(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::override_folder));
env.get_test_icd().physical_devices.push_back({});
auto driver_path = env.get_icd_manifest_path(0);
std::string symlink_name = "symlink_to_driver.json";
env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
int res = symlink(driver_path.c_str(), symlink_path.c_str());
ASSERT_EQ(res, 0);
- set_env_var("XDG_CONFIG_DIRS", symlink_path.str());
+ EnvVarWrapper xdg_config_dirs_env_var{"XDG_CONFIG_DIRS", symlink_path.str()};
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
// Check that valid symlinks do not cause the loader to crash
TEST(ManifestDiscovery, ValidSymlink) {
FrameworkEnvironment env{true, false};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::none));
+ env.add_icd(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::override_folder));
env.get_test_icd().physical_devices.push_back({});
auto driver_path = env.get_icd_manifest_path(0);
ASSERT_EQ(res, 0);
env.get_folder(ManifestLocation::driver_env_var).add_existing_file(symlink_name);
- set_env_var("XDG_CONFIG_DIRS", symlink_path.str());
+ EnvVarWrapper xdg_config_dirs_env_var{symlink_path.str()};
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
/*
- * Copyright (c) 2021 The Khronos Group Inc.
- * Copyright (c) 2021 Valve Corporation
- * Copyright (c) 2021 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
// clean up folders from old test
fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "null_dir");
fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "icd_manifests");
- fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "portability_icd_manifests");
+ fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "icd_env_vars_manifests");
fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "explicit_layer_manifests");
+ fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "explicit_env_var_layer_folder");
+ fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "explicit_add_env_var_layer_folder");
fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "implicit_layer_manifests");
+ fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "override_layer_manifests");
+ fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "app_package_manifests");
+ fs::delete_folder(fs::path(FRAMEWORK_BUILD_DIRECTORY) / "macos_bundle");
// make sure the tests don't find these env-vars if they were set on the system
- remove_env_var("VK_ICD_FILENAMES");
- remove_env_var("VK_DRIVER_FILES");
- remove_env_var("VK_ADD_DRIVER_FILES");
- remove_env_var("VK_LAYER_PATH");
- remove_env_var("VK_ADD_LAYER_PATH");
- remove_env_var("VK_INSTANCE_LAYERS");
- remove_env_var("VK_LOADER_DRIVERS_SELECT");
- remove_env_var("VK_LOADER_DRIVERS_DISABLE");
- remove_env_var("VK_LOADER_LAYERS_ENABLE");
- remove_env_var("VK_LOADER_LAYERS_DISABLE");
- remove_env_var("VK_LOADER_DEBUG");
- remove_env_var("VK_LOADER_DISABLE_INST_EXT_FILTER");
+ EnvVarWrapper vk_icd_filenames_env_var{"VK_ICD_FILENAMES"};
+ EnvVarWrapper vk_driver_files_env_var{"VK_DRIVER_FILES"};
+ EnvVarWrapper vk_add_driver_files_env_var{"VK_ADD_DRIVER_FILES"};
+ EnvVarWrapper vk_layer_path_env_var{"VK_LAYER_PATH"};
+ EnvVarWrapper vk_add_layer_path_env_var{"VK_ADD_LAYER_PATH"};
+ EnvVarWrapper vk_instance_layers_env_var{"VK_INSTANCE_LAYERS"};
+ EnvVarWrapper vk_loader_drivers_select_env_var{"VK_LOADER_DRIVERS_SELECT"};
+ EnvVarWrapper vk_loader_drivers_disable_env_var{"VK_LOADER_DRIVERS_DISABLE"};
+ EnvVarWrapper vk_loader_layers_enable_env_var{"VK_LOADER_LAYERS_ENABLE"};
+ EnvVarWrapper vk_loader_layers_disable_env_var{"VK_LOADER_LAYERS_DISABLE"};
+ EnvVarWrapper vk_loader_debug_env_var{"VK_LOADER_DEBUG"};
+ EnvVarWrapper vk_loader_disable_inst_ext_filter_env_var{"VK_LOADER_DISABLE_INST_EXT_FILTER"};
+ vk_icd_filenames_env_var.remove_value();
+ vk_driver_files_env_var.remove_value();
+ vk_add_driver_files_env_var.remove_value();
+ vk_layer_path_env_var.remove_value();
+ vk_add_layer_path_env_var.remove_value();
+ vk_instance_layers_env_var.remove_value();
+ vk_loader_drivers_select_env_var.remove_value();
+ vk_loader_drivers_disable_env_var.remove_value();
+ vk_loader_layers_enable_env_var.remove_value();
+ vk_loader_layers_disable_env_var.remove_value();
+ vk_loader_debug_env_var.remove_value();
+ vk_loader_disable_inst_ext_filter_env_var.remove_value();
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__)
- set_env_var("XDG_CONFIG_HOME", "/etc");
- set_env_var("XDG_CONFIG_DIRS", "/etc");
- set_env_var("XDG_DATA_HOME", "/etc");
- set_env_var("XDG_DATA_DIRS", "/etc");
+ EnvVarWrapper xdg_config_home_env_var{"XDG_CONFIG_HOME", "/etc"};
+ EnvVarWrapper xdg_config_dirs_env_var{"XDG_CONFIG_DIRS", "/etc"};
+ EnvVarWrapper xdg_data_home_env_var{"XDG_DATA_HOME", "/etc"};
+ EnvVarWrapper xdg_data_dirs_env_var{"XDG_DATA_DIRS", "/etc"};
#endif
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
- set_env_var("HOME", "/home/fake_home");
+ EnvVarWrapper home_env_var{"HOME", "/home/fake_home"};
#endif
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
/*
- * Copyright (c) 2021-2022 The Khronos Group Inc.
- * Copyright (c) 2021-2022 Valve Corporation
- * Copyright (c) 2021-2022 LunarG, Inc.
+ * Copyright (c) 2021-2023 The Khronos Group Inc.
+ * Copyright (c) 2021-2023 Valve Corporation
+ * Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
// Make the version_6 driver found through the D3DKMT driver discovery mechanism of the loader
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, version_6) {
FrameworkEnvironment env{};
- env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_discovery_type(ManifestDiscoveryType::none));
+ env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_discovery_type(ManifestDiscoveryType::null_dir));
// Version 6 provides a mechanism to allow the loader to sort physical devices.
// The loader will only attempt to sort physical devices on an ICD if version 6 of the interface is supported.
// This version provides the vk_icdEnumerateAdapterPhysicalDevices function.
// EnumerateAdapterPhysicalDevices
TEST(ICDInterfaceVersion2, EnumAdapters2) {
FrameworkEnvironment env{};
- env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::none));
+ env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::null_dir));
InstWrapper inst{env.vulkan_functions};
auto& driver = env.get_test_icd();
driver.physical_devices.emplace_back("physical_device_1");
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, VerifyPhysDevResults) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES}.set_discovery_type(
- ManifestDiscoveryType::none));
+ ManifestDiscoveryType::null_dir));
auto& driver = env.get_test_icd();
driver.min_icd_interface_version = 6;
driver.set_icd_api_version(VK_API_VERSION_1_1);
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, VerifyGroupResults) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES}.set_discovery_type(
- ManifestDiscoveryType::none));
+ ManifestDiscoveryType::null_dir));
auto& driver = env.get_test_icd();
driver.min_icd_interface_version = 6;
driver.set_icd_api_version(VK_API_VERSION_1_1);
// log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
ASSERT_TRUE(log.find("has unknown layer manifest file version 3.2.1. May cause errors."));
}
+
+struct DriverInfo {
+ DriverInfo(TestICDDetails icd_details, uint32_t driver_version, bool expect_to_find) noexcept
+ : icd_details(icd_details), driver_version(driver_version), expect_to_find(expect_to_find) {}
+ TestICDDetails icd_details;
+ uint32_t driver_version = 0;
+ bool expect_to_find = false;
+};
+
+void CheckDirectDriverLoading(FrameworkEnvironment& env, std::vector<DriverInfo> const& normal_drivers,
+ std::vector<DriverInfo> const& direct_drivers, bool exclusive) {
+ std::vector<VkDirectDriverLoadingInfoLUNARG> ddl_infos;
+ uint32_t expected_driver_count = 0;
+
+ for (auto const& driver : direct_drivers) {
+ auto& direct_driver_icd = env.add_icd(driver.icd_details);
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+ direct_driver_icd.get_test_icd().physical_devices.at(0).properties.driverVersion = driver.driver_version;
+ VkDirectDriverLoadingInfoLUNARG ddl_info{};
+ ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_info.pfnGetInstanceProcAddr = direct_driver_icd.icd_library.get_symbol("vk_icdGetInstanceProcAddr");
+ ddl_infos.push_back(ddl_info);
+ if (driver.expect_to_find) {
+ expected_driver_count++;
+ }
+ }
+
+ for (auto const& driver : normal_drivers) {
+ auto& direct_driver_icd = env.add_icd(driver.icd_details);
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+ direct_driver_icd.get_test_icd().physical_devices.at(0).properties.driverVersion = driver.driver_version;
+ if (!exclusive && driver.expect_to_find) {
+ expected_driver_count++;
+ }
+ }
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = exclusive ? VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG : VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = static_cast<uint32_t>(ddl_infos.size());
+ ddl_list.pDrivers = ddl_infos.data();
+
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
+
+ if (exclusive) {
+ ASSERT_TRUE(
+ log.find("loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified "
+ "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment "
+ "variable driver search mechanisms."));
+ }
+
+ // Make sure all drivers we expect to load were found - including checking that the pfn matches exactly.
+ for (uint32_t i = 0; i < direct_drivers.size(); i++) {
+ if (direct_drivers.at(i).expect_to_find) {
+ std::stringstream ss;
+ ss << "loader_add_direct_driver: Adding driver found in index " << i
+ << " of VkDirectDriverLoadingListLUNARG::pDrivers structure. pfnGetInstanceProcAddr was set to "
+ << reinterpret_cast<const void*>(ddl_infos.at(i).pfnGetInstanceProcAddr);
+ std::string log_message = ss.str();
+ ASSERT_TRUE(log.find(log_message));
+ }
+ }
+
+ auto phys_devs = inst.GetPhysDevs();
+ ASSERT_EQ(phys_devs.size(), expected_driver_count);
+
+ // We have to iterate through the driver lists backwards because the loader *prepends* icd's, so the last found ICD is found
+ // first in the driver list
+ uint32_t driver_index = 0;
+ for (size_t i = normal_drivers.size() - 1; i == 0; i--) {
+ if (normal_drivers.at(i).expect_to_find) {
+ VkPhysicalDeviceProperties props{};
+ inst.functions->vkGetPhysicalDeviceProperties(phys_devs.at(driver_index), &props);
+ ASSERT_EQ(props.driverVersion, normal_drivers.at(i).driver_version);
+ driver_index++;
+ }
+ }
+ for (size_t i = direct_drivers.size() - 1; i == 0; i--) {
+ if (direct_drivers.at(i).expect_to_find) {
+ VkPhysicalDeviceProperties props{};
+ inst.functions->vkGetPhysicalDeviceProperties(phys_devs.at(driver_index), &props);
+ ASSERT_EQ(props.driverVersion, direct_drivers.at(i).driver_version);
+ driver_index++;
+ }
+ }
+}
+
+// Only 1 direct driver
+TEST(DirectDriverLoading, Individual) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 10, true);
+
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
+}
+
+// 2 direct drivers
+TEST(DirectDriverLoading, MultipleDirectDrivers) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 13, true);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 7, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
+}
+
+// Multiple direct drivers with a normal driver in the middle
+TEST(DirectDriverLoading, MultipleDirectDriversAndNormalDrivers) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+ normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA), 90, true);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 80, true);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 70, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
+}
+
+// Normal driver and direct driver with direct driver exclusivity
+TEST(DirectDriverLoading, ExclusiveWithNormalDriver) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 33, true);
+ normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 44, false);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
+}
+
+TEST(DirectDriverLoading, ExclusiveWithMultipleNormalDriver) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+ normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 55, true);
+ normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 66, true);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 77, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
+}
+
+TEST(DirectDriverLoading, ExclusiveWithDriverEnvVar) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+ normal_drivers.emplace_back(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::env_var), 4, false);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 5, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
+}
+
+TEST(DirectDriverLoading, ExclusiveWithAddDriverEnvVar) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+
+ normal_drivers.emplace_back(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::add_env_var), 6, false);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 7, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
+}
+
+TEST(DirectDriverLoading, InclusiveWithFilterSelect) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+
+ EnvVarWrapper driver_filter_select_env_var{"VK_LOADER_DRIVERS_SELECT", "normal_driver.json"};
+
+ normal_drivers.emplace_back(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 8, true);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 9, true);
+
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
+}
+
+TEST(DirectDriverLoading, ExclusiveWithFilterSelect) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+
+ EnvVarWrapper driver_filter_select_env_var{"VK_LOADER_DRIVERS_SELECT", "normal_driver.json"};
+
+ normal_drivers.emplace_back(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 10,
+ false);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 11, true);
+
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
+}
+
+TEST(DirectDriverLoading, InclusiveWithFilterDisable) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+
+ EnvVarWrapper driver_filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE", "normal_driver.json"};
+
+ normal_drivers.emplace_back(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 12,
+ false);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 13, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
+}
+
+TEST(DirectDriverLoading, ExclusiveWithFilterDisable) {
+ FrameworkEnvironment env{};
+ std::vector<DriverInfo> normal_drivers;
+ std::vector<DriverInfo> direct_drivers;
+
+ EnvVarWrapper driver_filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE", "normal_driver.json"};
+
+ normal_drivers.emplace_back(
+ TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 14,
+ false);
+ direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 15, true);
+ ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
+}
+
+// The VK_LUNARG_direct_driver_loading extension is not enabled
+TEST(DirectDriverLoading, ExtensionNotEnabled) {
+ FrameworkEnvironment env{};
+
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+
+ VkDirectDriverLoadingInfoLUNARG ddl_info{};
+ ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_info.pfnGetInstanceProcAddr = direct_driver_icd.icd_library.get_symbol("vk_icdGetInstanceProcAddr");
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = 1U;
+ ddl_list.pDrivers = &ddl_info;
+
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the "
+ "VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was "
+ "not enabled."));
+}
+
+// VkDirectDriverLoadingListLUNARG is not in the pNext chain of VkInstanceCreateInfo
+TEST(DirectDriverLoading, DriverListNotInPnextChain) {
+ FrameworkEnvironment env{};
+
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the pNext chain of "
+ "VkInstanceCreateInfo did not contain the "
+ "VkDirectDriverLoadingListLUNARG structure."));
+}
+
+// User sets the pDrivers pointer in VkDirectDriverLoadingListLUNARG to nullptr
+TEST(DirectDriverLoading, DriverListHasNullDriverPointer) {
+ FrameworkEnvironment env{};
+
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = 1U;
+ ddl_list.pDrivers = nullptr; // user forgot to set the pDrivers
+
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
+ "VkInstanceCreateInfo has a NULL pDrivers member."));
+}
+
+// User sets the driverCount in VkDirectDriverLoadingListLUNARG to zero
+TEST(DirectDriverLoading, DriverListHasZeroInfoCount) {
+ FrameworkEnvironment env{};
+
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+
+ VkDirectDriverLoadingInfoLUNARG ddl_info{};
+ ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_info.pfnGetInstanceProcAddr = direct_driver_icd.icd_library.get_symbol("vk_icdGetInstanceProcAddr");
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = 0; // user set 0 for the info list
+ ddl_list.pDrivers = &ddl_info;
+
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
+ "VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value "
+ "of zero."));
+}
+
+// pfnGetInstanceProcAddr in VkDirectDriverLoadingInfoLUNARG is nullptr
+TEST(DirectDriverLoading, DriverInfoMissingGetInstanceProcAddr) {
+ FrameworkEnvironment env{};
+
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+
+ std::array<VkDirectDriverLoadingInfoLUNARG, 2> ddl_infos{};
+ ddl_infos[0].sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_infos[0].pfnGetInstanceProcAddr = nullptr; // user didn't set the pfnGetInstanceProcAddr to the driver's handle
+
+ ddl_infos[1].sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_infos[1].pfnGetInstanceProcAddr = nullptr; // user didn't set the pfnGetInstanceProcAddr to the driver's handle
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = static_cast<uint32_t>(ddl_infos.size());
+ ddl_list.pDrivers = ddl_infos.data();
+
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 0 contains a NULL pointer for the "
+ "pfnGetInstanceProcAddr member, skipping."));
+ ASSERT_TRUE(
+ log.find("loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 1 contains a NULL pointer for the "
+ "pfnGetInstanceProcAddr member, skipping."));
+}
+
+// test the various error paths in loader_add_direct_driver
+TEST(DirectDriverLoading, DriverDoesNotExportNegotiateFunction) {
+ FrameworkEnvironment env{};
+
+ auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
+ direct_driver_icd.get_test_icd().physical_devices.push_back({});
+ direct_driver_icd.get_test_icd()
+ .set_exposes_vk_icdNegotiateLoaderICDInterfaceVersion(false)
+ .set_exposes_vkCreateInstance(false)
+ .set_exposes_vkEnumerateInstanceExtensionProperties(false);
+
+ VkDirectDriverLoadingInfoLUNARG ddl_info{};
+ ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
+ ddl_info.pfnGetInstanceProcAddr = direct_driver_icd.icd_library.get_symbol("vk_icdGetInstanceProcAddr");
+
+ VkDirectDriverLoadingListLUNARG ddl_list{};
+ ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
+ ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
+ ddl_list.driverCount = 1;
+ ddl_list.pDrivers = &ddl_info;
+
+ {
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_add_direct_driver: Could not get 'vk_icdNegotiateLoaderICDInterfaceVersion' from "
+ "VkDirectDriverLoadingInfoLUNARG structure at "
+ "index 0, skipping."));
+ }
+
+ // Allow the negotiate function to be found, now it should fail to find instance creation function
+ direct_driver_icd.get_test_icd().set_exposes_vk_icdNegotiateLoaderICDInterfaceVersion(true);
+ direct_driver_icd.get_test_icd().set_max_icd_interface_version(4);
+
+ {
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(log.find(
+ "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 0 supports interface version 4, "
+ "which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading "
+ "extension, skipping."));
+ }
+ direct_driver_icd.get_test_icd().set_max_icd_interface_version(7);
+
+ {
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
+ "VkDirectDriverLoadingInfoLUNARG structure at index 0, skipping."));
+ }
+
+ // Allow the instance creation function to be found, now it should fail to find EnumInstExtProps
+ direct_driver_icd.get_test_icd().set_exposes_vkCreateInstance(true);
+
+ {
+ DebugUtilsLogger log;
+ InstWrapper inst{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst.create_info, log);
+ log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
+ inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
+ inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
+
+ ASSERT_TRUE(
+ log.find("loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
+ "VkDirectDriverLoadingInfoLUNARG structure at index 0, skipping."));
+ }
+}