Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/Vulkan-Loader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Young <marky@lunarg.com>2022-07-26 22:35:25 +0300
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2022-11-04 23:08:39 +0300
commit38ce56b21bddf8f2a90af1471e3382b3d296cceb (patch)
treeea0e69c9e21f5e48201a8adfdd0799f21a88d4a1
parent1bc3a2fa8ec194492de622448aae2f4ad3520bd8 (diff)
Add loader enable/disable env vars
Add new environment variables that will allow the loader to filter layers and drivers in specific ways. This control should give developers ways to more quickly narrow down issues with a layer or driver. Also, it should give CI environments a mechanism to selectively enable only drivers and layers that are needed for testing. Add tests to support validating the new changes. Add documentation that describes the new changes and also create new loader debugging markdown document to help people debug issues with drivers or layers using the new filter enums. Rename the old get_environment.* source files to loader_environment.*. Then put all the environment variable helpers from loader.c into the new files.
-rw-r--r--BUILD.gn4
-rw-r--r--docs/LoaderApplicationInterface.md143
-rw-r--r--docs/LoaderDebugging.md322
-rw-r--r--docs/LoaderDriverInterface.md158
-rw-r--r--docs/LoaderInterfaceArchitecture.md217
-rw-r--r--docs/LoaderLayerInterface.md162
-rw-r--r--loader/CMakeLists.txt2
-rw-r--r--loader/get_environment.c173
-rw-r--r--loader/loader.c512
-rw-r--r--loader/loader.h19
-rw-r--r--loader/loader_common.h26
-rw-r--r--loader/loader_environment.c546
-rw-r--r--loader/loader_environment.h (renamed from loader/get_environment.h)15
-rw-r--r--loader/loader_linux.c4
-rw-r--r--loader/loader_windows.c2
-rw-r--r--loader/log.c2
-rw-r--r--loader/trampoline.c54
-rw-r--r--loader/vk_loader_platform.h15
-rw-r--r--tests/framework/test_environment.cpp25
-rw-r--r--tests/framework/test_environment.h5
-rw-r--r--tests/loader_envvar_tests.cpp354
-rw-r--r--tests/loader_layer_tests.cpp1465
-rw-r--r--tests/loader_regression_tests.cpp32
-rw-r--r--tests/loader_testing_main.cpp4
-rw-r--r--tests/loader_version_tests.cpp8
25 files changed, 3602 insertions, 667 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 77239176a..5790e753a 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -111,14 +111,14 @@ if (!is_android) {
"loader/dev_ext_trampoline.c",
"loader/extension_manual.c",
"loader/extension_manual.h",
- "loader/get_environment.c",
- "loader/get_environment.h",
"loader/generated/vk_layer_dispatch_table.h",
"loader/generated/vk_loader_extensions.h",
"loader/generated/vk_object_types.h",
"loader/gpa_helper.h",
"loader/gpa_helper.c",
"loader/loader_common.h",
+ "loader/loader_environment.c",
+ "loader/loader_environment.h",
"loader/loader.c",
"loader/loader.h",
"loader/log.c",
diff --git a/docs/LoaderApplicationInterface.md b/docs/LoaderApplicationInterface.md
index c9af0343a..6144a6656 100644
--- a/docs/LoaderApplicationInterface.md
+++ b/docs/LoaderApplicationInterface.md
@@ -7,7 +7,7 @@
# Application Interface to Loader
[![Creative Commons][3]][4]
-<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
+<!-- Copyright &copy; 2015-2022 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/
@@ -36,9 +36,6 @@
- [Forcing Layers to be Enabled on Windows, Linux and macOS](#forcing-layers-to-be-enabled-on-windows-linux-and-macos)
- [Overall Layer Ordering](#overall-layer-ordering)
- [Debugging Possible Layer Issues](#debugging-possible-layer-issues)
- - [Enable Loader Debug Layer Output](#enable-loader-debug-layer-output)
- - [Disable All Layers](#disable-all-layers)
- - [Enable More Loader Debug Output](#enable-more-loader-debug-output)
- [Application Usage of Extensions](#application-usage-of-extensions)
- [Instance and Device Extensions](#instance-and-device-extensions)
- [WSI Extensions](#wsi-extensions)
@@ -572,140 +569,10 @@ make to function.
### Debugging Possible Layer Issues
If it is possible that a layer is causing issues, there are several things that
-can be tried.
-
-
-#### Enable Loader Debug Layer Output
-
-First, enable the "layer" debug output option (`VK_LOADER_DEBUG`) in the loader,
-See the
-[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md##table-of-debug-environment-variables)
-for more info.
-
-When enabled, the loader will output information on:
- * Where it looks for implicit layers
- * Where it looks for explicit layers
- * What manifest files it finds
- * Which layer manifest files are loaded
- * What libraries are associated with a layer
- * What the layer callstack looks like for both the instance and device chain
-
-For example, the layer output for searching for implicit layers on Linux may
-look like:
-
-```
-LAYER: Searching for layer manifest files
-LAYER: In following folders:
-LAYER: /home/linust/.config/vulkan/implicit_layer.d
-LAYER: /etc/xdg/vulkan/implicit_layer.d
-LAYER: /usr/local/etc/vulkan/implicit_layer.d
-LAYER: /etc/vulkan/implicit_layer.d
-LAYER: /home/linust/.local/share/vulkan/implicit_layer.d
-LAYER: /home/linust/.local/share/flatpak/exports/share/vulkan/implicit_layer.d
-LAYER: /var/lib/flatpak/exports/share/vulkan/implicit_layer.d
-LAYER: /usr/local/share/vulkan/implicit_layer.d
-LAYER: /usr/share/vulkan/implicit_layer.d
-LAYER: Found the following files:
-LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/renderdoc_capture.json
-LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamfossilize_i386.json
-LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamfossilize_x86_64.json
-LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamoverlay_i386.json
-LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamoverlay_x86_64.json
-LAYER: /usr/share/vulkan/implicit_layer.d/nvidia_layers.json
-LAYER: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
-```
-
-In the above scenario, seven implicit layers were discovered in two different
-folders.
-Just because they were found does not mean that they will be loaded, but this
-information can be used to make sure a layer JSON file was properly discovered.
-
-When the loader actually loads a layer, the messages may look like the
-following:
-
-```
-LAYER | DEBUG: Loading layer library libVkLayer_khronos_validation.so
-LAYER | INFO: Insert instance layer VK_LAYER_KHRONOS_validation (libVkLayer_khronos_validation.so)
-LAYER | DEBUG: Loading layer library libVkLayer_MESA_device_select.so
-LAYER | INFO: Insert instance layer VK_LAYER_MESA_device_select (libVkLayer_MESA_device_select.so)
-```
-
-This information does not indicate the order the layers are used in.
-That information is displayed later showing all the callstack during both
-`vkCreateInstance` and `vkCreateDevice`.
-In the same sample above, the callstack for `vkCreateInstance` looks like the
-following:
-
-```
-LAYER: vkCreateInstance layer callstack setup to:
-LAYER: <Application>
-LAYER: ||
-LAYER: <Loader>
-LAYER: ||
-LAYER: VK_LAYER_MESA_device_select
-LAYER: Type: Implicit
-LAYER: Disable Env Var: NODEVICE_SELECT
-LAYER: Manifest: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
-LAYER: Library: libVkLayer_MESA_device_select.so
-LAYER: ||
-LAYER: VK_LAYER_KHRONOS_validation
-LAYER: Type: Explicit
-LAYER: Manifest: /usr/share/vulkan/explicit_layer.d/VkLayer_khronos_validation.json
-LAYER: Library: libVkLayer_khronos_validation.so
-LAYER: ||
-LAYER: <Drivers>
-```
-
-In this scenario, two layers were used (the same two that were loaded earlier):
-* `VK_LAYER_MESA_device_select`
-* `VK_LAYER_KHRONOS_validation`
-
-This information now shows us that the `VK_LAYER_MESA_device_select` is loaded
-first, followed by `VK_LAYER_KHRONOS_validation` which will then continue into
-any available drivers.
-It also shows that `VK_LAYER_MESA_device_select` is an implicit layer which
-implies that it wasn't directly enabled by the application.
-On the other hand, `VK_LAYER_KHRONOS_validation` is shown as an explicit layer
-which indicates that it was likely enabled by the application.
-
-Sometimes, implicit layers can cause issues with an application.
-Because of this, the next step is to try to disable one or more of the listed
-implicit layers.
-This can be done by defining the disable environment variable for that layer.
-Each layer has it's own disable environment variable as mentioned in the
-[Layer Manifest File Format](LoaderLayerInterface.md#layer-manifest-file-format).
-However, it can be difficult to find this variable in the manifest files, so
-the loader now outputs it as part of the callstack information.
-Looking at the above `vkCreateInstance` callstack output, under the
-section for `VK_LAYER_MESA_device_select` exists a section listed as
-"Disable Env Var:".
-This is the disable environment variable that can be used to disable the
-`VK_LAYER_MESA_device_select` layer from being loaded by the loader.
-In the above output, the disable environment variable is listed as
-"NODEVICE_SELECT" which can be defined to a non-zero value to cause the loader
-to ignore this layer.
-
-
-#### Disable All Layers
-
-Because implicit layers are virtually unknown to the application, it is best to
-next try to disable each one of them.
-Using the above debug output, define each environment variable to disable the
-corresponding implicit layer that was used.
-
-Once all are disabled, re-run the application again.
-
-If the failure still occurs, try disabling all explicit layers loaded by the
-application by modifying the application or using a tool such as
-[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md).
-
-
-#### Enable More Loader Debug Output
-
-If the failure continues after disabling all layers, then enable all loader
-debug warnings and errors by setting `VK_LOADER_DEBUG` to "error,warn" or
-even "all".
-This will output any other issues that the loader has encountered.
+can be tried which are documented in the
+[Debugging Possible Layer Issues](LoaderDebugging.md#debugging-possible-layer-issues)
+section of the [LoaderDebugging.mg](LoaderDebugging.md) document in the docs
+folder.
## Application Usage of Extensions
diff --git a/docs/LoaderDebugging.md b/docs/LoaderDebugging.md
new file mode 100644
index 000000000..e404fe791
--- /dev/null
+++ b/docs/LoaderDebugging.md
@@ -0,0 +1,322 @@
+<!-- markdownlint-disable MD041 -->
+[![Khronos Vulkan][1]][2]
+
+[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
+[![Creative Commons][3]][4]
+
+<!-- Copyright &copy; 2015-2022 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
+
+- [Debugging Issues](#debugging-issues)
+- [Loader Logging](#loader-logging)
+- [Debugging Possible Layer Issues](#debugging-possible-layer-issues)
+ - [Enable Layer Logging](#enable-layer-logging)
+ - [Disable Layers](#disable-layers)
+ - [Selectively Re-enable Layers](#selectively-re-enable-layers)
+- [Debugging Possible Driver Issues](#debugging-possible-driver-issues)
+ - [Enable Driver Logging](#enable-driver-logging)
+ - [Selectively Enable Specific Drivers](#selectively-enable-specific-drivers)
+
+## Debugging Issues
+
+If your application is crashing or behaving weirdly, the loader provides
+several mechanisms for you to debug the issues.
+
+**NOTE**: This functionality is all specific to the desktop Vulkan loader and
+does not work for the Android loader.
+
+## Loader Logging
+
+The Vulkan desktop loader has added logging functionality that can be enabled by
+using the `VK_LOADER_DEBUG` environment variable.
+The results will be output to the standard output, but will also be passed to
+any `VK_EXT_debug_utils` messengers present as well.
+The variable can be set to a comma-delimited list of debug level options which
+include:
+
+ * error&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report any errors encountered by
+ the loader
+ * warn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report any warnings encountered by
+ the loader
+ * info&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report info-level
+ messages generated by the loader
+ * debug&nbsp;&nbsp;&nbsp;&nbsp;Report debug-level messages generated by the
+ loader
+ * layer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report all layer-specific messages
+ generated by the loader
+ * driver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report all driver-specific messages
+ generated by the loader
+ * all&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report all
+ messages generated by the loader (includes all of the above)
+
+If you're not sure where the issue comes from, at least set it to output all
+messages through the "info" level:
+
+```
+set VK_LOADER_DEBUG=error,warn,info
+```
+
+Then, you can search the list for any errors or warnings that might provide a
+hint at why you're seeing issues.
+
+For more info on enabling loader logging, refer to the
+[Enable Loader Debug Layer Output](LoaderApplicationInterface.md#enable-loader-debug-layer-output)
+and the
+[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
+below.
+
+## Debugging Possible Layer Issues
+
+### Enable Layer Logging
+
+If you suspect a layer issue, set the loader logging to specifically output
+layer messages in addition to warnings and errors:
+
+```
+set VK_LOADER_DEBUG=error,warn,layer
+```
+
+Most important layer messages should go out with error or warning levels set,
+but this will provide more layer-specific info as well such as:
+ * What layers are found
+ * Where they were found
+ * If they are implicit, what environment variables can be used to disable them
+ * If there is any incompatibility with a given layer, this could include:
+ * The layer library file (.so/.dll) wasn't found
+ * The layer library is the wrong bit-depth for the executing application
+ (i.e. 32-bit vs 64-bit)
+ * The layer itself doesn't support the application desired version of Vulkan
+ * If any environment variables are disabling any layers
+
+For example, the output of the loader looking for implicit layers may look like
+the following:
+
+```
+LAYER: Searching for layer manifest files
+LAYER: In following folders:
+LAYER: /home/${USER}/.config/vulkan/implicit_layer.d
+LAYER: /etc/xdg/vulkan/implicit_layer.d
+LAYER: /usr/local/etc/vulkan/implicit_layer.d
+LAYER: /etc/vulkan/implicit_layer.d
+LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d
+LAYER: /home/${USER}/.local/share/flatpak/exports/share/vulkan/implicit_layer.d
+LAYER: /var/lib/flatpak/exports/share/vulkan/implicit_layer.d
+LAYER: /usr/local/share/vulkan/implicit_layer.d
+LAYER: /usr/share/vulkan/implicit_layer.d
+LAYER: Found the following files:
+LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/renderdoc_capture.json
+LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamfossilize_i386.json
+LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamfossilize_x86_64.json
+LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamoverlay_i386.json
+LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamoverlay_x86_64.json
+LAYER: /usr/share/vulkan/implicit_layer.d/nvidia_layers.json
+LAYER: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
+```
+
+Then, the loading of layer libraries is reported similar to this:
+
+```
+LAYER | DEBUG: Loading layer library libVkLayer_khronos_validation.so
+LAYER | INFO: Insert instance layer VK_LAYER_KHRONOS_validation (libVkLayer_khronos_validation.so)
+LAYER | DEBUG: Loading layer library libVkLayer_MESA_device_select.so
+LAYER | INFO: Insert instance layer VK_LAYER_MESA_device_select (libVkLayer_MESA_device_select.so)
+```
+
+Finally, when the Vulkan instance is created, you can see the full instance
+call-chain from a functional standpoint with output like this:
+
+```
+LAYER: vkCreateInstance layer callstack setup to:
+LAYER: <Application>
+LAYER: ||
+LAYER: <Loader>
+LAYER: ||
+LAYER: VK_LAYER_MESA_device_select
+LAYER: Type: Implicit
+LAYER: Disable Env Var: NODEVICE_SELECT
+LAYER: Manifest: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
+LAYER: Library: libVkLayer_MESA_device_select.so
+LAYER: ||
+LAYER: VK_LAYER_KHRONOS_validation
+LAYER: Type: Explicit
+LAYER: Manifest: /usr/share/vulkan/explicit_layer.d/VkLayer_khronos_validation.json
+LAYER: Library: libVkLayer_khronos_validation.so
+LAYER: ||
+LAYER: <Drivers>
+```
+
+In this scenario, two layers were used (the same two that were loaded earlier):
+* `VK_LAYER_MESA_device_select`
+* `VK_LAYER_KHRONOS_validation`
+
+This information now shows us that the `VK_LAYER_MESA_device_select` is loaded
+first, followed by `VK_LAYER_KHRONOS_validation` which will then continue into
+any available drivers.
+It also shows that `VK_LAYER_MESA_device_select` is an implicit layer which
+implies that it wasn't directly enabled by the application.
+On the other hand, `VK_LAYER_KHRONOS_validation` is shown as an explicit layer
+which indicates that it was likely enabled by the application.
+
+### Disable Layers
+
+Sometimes, implicit layers can cause issues with an application.
+Because of this, the next step is to try to disable one or more of the listed
+implicit layers.
+You can use the filtering environment variables
+(`VK_LOADER_LAYERS_ENABLE` and `VK_LOADER_LAYERS_DISABLE`) to selectively enable
+or disable various layers.
+If you're not sure what to do, try disabling all implicit layers manually by
+setting `VK_LOADER_LAYERS_DISABLE` to '~implicit~'.
+
+```
+ set VK_LOADER_LAYERS_DISABLE=~implicit~
+```
+
+This will disable all implicit layers and the loader will report any disabled
+layers to the logging output when layer logging is enabled in the following way:
+
+```
+WARNING | LAYER: Implicit layer "VK_LAYER_MESA_device_select" forced disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'.
+WARNING | LAYER: Implicit layer "VK_LAYER_AMD_switchable_graphics_64" forced disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'.
+WARNING | LAYER: Implicit layer "VK_LAYER_Twitch_Overlay" forced disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'.
+```
+
+### Selectively Re-enable Layers
+
+When trying to diagnose problems caused by layers, it is useful to first disable
+all layers and re-enable each layer individually.
+If the problem reappears, then it is immediately clear which layer is the source
+of the issue.
+
+For example, from the above given list of disabled layers, let’s selectively
+re-enable one:
+
+```
+set VK_LOADER_LAYERS_DISABLE=~implicit~
+set VK_LOADER_LAYERS_ENABLE=*AMD*
+```
+
+This would keep both the "VK_LAYER_MESA_device_select" and
+"VK_LAYER_Twitch_Overlay" layers disabled, while enabling the
+"VK_LAYER_AMD_switchable_graphics_64" layer.
+If everything continues to work, then the evidence seems to suggest the issue is
+likely not related to the AMD layer.
+This would lead to enabling one other layer and trying again:
+
+```
+set VK_LOADER_LAYERS_DISABLE=~implicit~
+set VK_LOADER_LAYERS_ENABLE=*AMD*,*twitch*
+```
+
+And so forth.
+
+For more info on how to use the filtering environment variables, refer to the
+[Layer Filtering](LoaderLayerInterface.md#layer-filtering) section of the
+[LoaderLayerInterface](LoaderLayerInterface.md) document.
+
+
+## Debugging Possible Driver Issues
+
+### Enable Driver Logging
+
+If you suspect a driver issue, set the loader logging to specifically output
+driver messages:
+
+```
+set VK_LOADER_DEBUG=error,warn,driver
+```
+
+Most important driver messages should go out with error or warning levels set,
+but this will provide more driver-specific info as well such as:
+ * What drivers are found
+ * Where they were found
+ * If there is any incompatibility with a given driver
+ * If any environment variables are disabling any of the drivers
+
+For example, the output of the loader looking for drivers on a Linux system may
+look like the following (NOTE: additional spaces have been removed from the
+output for easier reading):
+
+```
+DRIVER: Searching for driver manifest files
+DRIVER: In following folders:
+DRIVER: /home/$(USER)/.config/vulkan/icd.d
+DRIVER: /etc/xdg/vulkan/icd.d
+DRIVER: /etc/vulkan/icd.d
+DRIVER: /home/$(USER)/.local/share/vulkan/icd.d
+DRIVER: /home/$(USER)/.local/share/flatpak/exports/share/vulkan/icd.d
+DRIVER: /var/lib/flatpak/exports/share/vulkan/icd.d
+DRIVER: /usr/local/share/vulkan/icd.d
+DRIVER: /usr/share/vulkan/icd.d
+DRIVER: Found the following files:
+DRIVER: /usr/share/vulkan/icd.d/intel_icd.x86_64.json
+DRIVER: /usr/share/vulkan/icd.d/lvp_icd.x86_64.json
+DRIVER: /usr/share/vulkan/icd.d/radeon_icd.x86_64.json
+DRIVER: /usr/share/vulkan/icd.d/lvp_icd.i686.json
+DRIVER: /usr/share/vulkan/icd.d/radeon_icd.i686.json
+DRIVER: /usr/share/vulkan/icd.d/intel_icd.i686.json
+DRIVER: /usr/share/vulkan/icd.d/nvidia_icd.json
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/intel_icd.x86_64.json, version "1.0.0"
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/lvp_icd.x86_64.json, version "1.0.0"
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/radeon_icd.x86_64.json, version "1.0.0"
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/lvp_icd.i686.json, version "1.0.0"
+DRIVER: Requested driver /usr/lib/libvulkan_lvp.so was wrong bit-type. Ignoring this JSON
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/radeon_icd.i686.json, version "1.0.0"
+DRIVER: Requested driver /usr/lib/libvulkan_radeon.so was wrong bit-type. Ignoring this JSON
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/intel_icd.i686.json, version "1.0.0"
+DRIVER: Requested driver /usr/lib/libvulkan_intel.so was wrong bit-type. Ignoring this JSON
+DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/nvidia_icd.json, version "1.0.0"
+```
+
+Then when the application selects the device to use, you will see the Vulkan
+device call chain reported in the following way (NOTE: additional spaces have
+been removed from the output for easier reading):
+
+```
+DRIVER: vkCreateDevice layer callstack setup to:
+DRIVER: <Application>
+DRIVER: ||
+DRIVER: <Loader>
+DRIVER: ||
+DRIVER: <Device>
+DRIVER: Using "Intel(R) UHD Graphics 630 (CFL GT2)" with driver: "/usr/lib64/libvulkan_intel.so"
+```
+
+
+### Selectively Enable Specific Drivers
+
+You can now use the filtering environment variables
+(`VK_LOADER_DRIVERS_SELECT` and `VK_LOADER_DRIVERS_DISABLE`) to selectively
+select or disable various drivers.
+Remember, that to disable drivers, you must use the name of the Driver JSON to
+disable since the drivers do not reveal a name until much later in the Vulkan
+initialization process.
+
+So to disable all drivers except Nvidia you could do the following:
+
+```
+set VK_LOADER_DRIVERS_DISABLE=*
+set VK_LOADER_DRIVERS_SELECT=*nvidia*
+```
+
+The loader outputs messages like the following when the environment variables
+are used:
+
+```
+WARNING | DRIVER: Driver "intel_icd.x86_64.json" ignored because not selected by env var 'VK_LOADER_DRIVERS_SELECT'
+WARNING | DRIVER: Driver "radeon_icd.x86_64.json" ignored because it was disabled by env var 'VK_LOADER_DRIVERS_DISABLE'
+```
+
+These can be used to make sure that the appropriate drivers are enabled/disabled
+properly.
+
+For more info on how to use the filtering environment variables, refer to the
+[Driver Filtering](LoaderDriverInterface.md#driver-filtering) section of the
+[LoaderDriverInterface](LoaderDriverInterface.md) document.
+
diff --git a/docs/LoaderDriverInterface.md b/docs/LoaderDriverInterface.md
index 40430fbd8..e82d7ab68 100644
--- a/docs/LoaderDriverInterface.md
+++ b/docs/LoaderDriverInterface.md
@@ -7,7 +7,7 @@
# Driver interface to the Vulkan Loader
[![Creative Commons][3]][4]
-<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
+<!-- Copyright &copy; 2015-2022 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/
@@ -19,7 +19,12 @@
- [Driver Discovery](#driver-discovery)
- [Overriding the Default Driver Discovery](#overriding-the-default-driver-discovery)
- [Additional Driver Discovery](#additional-driver-discovery)
- - [Exception for Elevated Privileges](#exception-for-elevated-privileges)
+ - [Driver Filtering](#driver-filtering)
+ - [Comma-delimited lists](#comma-delimited-lists)
+ - [Globs](#globs)
+ - [Case-insensitive](#case-insensitive)
+ - [Environment Variable Priority](#environment-variable-priority)
+ - [Exception for Elevated Privileges](#exception-for-elevated-privileges)
- [Examples](#examples)
- [On Windows](#on-windows)
- [On Linux](#on-linux)
@@ -126,7 +131,8 @@ There may be times that a developer wishes to force the loader to use a specific
Driver in addition to the standard drivers (without replacing the standard
search paths.
The `VK_ADD_DRIVER_FILES` environment variable can be used to add a list of
-Driver Manifest files, containing the full path to the driver JSON Manifest file.
+Driver Manifest files, containing the full path to the driver JSON Manifest
+file.
This list is colon-separated on Linux and macOS, and semicolon-separated on
Windows.
It will be added prior to the standard driver search files.
@@ -134,11 +140,94 @@ If `VK_DRIVER_FILES` or `VK_ICD_FILENAMES` is present, then
`VK_ADD_DRIVER_FILES` will not be used by the loader and any values will be
ignored.
-#### Exception for Elevated Privileges
+### Driver Filtering
-For security reasons, `VK_ICD_FILENAMES`, `VK_DRIVER_FILES` and
-`VK_ADD_DRIVER_FILES` are all ignored if running the Vulkan application with
-elevated privileges.
+The driver select environment variable `VK_LOADER_DRIVERS_SELECT` is a
+comma-delimited list of globs to search for in known drivers.
+Since drivers don’t have a name like layers, this substring is used to compare
+against the manifest filename.
+Known driver manifests are those files that are already found by the loader
+taking into account default search paths and other environment variables (like
+`VK_ICD_FILENAMES` or `VK_ADD_DRIVER_FILES`).
+
+When a driver is disabled using the `VK_LOADER_DRIVERS_SELECT` filter, and
+loader logging is set to emit either warnings or driver messages, then a message
+will show for each driver that has been ignored.
+This message will look like the following:
+
+```
+WARNING | DRIVER: Driver "intel_icd.x86_64.json" ignored because not selected by env var 'VK_LOADER_DRIVERS_SELECT'
+```
+
+If no drivers are found with a manifest filename that matches any of the
+provided globs, then no driver is enabled and it can result in Vulkan
+applications failing to run properly.
+
+The driver disable environment variable `VK_LOADER_DRIVERS_DISABLE` is a
+comma-delimited list of globs to search for in known drivers.
+Since drivers don’t have a name like layers, this substring is used to compare
+against the manifest filename.
+Known driver manifests are those files that are already found by the loader
+taking into account default search paths and other environment variables
+(like `VK_ICD_FILENAMES` or `VK_ADD_DRIVER_FILES`).
+
+When a driver is disabled using the `VK_LOADER_DRIVERS_DISABLE` filter, and
+loader logging is set to emit either warnings or driver messages, then a message
+will show for each driver that has been forcibly disabled.
+This message will look like the following:
+
+```
+WARNING | DRIVER: Driver "radeon_icd.x86_64.json" ignored because it was disabled by env var 'VK_LOADER_DRIVERS_DISABLE'
+```
+
+If no drivers are found with a manifest filename that matches any of the
+provided globs, then no driver is disabled.
+
+#### Comma-delimited lists
+
+All of the filter environment variables accept comma-delimited input.
+Therefore, you can chain multiple strings together and it will use the strings
+to individually enable or disable the appropriate item in the current list of
+available items.
+
+#### Globs
+
+To provide enough flexibility to limit driver name searches to only those
+desired by the developer, the loader uses a limited glob format for strings.
+Acceptable globs are:
+ - Prefixes: `"string*"`
+ - Suffixes: `"*string"`
+ - Substrings: `"*string*"`
+ - Whole strings: `"string"`
+
+This is especially important because it is difficult sometimes to determine the
+full name of a driver manifest file.
+So, instead of having to type in `intel_icd.x86_64.json` to select only the
+Intel driver on Linux, the substring `*intel*` can be used in the
+`VK_LOADER_DRIVER_SELECT` environment variable.
+
+#### Case-insensitive
+
+All of the filter environment variables assume the strings inside of the glob
+are not case-sensitive.
+Therefore, “Bob”, “bob”, and “BOB” all amount to the same thing.
+
+#### Environment Variable Priority
+
+The values from the disable environment variable will be considered
+<b>before</b> the select environment variable.
+Because of this, it is possible to disable a driver using the disable
+environment variable, only to have it be re-enabled by the enable environment
+variable.
+
+
+### Exception for Elevated Privileges
+
+For security reasons, `VK_ICD_FILENAMES`, `VK_DRIVER_FILES`, and
+`VK_ADD_DRIVER_FILES` are all ignored if running the Vulkan application
+with elevated privileges.
+This is because they may insert new libraries into the executable process that
+are not normally found by the loader.
Because of this, these environment variables can only be used for applications
that do not use elevated privileges.
@@ -292,9 +381,10 @@ middle.
This is because the value of 1 for vendor_b_vk.json disables the driver.
Additionally, the Vulkan loader will scan the system for well-known Windows
-AppX/MSIX packages. If a package is found, the loader will scan the root directory
-of this installed package for JSON manifest files. At this time, the only package
-that is known is Microsoft's
+AppX/MSIX packages.
+If a package is found, the loader will scan the root directory of this installed
+package for JSON manifest files. At this time, the only package that is known is
+Microsoft's
[OpenCL™ and OpenGL® Compatibility Pack](https://apps.microsoft.com/store/detail/9NQPSL29BFFF?hl=en-us&gl=US).
The Vulkan loader will open each enabled manifest file found to obtain the name
@@ -510,7 +600,8 @@ The loader will load the driver via `hw_get_module` with the ID of "vulkan".
## Driver Manifest File Format
-The following section discusses the details of the Driver Manifest JSON file format.
+The following section discusses the details of the Driver Manifest JSON file
+format.
The JSON file itself does not have any requirements for naming.
The only requirement is that the extension suffix of the file is ".json".
@@ -569,18 +660,18 @@ Here is an example driver JSON Manifest file:
<td>"api_version" </td>
<td>The major.minor.patch version number of the maximum Vulkan API supported
by the driver.
- However, just because the driver supports the specific Vulkan API version,
- it does not guarantee that the hardware on a user's system can support
- that version.
+ However, just because the driver supports the specific Vulkan API
+ version, it does not guarantee that the hardware on a user's system can
+ support that version.
Information on what the underlying physical device can support must be
- queried by the user using the <i>vkGetPhysicalDeviceProperties</i> API call.
- <br/>
+ queried by the user using the <i>vkGetPhysicalDeviceProperties</i> API
+ call.<br/>
For example: 1.0.33.</td>
</tr>
<tr>
<td>"is_portability_driver" </td>
- <td>Defines whether the driver contains any VkPhysicalDevices which implement
- the VK_KHR_portability_subset extension.<br/>
+ <td>Defines whether the driver contains any VkPhysicalDevices which
+ implement the VK_KHR_portability_subset extension.<br/>
</td>
</tr>
</table>
@@ -762,13 +853,13 @@ In this way, it compares "pName" to every physical device function supported in
the driver.
Implementations of the function should have the following behavior:
-* If `pName` is the name of a Vulkan API entrypoint that takes a `VkPhysicalDevice`
- as its primary dispatch handle, and the driver supports the entrypoint, then
- the driver **must** return the valid function pointer to the driver's
- implementation of that entrypoint.
-* If `pName` is the name of a Vulkan API entrypoint that takes something other than
- a `VkPhysicalDevice` as its primary dispatch handle, then the driver **must**
- return `NULL`.
+* If `pName` is the name of a Vulkan API entrypoint that takes a
+ `VkPhysicalDevice` as its primary dispatch handle, and the driver supports the
+ entrypoint, then the driver **must** return the valid function pointer to the
+ driver's implementation of that entrypoint.
+* If `pName` is the name of a Vulkan API entrypoint that takes something other
+ than a `VkPhysicalDevice` as its primary dispatch handle, then the driver
+ **must** return `NULL`.
* If the driver is unaware of any entrypoint with the name `pName`, it **must**
return `NULL`.
@@ -1257,12 +1348,13 @@ manifest files used by the Windows, Linux and macOS loaders.
The loader implements the `VK_KHR_portability_enumeration` instance extension,
which filters out any drivers that report support for the portability subset
device extension. Unless the application explicitly requests enumeration of
-portability devices by setting the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR
-bit in the VkInstanceCreateInfo::flags, the loader does not load any drivers
-that declare themselves to be portability drivers.
+portability devices by setting the
+`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the
+VkInstanceCreateInfo::flags, the loader does not load any drivers that declare
+themselves to be portability drivers.
-Drivers declare whether they are portability drivers or not in the Driver Manifest
-Json file, with the `is_portability_driver` boolean field.
+Drivers declare whether they are portability drivers or not in the Driver
+Manifest Json file, with the `is_portability_driver` boolean field.
[More information here](#driver-manifest-file-version-101)
The initial support for this extension only reported errors when an application
@@ -1404,7 +1496,8 @@ Android Vulkan documentation</a>.
</tr>
<tr>
<td><small><b>LDP_DRIVER_6</b></small></td>
- <td>Removed - See <a href="#removed-driver-policies">Removed Driver Policies</a>
+ <td>Removed - See
+ <a href="#removed-driver-policies">Removed Driver Policies</a>
</td>
<td>-</td>
<td>-</td>
@@ -1515,7 +1608,8 @@ Android Vulkan documentation</a>.
#### Removed Driver Policies
-These policies were in the loader source at some point but later removed. They are documented here for reference.
+These policies were in the loader source at some point but later removed.
+They are documented here for reference.
<table>
<tr>
diff --git a/docs/LoaderInterfaceArchitecture.md b/docs/LoaderInterfaceArchitecture.md
index 66d38e658..22b4518fb 100644
--- a/docs/LoaderInterfaceArchitecture.md
+++ b/docs/LoaderInterfaceArchitecture.md
@@ -7,7 +7,7 @@
# Architecture of the Vulkan Loader Interfaces
[![Creative Commons][3]][4]
-<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
+<!-- Copyright &copy; 2015-2022 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/
@@ -38,6 +38,7 @@
- [Application Interface to the Loader](#application-interface-to-the-loader)
- [Layer Interface with the Loader](#layer-interface-with-the-loader)
- [Driver Interface With the Loader](#driver-interface-with-the-loader)
+- [Debugging Issues](#debugging-issues)
- [Loader Policies](#loader-policies)
- [Table of Debug Environment Variables](#table-of-debug-environment-variables)
- [Glossary of Terms](#glossary-of-terms)
@@ -458,6 +459,17 @@ directory as this file.
<br/>
+## Debugging Issues
+
+
+If your application is crashing or behaving weirdly, the loader provides
+several mechanisms for you to debug the issues.
+These are detailed in the [LoaderDebugging.md](LoaderDebugging.md) document
+found in the same directory as this file.
+<br/>
+<br/>
+
+
## Loader Policies
Loader policies with regards to the loader interaction with drivers and layers
@@ -582,46 +594,51 @@ discovery.
</tr>
<tr>
<td><small>
- <i>VK_INSTANCE_LAYERS</i>
- </small></td>
+ <i>VK_LAYER_PATH</i></small></td>
<td><small>
- Force the loader to add the given layers to the list of Enabled layers
- normally passed into <b>vkCreateInstance</b>.
- These layers are added first, and the loader will remove any duplicate
- layers that appear in both this list as well as that passed into
- <i>ppEnabledLayerNames</i>.
+ Override the loader's standard Layer library search folders and use the
+ provided delimited folders to search for explicit layer manifest files.
</small></td>
<td><small>
- None
+ <a href="#elevated-privilege-caveats">
+ Ignored when running Vulkan application with elevated privileges.
+ </a>
</small></td>
<td><small>
export<br/>
- &nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;:&lt;layer_b&gt;<br/><br/>
+ &nbsp;&nbsp;VK_LAYER_PATH=<br/>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;path_a&gt;:&lt;path_b&gt;<br/><br/>
set<br/>
- &nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;;&lt;layer_b&gt;
+ &nbsp;&nbsp;VK_LAYER_PATH=<br/>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;path_a&gt;;&lt;path_b&gt;
</small></td>
</tr>
<tr>
<td><small>
- <i>VK_LAYER_PATH</i></small></td>
+ <i>VK_LOADER_DEBUG</i>
+ </small></td>
<td><small>
- Override the loader's standard Layer library search folders and use the
- provided delimited folders to search for explicit layer manifest files.
+ Enable loader debug messages using a comma-delimited list of level
+ options. These options are:<br/>
+ &nbsp;&nbsp;* error (only errors)<br/>
+ &nbsp;&nbsp;* warn (only warnings)<br/>
+ &nbsp;&nbsp;* info (only info)<br/>
+ &nbsp;&nbsp;* debug (only debug)<br/>
+ &nbsp;&nbsp;* layer (layer-specific output)<br/>
+ &nbsp;&nbsp;* driver (driver-specific output)<br/>
+ &nbsp;&nbsp;* all (report out all messages)<br/><br/>
+ To enable multiple options (outside of "all") like info, warning and
+ error messages, set the value to "error,warn,info".
</small></td>
<td><small>
- <a href="#elevated-privilege-caveats">
- Ignored when running Vulkan application with elevated privileges.
- </a>
+ None
</small></td>
<td><small>
export<br/>
- &nbsp;&nbsp;VK_LAYER_PATH=<br/>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;path_a&gt;:&lt;path_b&gt;<br/><br/>
+ &nbsp;&nbsp;VK_LOADER_DEBUG=all<br/>
+ <br/>
set<br/>
- &nbsp;&nbsp;VK_LAYER_PATH=<br/>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;path_a&gt;;&lt;path_b&gt;
+ &nbsp;&nbsp;VK_LOADER_DEBUG=warn
</small></td>
</tr>
<tr>
@@ -679,30 +696,124 @@ discovery.
</tr>
<tr>
<td><small>
- <i>VK_LOADER_DEBUG</i>
+ <i>VK_LOADER_DRIVERS_SELECT</i>
</small></td>
<td><small>
- Enable loader debug messages using a comma-delimited list of level
- options. These options are:<br/>
- &nbsp;&nbsp;* error (only errors)<br/>
- &nbsp;&nbsp;* warn (only warnings)<br/>
- &nbsp;&nbsp;* info (only info)<br/>
- &nbsp;&nbsp;* debug (only debug)<br/>
- &nbsp;&nbsp;* layer (layer-specific output)<br/>
- &nbsp;&nbsp;* driver (driver-specific output)<br/>
- &nbsp;&nbsp;* all (report out all messages)<br/><br/>
- To enable multiple options (outside of "all") like info, warning and
- error messages, set the value to "error,warn,info".
+ A comma-delimited list of globs to search for in known drivers and
+ used to select only the drivers whose manifest file names match one or
+ more of the provided globs.<br/>
+ Since drivers don’t have a name like layers, this glob is used to
+ compare against the manifest filename.
+ Known driver manifests being those files that are already found by the
+ loader taking into account default search paths and other environment
+ variables (like <i>VK_ICD_FILENAMES</i> or <i>VK_ADD_DRIVER_FILES</i>).
+ </small></td>
+ <td><small>
+ If no drivers are found with a manifest filename that matches any of the
+ provided globs, then no driver is enabled and it <b>may</b> result
+ in Vulkan applications failing to run properly.
+ </small></td>
+ <td><small>
+ export<br/>
+ &nbsp;&nbsp;VK_LOADER_DRIVERS_SELECT=nvidia<br/>
+ <br/>
+ set<br/>
+ &nbsp;&nbsp;VK_LOADER_DRIVERS_SELECT=nvidia<br/><br/>
+ The above would select only the Nvidia driver if it was present on the
+ system and already visible to the loader.
+ </small></td>
+ </tr>
+ <tr>
+ <td><small>
+ <i>VK_LOADER_DRIVERS_DISABLE</i>
+ </small></td>
+ <td><small>
+ A comma-delimited list of globs to search for in known drivers and
+ used to disable only the drivers whose manifest file names match one or
+ more of the provided globs.<br/>
+ Since drivers don’t have a name like layers, this glob is used to
+ compare against the manifest filename.
+ Known driver manifests being those files that are already found by the
+ loader taking into account default search paths and other environment
+ variables (like <i>VK_ICD_FILENAMES</i> or <i>VK_ADD_DRIVER_FILES</i>).
+ </small></td>
+ <td><small>
+ If all available drivers are disabled using this environment variable,
+ then no drivers will be found by the loader and <b>will</b> result
+ in Vulkan applications failing to run properly.<br/>
+ This is also checked before other driver environment variables (such as
+ <i>VK_LOADER_DRIVERS_SELECT</i>) so that a user may easily disable all
+ drivers and then selectively re-enable individual drivers using the
+ enable environment variable.
+ </small></td>
+ <td><small>
+ export<br/>
+ &nbsp;&nbsp;VK_LOADER_DRIVERS_DISABLE=*amd*,*intel*<br/>
+ <br/>
+ set<br/>
+ &nbsp;&nbsp;VK_LOADER_DRIVERS_DISABLE=*amd*,*intel*<br/><br/>
+ The above would disable both Intel and AMD drivers if both were present
+ on the system and already visible to the loader.
+ </small></td>
+ </tr>
+ <tr>
+ <td><small>
+ <i>VK_LOADER_LAYERS_ENABLE</i>
+ </small></td>
+ <td><small>
+ A comma-delimited list of globs to search for in known layers and
+ used to select only the layers whose layer name matches one or more of
+ the provided globs.<br/>
+ Known layers are those which are found by the loader taking into account
+ default search paths and other environment variables
+ (like <i>VK_LAYER_PATH</i>).
+ <br/>
+ This has replaced the older deprecated environment variable
+ <i>VK_INSTANCE_LAYERS</i>
</small></td>
<td><small>
None
</small></td>
<td><small>
export<br/>
- &nbsp;&nbsp;VK_LOADER_DEBUG=all<br/>
+ &nbsp;&nbsp;VK_LOADER_LAYERS_ENABLE=*validation,*recon*<br/>
<br/>
set<br/>
- &nbsp;&nbsp;VK_LOADER_DEBUG=warn
+ &nbsp;&nbsp;VK_LOADER_LAYERS_ENABLE=*validation,*recon*<br/><br/>
+ The above would enable the Khronos validation layer and the
+ GfxReconstruct layer, if both were present on the system and already
+ visible to the loader.
+ </small></td>
+ </tr>
+ <tr>
+ <td><small>
+ <i>VK_LOADER_LAYERS_DISABLE</i>
+ </small></td>
+ <td><small>
+ A comma-delimited list of globs to search for in known layers and
+ used to disable only the layers whose layer name matches one or more of
+ the provided globs.<br/>
+ Known layers are those which are found by the loader taking into account
+ default search paths and other environment variables
+ (like <i>VK_LAYER_PATH</i>).
+ </small></td>
+ <td><small>
+ Disabling a layer that an application intentionally enables as an
+ explicit layer <b>may</b> cause the application to not function
+ properly.<br/>
+ This is also checked before other layer environment variables (such as
+ <i>VK_LOADER_LAYERS_ENABLE</i>) so that a user may easily disable all
+ layers and then selectively re-enable individual layers using the
+ enable environment variable.
+ </small></td>
+ <td><small>
+ export<br/>
+ &nbsp;&nbsp;VK_LOADER_LAYERS_DISABLE=*MESA*,~implicit~<br/>
+ <br/>
+ set<br/>
+ &nbsp;&nbsp;VK_LOADER_LAYERS_DISABLE=*MESA*,~implicit~<br/><br/>
+ The above would disable any Mesa layer and all other implicit layers
+ that would normally be enabled on the system.
</small></td>
</tr>
</table>
@@ -750,6 +861,34 @@ may be removed in a future loader release.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<folder_a>\nvidia.json;<folder_b>\mesa.json
</small></td>
</tr>
+ <tr>
+ <td><small>
+ <i>VK_INSTANCE_LAYERS</i>
+ </small></td>
+ <td><small>
+ Force the loader to add the given layers to the list of Enabled layers
+ normally passed into <b>vkCreateInstance</b>.
+ These layers are added first, and the loader will remove any duplicate
+ layers that appear in both this list as well as that passed into
+ <i>ppEnabledLayerNames</i>.
+ </small></td>
+ <td><small>
+ This has been deprecated by <i>VK_LOADER_LAYERS_ENABLE</i>.
+ It also overrides any layers disabled with
+ <i>VK_LOADER_LAYERS_DISABLE</i>.
+ </small></td>
+ <td><small>
+ None
+ </small></td>
+ <td><small>
+ export<br/>
+ &nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;;&lt;layer_b&gt;<br/><br/>
+ set<br/>
+ &nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;;&lt;layer_b&gt;
+ </small></td>
+ </tr>
</table>
<br/>
<br/>
@@ -814,8 +953,8 @@ may be removed in a future loader release.
<td>Discovery</td>
<td>The process of the loader searching for driver and layer files to set up
the internal list of Vulkan objects available.<br/>
- On <i>Windows/Linux/macOS</i>, the discovery process typically focuses on
- searching for Manifest files.<br/>
+ On <i>Windows/Linux/macOS</i>, the discovery process typically focuses
+ on searching for Manifest files.<br/>
On <i>Android</i>, the process focuses on searching for library files.
</td>
</tr>
diff --git a/docs/LoaderLayerInterface.md b/docs/LoaderLayerInterface.md
index bd6266a60..638e6a589 100644
--- a/docs/LoaderLayerInterface.md
+++ b/docs/LoaderLayerInterface.md
@@ -7,7 +7,7 @@
# Layer Interface to the Loader
[![Creative Commons][3]][4]
-<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
+<!-- Copyright &copy; 2015-2022 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/
@@ -25,6 +25,13 @@
- [Fuchsia Layer Discovery](#fuchsia-layer-discovery)
- [macOS Layer Discovery](#macos-layer-discovery)
- [Example macOS Implicit Layer Search Path](#example-macos-implicit-layer-search-path)
+ - [Layer Filtering](#layer-filtering)
+ - [Layer Special Case Disable](#layer-special-case-disable)
+ - [Layer Disable Warning](#layer-disable-warning)
+ - [Comma-delimited lists](#comma-delimited-lists)
+ - [Globs](#globs)
+ - [Case-insensitive](#case-insensitive)
+ - [Environment Variable Priority](#environment-variable-priority)
- [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)
@@ -412,14 +419,130 @@ following:
/usr/share/vulkan/implicit_layer.d
```
+### Layer Filtering
+
+The layer enable environment variable `VK_LOADER_LAYERS_ENABLE` is a
+comma-delimited list of globs to search for in known layers.
+Known layers are those that are already found by the loader taking into account
+default search paths and other environment variables (like
+`VK_LAYER_PATH` or `VK_ADD_LAYER_PATH`).
+The layer names are compared against the globs listed in the environment
+variable, and if they match, they will automatically be added to the enabled
+layer list in the loader for each application.
+These layers are enabled after implicit layers but before other explicit layers.
+
+When a layer is enabled using the `VK_LOADER_LAYERS_ENABLE` filter, and
+loader logging is set to emit either warnings or layer messages, then a message
+will show for each layer that has been forced on.
+This message will look like the following:
+
+```
+WARNING | LAYER: Layer "VK_LAYER_LUNARG_wrap_objects" force enabled due to env var 'VK_LOADER_LAYERS_ENABLE'
+```
+
+The layer disable environment variable `VK_LOADER_LAYERS_DISABLE` is a
+comma-delimited list of globs to search for in known layers.
+Known layers are those that are already found by the loader taking into account
+default search paths and other environment variables
+(like `VK_LAYER_PATH` or `VK_ADD_LAYER_PATH`).
+The layer names are compared against the globs listed in the environment
+variable, and if they match, they will automatically be disabled (whether or not
+the layer is Implicit or Explicit).
+This means that they will not be added to the enabled layer list in the loader
+for each application.
+This could mean that layers requested by an application are also not enabled
+such as `VK_KHRONOS_LAYER_synchronization2` which could cause some applications
+to misbehave.
+
+When a layer is disabled using the `VK_LOADER_LAYERS_DISABLE` filter, and
+loader logging is set to emit either warnings or layer messages, then a message
+will show for each layer that has been forcibly disabled.
+This message will look like the following:
+
+```
+WARNING | LAYER: Layer "VK_LAYER_LUNARG_wrap_objects" disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'
+```
+
+#### Layer Special Case Disable
+
+Because there are different types of layers, there are 3 additional special
+disable options available when using the `VK_LOADER_LAYERS_DISABLE` environment
+variable.
+
+These are:
+
+ * `~all~`
+ * `~implicit~`
+ * `~explicit~`
+
+`~all~` will effectively disable every layer.
+This enables a developer to disable all layers on the system.
+`~implicit~` will effectively disable every implicit layer (leaving explicit
+layers still present in the application call chain).
+`~explicit~` will effectively disable every explicit layer (leaving implicit
+layers still present in the application call chain).
+
+#### Layer Disable Warning
+
+Disabling layers, whether just through normal usage of
+`VK_LOADER_LAYERS_DISABLE` or by evoking one of the special disable options like
+`~all~` or `~explicit~` could cause application breakage if the application is
+relying on features provided by one or more explicit layers.
+
+#### Comma-delimited lists
+
+All of the filter environment variables accept comma-delimited input.
+Therefore, you can chain multiple strings together and it will use the strings
+to individually enable or disable the appropriate item in the current list of
+available items.
+
+#### Globs
+
+To provide enough flexibility to limit layer name searches to only those
+desired by the developer, the loader uses a limited glob format for strings.
+Acceptable globs are:
+ - Prefixes: `"string*"`
+ - Suffixes: `"*string"`
+ - Substrings: `"*string*"`
+ - Whole strings: `"string"`
+
+This is especially important because it is difficult sometimes to determine the
+full name of a driver manifest file.
+So, instead of having to type in `VK_LAYER_KHRONOS_validation` into the older
+`VK_INSTANCE_LAYERS` environment variable to force on validation, the substring
+`*validation` can be used in the `VK_LOADER_LAYER_ENABLE` environment variable.
+
+#### Case-insensitive
+
+All of the filter environment variables assume the strings inside of the glob
+are not case-sensitive.
+Therefore, “Bob”, “bob”, and “BOB” all amount to the same thing.
+
+#### Environment Variable Priority
+
+The values from the disable environment variable will be considered
+<b>before</b> the enable environment variable.
+Because of this, it is possible to disable a layer using the disable environment
+variable, only to have it be re-enabled by the enable environment variable.
+This is useful if you disable all layers with the intent of only enabling a
+smaller subset of specific layers for issue triaging.
+
+##### VK_INSTANCE_LAYERS
+
+The original `VK_INSTANCE_LAYERS` can be viewed as a special case of the new
+`VK_LOADER_LAYERS_ENABLE`.
+Because of this, any layers enabled via `VK_INSTANCE_LAYERS` will be treated the
+same as layers enabled with `VK_LOADER_LAYERS_ENABLE` and will therefore
+override any disables supplied in `VK_LOADER_LAYERS_DISABLE`.
+
### Exception for Elevated Privileges
-There is an exception to when either `VK_LAYER_PATH` or `VK_ADD_LAYER_PATH` are
-available for use.
-For security reasons, both `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` are ignored
-if running the Vulkan application with elevated privileges.
-Because of this, both `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` can only be used
-for applications that do not use elevated privileges.
+For security reasons, `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` are ignored if
+running the Vulkan application with elevated privileges.
+This is because they may insert new libraries into the executable process that
+are not normally found by the loader.
+Because of this, these environment variables can only be used for applications
+that do not use elevated privileges.
For more information see
[Elevated Privilege Caveats](LoaderInterfaceArchitecture.md#elevated-privilege-caveats)
@@ -630,7 +753,8 @@ chain_info->u.pLayerInfo->pfnNextGetPhysicalDeviceProcAddr
`vk_layerGetPhysicalDeviceProcAddr`.
If a layer intends to support functions that take VkPhysicalDevice as the
-dispatchable parameter, then layer should support `vk_layerGetPhysicalDeviceProcAddr`.
+dispatchable parameter, then layer should support
+`vk_layerGetPhysicalDeviceProcAddr`.
This is because if these functions aren't known to the loader, such as those
from unreleased extensions or because the loader is an older build thus doesn't
know about them _yet_, the loader won't be able to distinguish whether this is
@@ -658,8 +782,8 @@ function, and set up a generic terminator which will pass it to the proper
driver.
4. Call down using `GetInstanceProcAddr`
- If it returns non-NULL, treat it as an unknown logical device command.
-This means setting up a generic trampoline function that takes in a `VkDevice` as
-the first parameter and adjusting the dispatch table to call the
+This means setting up a generic trampoline function that takes in a `VkDevice`
+as the first parameter and adjusting the dispatch table to call the
driver/layer's function after getting the dispatch table from the `VkDevice`.
Then, return the pointer to corresponding trampoline function.
5. Return NULL
@@ -714,7 +838,8 @@ function.
corresponding Vulkan function in the next entity.
* The common behavior for a layer is to intercept a call, perform some
behavior, then pass it down to the next entity.
- * If a layer doesn't pass the information down, undefined behavior may occur.
+ * If a layer doesn't pass the information down, undefined behavior may
+ occur.
* This is because the function will not be received by layers further
down the chain, or any drivers.
* One function that **must never call down the chain** is:
@@ -1083,8 +1208,8 @@ Please refer to that documentation for more information.
Vulkan includes a small number of functions which are called without any
dispatchable object.
-<b>Most layers do not intercept these functions</b>, as layers are enabled when an
-instance is created.
+<b>Most layers do not intercept these functions</b>, as layers are enabled when
+an instance is created.
However, under certain conditions it is possible for a layer to intercept
these functions.
@@ -1411,7 +1536,8 @@ are in the blacklist will not be enabled.
* The `app_keys` member of the override meta layer will make a meta layer apply
to only applications found in this list.
-If there are any items in the app keys list, the meta layer isn't enabled for any application except those found in the list.
+If there are any items in the app keys list, the meta layer isn't enabled for
+any application except those found in the list.
* The `override_paths` member of the override meta layer, if present, will
replace the search paths the loader uses to find component layers.
@@ -1539,7 +1665,7 @@ Here's an example of a meta-layer manifest file:
supports.
It does not require the application to make use of that API version.
It simply is an indication that the layer can support Vulkan API
- instance and device functions up to and including that API version. </br>
+ instance and device functions up to and including that API version.</br>
For example: 1.0.33.
</td>
<td>None</td>
@@ -1837,8 +1963,8 @@ loader needs to query using OS-specific calls.
- NOTE: This is an optional field and, as the two previous fields, only
needed if the layer requires changing the name of the function for some reason.
-The layer manifest file does not need to to be updated if the names of any listed
-functions has not changed.
+The layer manifest file does not need to to be updated if the names of any
+listed functions has not changed.
#### Layer Manifest File Version 1.0.1
@@ -1878,7 +2004,7 @@ The following sections detail the differences between the various versions.
### Layer Interface Version 2
Introduced the concept of
-[loader and layer interface](#layer-version-negotiation) using the new
+[loader and layer interface](#layer-version-negotiation) using the
`vkNegotiateLoaderLayerInterfaceVersion` function.
Additionally, it introduced the concept of
[Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-extensions)
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index 62f8e2c40..c542c756d 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -106,7 +106,7 @@ set(NORMAL_LOADER_SRCS
cJSON.c
debug_utils.c
extension_manual.c
- get_environment.c
+ loader_environment.c
gpa_helper.c
loader.c
log.c
diff --git a/loader/get_environment.c b/loader/get_environment.c
deleted file mode 100644
index 41ed61f66..000000000
--- a/loader/get_environment.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- *
- * Copyright (c) 2014-2021 The Khronos Group Inc.
- * Copyright (c) 2014-2021 Valve Corporation
- * Copyright (c) 2014-2021 LunarG, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Author: Jon Ashburn <jon@lunarg.com>
- * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
- * Author: Chia-I Wu <olvaffe@gmail.com>
- * Author: Chia-I Wu <olv@lunarg.com>
- * Author: Mark Lobodzinski <mark@LunarG.com>
- * Author: Lenny Komow <lenny@lunarg.com>
- * Author: Charles Giessen <charles@lunarg.com>
- *
- */
-
-#include "get_environment.h"
-
-#include "allocation.h"
-#include "log.h"
-
-// Environment variables
-#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-
-bool is_high_integrity() { return geteuid() != getuid() || getegid() != getgid(); }
-
-char *loader_getenv(const char *name, const struct loader_instance *inst) {
- // No allocation of memory necessary for Linux, but we should at least touch
- // the inst pointer to get rid of compiler warnings.
- (void)inst;
- return getenv(name);
-}
-
-char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
-#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
- // Apple does not appear to have a secure getenv implementation.
- // The main difference between secure getenv and getenv is that secure getenv
- // returns NULL if the process is being run with elevated privileges by a normal user.
- // The idea is to prevent the reading of malicious environment variables by a process
- // that can do damage.
- // This algorithm is derived from glibc code that sets an internal
- // variable (__libc_enable_secure) if the process is running under setuid or setgid.
- return is_high_integrity() ? NULL : loader_getenv(name, inst);
-#elif defined(__Fuchsia__)
- return loader_getenv(name, inst);
-#else
- // Linux
- char *out;
-#if defined(HAVE_SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
- (void)inst;
- out = secure_getenv(name);
-#elif defined(HAVE___SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
- (void)inst;
- out = __secure_getenv(name);
-#else
- out = loader_getenv(name, inst);
-#if !defined(USE_UNSAFE_FILE_SEARCH)
- loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
-#endif
-#endif
- return out;
-#endif
-}
-
-void loader_free_getenv(char *val, const struct loader_instance *inst) {
- // No freeing of memory necessary for Linux, but we should at least touch
- // the val and inst pointers to get rid of compiler warnings.
- (void)val;
- (void)inst;
-}
-
-#elif defined(WIN32)
-
-bool is_high_integrity() {
- HANDLE process_token;
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
- // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
- uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)];
- DWORD buffer_size;
- if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer),
- &buffer_size) != 0) {
- const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer;
- const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
- const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1);
-
- CloseHandle(process_token);
- return integrity_level > SECURITY_MANDATORY_MEDIUM_RID;
- }
-
- CloseHandle(process_token);
- }
-
- return false;
-}
-
-char *loader_getenv(const char *name, const struct loader_instance *inst) {
- int name_utf16_size = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
- if (name_utf16_size <= 0) {
- return NULL;
- }
- wchar_t *name_utf16 = (wchar_t *)loader_stack_alloc(name_utf16_size * sizeof(wchar_t));
- if (MultiByteToWideChar(CP_UTF8, 0, name, -1, name_utf16, name_utf16_size) != name_utf16_size) {
- return NULL;
- }
-
- DWORD val_size = GetEnvironmentVariableW(name_utf16, NULL, 0);
- // val_size DOES include the null terminator, so for any set variable
- // will always be at least 1. If it's 0, the variable wasn't set.
- if (val_size == 0) {
- return NULL;
- }
-
- wchar_t *val = (wchar_t *)loader_stack_alloc(val_size * sizeof(wchar_t));
- if (GetEnvironmentVariableW(name_utf16, val, val_size) != val_size - 1) {
- return NULL;
- }
-
- int val_utf8_size = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0, NULL, NULL);
- if (val_utf8_size <= 0) {
- return NULL;
- }
- char *val_utf8 = (char *)loader_instance_heap_alloc(inst, val_utf8_size * sizeof(char), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (val_utf8 == NULL) {
- return NULL;
- }
- if (WideCharToMultiByte(CP_UTF8, 0, val, -1, val_utf8, val_utf8_size, NULL, NULL) != val_utf8_size) {
- loader_instance_heap_free(inst, val_utf8);
- return NULL;
- }
- return val_utf8;
-}
-
-char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
-#if !defined(USE_UNSAFE_FILE_SEARCH)
- if (is_high_integrity()) {
- loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
- "Loader is running with elevated permissions. Environment variable %s will be ignored", name);
- return NULL;
- }
-#endif
-
- return loader_getenv(name, inst);
-}
-
-void loader_free_getenv(char *val, const struct loader_instance *inst) { loader_instance_heap_free(inst, (void *)val); }
-
-#else
-
-char *loader_getenv(const char *name, const struct loader_instance *inst) {
- // stub func
- (void)inst;
- (void)name;
- return NULL;
-}
-void loader_free_getenv(char *val, const struct loader_instance *inst) {
- // stub func
- (void)val;
- (void)inst;
-}
-
-#endif
diff --git a/loader/loader.c b/loader/loader.c
index f7159e181..2a8b8e593 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -28,6 +28,7 @@
#include "loader.h"
+#include <ctype.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@@ -51,7 +52,7 @@
#include "allocation.h"
#include "cJSON.h"
#include "debug_utils.h"
-#include "get_environment.h"
+#include "loader_environment.h"
#include "gpa_helper.h"
#include "log.h"
#include "unknown_function_handling.h"
@@ -767,10 +768,10 @@ VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct l
return VK_SUCCESS;
}
-// Prototypes needed.
-bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
- struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
- const struct loader_layer_list *source_list);
+bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ const struct loader_layer_properties *prop, struct loader_layer_list *target_list,
+ struct loader_layer_list *expanded_target_list, const struct loader_layer_list *source_list);
// Manage lists of VkLayerProperties
static bool loader_init_layer_list(const struct loader_instance *inst, struct loader_layer_list *list) {
@@ -846,7 +847,9 @@ VkResult loader_add_layer_properties_to_list(const struct loader_instance *inst,
// Search the given search_list for any layers in the props list. Add these to the
// output layer_list.
-static VkResult loader_add_layer_names_to_list(const struct loader_instance *inst, struct loader_layer_list *output_list,
+static VkResult loader_add_layer_names_to_list(const struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ struct loader_layer_list *output_list,
struct loader_layer_list *expanded_output_list, uint32_t name_count,
const char *const *names, const struct loader_layer_list *source_list) {
struct loader_layer_properties *layer_prop;
@@ -854,14 +857,32 @@ static VkResult loader_add_layer_names_to_list(const struct loader_instance *ins
for (uint32_t i = 0; i < name_count; i++) {
const char *source_name = names[i];
+
layer_prop = loader_find_layer_property(source_name, source_list);
if (NULL == layer_prop) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_add_layer_names_to_list: Unable to find layer %s", source_name);
+ "loader_add_layer_names_to_list: Unable to find layer \"%s\"", source_name);
err = VK_ERROR_LAYER_NOT_PRESENT;
continue;
}
+ bool disabled = false;
+ bool is_implicit = (0 == (layer_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
+ if (NULL != disable_filter) {
+ if (disable_filter->disable_all || (is_implicit && disable_filter->disable_all_implicit) ||
+ (!is_implicit && disable_filter->disable_all_explicit) ||
+ check_name_matches_filter_environment_var(inst, source_name, &disable_filter->additional_filters)) {
+ disabled = true;
+ }
+ }
+
+ if (disabled && (NULL == enable_filter || !check_name_matches_filter_environment_var(inst, source_name, enable_filter))) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "Layer \"%s\" disabled because name matches filter of env var \'%s\'", source_name,
+ VK_LAYERS_DISABLE_ENV_VAR);
+ continue;
+ }
+
// Make sure the layer isn't already in the output_list, skip adding it if it is.
if (loader_find_layer_name_in_list(source_name, output_list)) {
continue;
@@ -872,7 +893,7 @@ static VkResult loader_add_layer_names_to_list(const struct loader_instance *ins
loader_add_layer_properties_to_list(inst, output_list, 1, layer_prop);
loader_add_layer_properties_to_list(inst, expanded_output_list, 1, layer_prop);
} else {
- loader_add_meta_layer(inst, layer_prop, output_list, expanded_output_list, source_list);
+ loader_add_meta_layer(inst, enable_filter, disable_filter, layer_prop, output_list, expanded_output_list, source_list);
}
}
@@ -881,22 +902,54 @@ static VkResult loader_add_layer_names_to_list(const struct loader_instance *ins
// Determine if the provided implicit layer should be enabled by querying the appropriate environmental variables.
// For an implicit layer, at least a disable environment variable is required.
-bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop) {
+bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ const struct loader_layer_properties *prop) {
bool enable = false;
+ bool forced_disabled = false;
+ bool forced_enabled = false;
char *env_value = NULL;
+ if ((NULL != disable_filter &&
+ (disable_filter->disable_all || disable_filter->disable_all_implicit ||
+ check_name_matches_filter_environment_var(inst, prop->info.layerName, &disable_filter->additional_filters)))) {
+ forced_disabled = true;
+ }
+ if (NULL != enable_filter && check_name_matches_filter_environment_var(inst, prop->info.layerName, enable_filter)) {
+ forced_enabled = true;
+ }
+
// If no enable_environment variable is specified, this implicit layer is always be enabled by default.
if (prop->enable_env_var.name[0] == 0) {
enable = true;
} else {
- // Otherwise, only enable this layer if the enable environment variable is defined
env_value = loader_getenv(prop->enable_env_var.name, inst);
if (env_value && !strcmp(prop->enable_env_var.value, env_value)) {
enable = true;
}
+
+ // Otherwise, only enable this layer if the enable environment variable is defined
loader_free_getenv(env_value, inst);
}
+ if (forced_enabled) {
+ // Only report a message that we've forced on a layer if it wouldn't have been enabled
+ // normally.
+ if (!enable) {
+ enable = true;
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "Implicit layer \"%s\" forced enabled due to env var \'%s\'.", prop->info.layerName,
+ VK_LAYERS_ENABLE_ENV_VAR);
+ }
+ } else if (enable && forced_disabled) {
+ enable = false;
+ // Report a message that we've forced off a layer if it would have been enabled normally.
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "Implicit layer \"%s\" forced disabled because name matches filter of env var \'%s\'.", prop->info.layerName,
+ VK_LAYERS_DISABLE_ENV_VAR);
+ return false;
+ }
+
// The disable_environment has priority over everything else. If it is defined, the layer is always
// disabled.
env_value = loader_getenv(prop->disable_env_var.name, inst);
@@ -930,24 +983,27 @@ bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const
// Check the individual implicit layer for the enable/disable environment variable settings. Only add it after
// every check has passed indicating it should be used.
static void loader_add_implicit_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
+ const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
const struct loader_layer_list *source_list) {
- if (loader_implicit_layer_is_enabled(inst, prop)) {
+ if (loader_implicit_layer_is_enabled(inst, enable_filter, disable_filter, prop)) {
if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
loader_add_layer_properties_to_list(inst, target_list, 1, prop);
if (NULL != expanded_target_list) {
loader_add_layer_properties_to_list(inst, expanded_target_list, 1, prop);
}
} else {
- loader_add_meta_layer(inst, prop, target_list, expanded_target_list, source_list);
+ loader_add_meta_layer(inst, enable_filter, disable_filter, prop, target_list, expanded_target_list, source_list);
}
}
}
// Add the component layers of a meta-layer to the active list of layers
-bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_layer_properties *prop,
- struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
- const struct loader_layer_list *source_list) {
+bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ const struct loader_layer_properties *prop, struct loader_layer_list *target_list,
+ struct loader_layer_list *expanded_target_list, const struct loader_layer_list *source_list) {
bool found = true;
// We need to add all the individual component layers
@@ -959,19 +1015,36 @@ bool loader_add_meta_layer(const struct loader_instance *inst, const struct load
loader_api_version search_prop_version = loader_make_version(prop->info.specVersion);
if (!loader_check_version_meets_required(meta_layer_api_version, search_prop_version)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_add_meta_layer: Meta-layer API version %u.%u, component layer %s version %u.%u, may have "
+ "Meta-layer \"%s\" API version %u.%u, component layer \"%s\" version %u.%u, may have "
"incompatibilities (Policy #LLP_LAYER_8)!",
- meta_layer_api_version.major, meta_layer_api_version.minor, search_prop->info.layerName,
- search_prop_version.major, search_prop_version.minor);
+ prop->info.layerName, meta_layer_api_version.major, meta_layer_api_version.minor,
+ search_prop->info.layerName, search_prop_version.major, search_prop_version.minor);
+ }
+
+ bool is_implicit = (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
+ bool disabled_by_type = (is_implicit) ? (NULL != disable_filter && disable_filter->disable_all_implicit)
+ : (NULL != disable_filter && disable_filter->disable_all_explicit);
+
+ if ((NULL != disable_filter && (disable_filter->disable_all || disabled_by_type ||
+ check_name_matches_filter_environment_var(inst, search_prop->info.layerName,
+ &disable_filter->additional_filters))) &&
+ (NULL == enable_filter ||
+ !check_name_matches_filter_environment_var(inst, search_prop->info.layerName, enable_filter))) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "Meta Layer \"%s\" component layer \"%s\" disabled because it matches filter in env var \'%s\'.",
+ prop->info.layerName, search_prop->info.layerName, VK_LAYERS_DISABLE_ENV_VAR);
+ continue;
}
// If the component layer is itself an implicit layer, we need to do the implicit layer enable
// checks
if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
- loader_add_implicit_layer(inst, search_prop, target_list, expanded_target_list, source_list);
+ loader_add_implicit_layer(inst, search_prop, enable_filter, disable_filter, target_list, expanded_target_list,
+ source_list);
} else {
if (0 != (search_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
- found = loader_add_meta_layer(inst, search_prop, target_list, expanded_target_list, source_list);
+ found = loader_add_meta_layer(inst, enable_filter, disable_filter, search_prop, target_list,
+ expanded_target_list, source_list);
} else {
loader_add_layer_properties_to_list(inst, target_list, 1, search_prop);
if (NULL != expanded_target_list) {
@@ -981,7 +1054,7 @@ bool loader_add_meta_layer(const struct loader_instance *inst, const struct load
}
} else {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_add_meta_layer: Failed to find layer name %s component layer %s to activate (Policy #LLP_LAYER_7)",
+ "Failed to find layer name \"%s\" component layer \"%s\" to activate (Policy #LLP_LAYER_7)",
prop->component_layer_names[comp_layer], prop->component_layer_names[comp_layer]);
found = false;
}
@@ -995,43 +1068,6 @@ bool loader_add_meta_layer(const struct loader_instance *inst, const struct load
return found;
}
-// Search the source_list for any layer with a name that matches the given name and a type
-// that matches the given type. Add all matching layers to the target_list.
-VkResult loader_add_layer_name_to_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
- const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
- struct loader_layer_list *expanded_target_list) {
- VkResult res = VK_SUCCESS;
- bool found = false;
- for (uint32_t i = 0; i < source_list->count; i++) {
- struct loader_layer_properties *source_prop = &source_list->list[i];
- if (0 == strcmp(source_prop->info.layerName, name) && (source_prop->type_flags & type_flags) == type_flags) {
- // If not a meta-layer, simply add it.
- if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
- if (VK_SUCCESS == loader_add_layer_properties_to_list(inst, target_list, 1, source_prop)) {
- found = true;
- }
- if (VK_SUCCESS == loader_add_layer_properties_to_list(inst, expanded_target_list, 1, source_prop)) {
- found = true;
- }
- } else {
- found = loader_add_meta_layer(inst, source_prop, target_list, expanded_target_list, source_list);
- }
- }
- }
- if (!found) {
- if (strcmp(name, "VK_LAYER_LUNARG_standard_validation")) {
- loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_add_layer_name_to_list: Failed to find layer name %s to activate", name);
- } else {
- res = VK_ERROR_LAYER_NOT_PRESENT;
- loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "Layer VK_LAYER_LUNARG_standard_validation has been changed to VK_LAYER_KHRONOS_validation. Please use the "
- "new version of the layer.");
- }
- }
- return res;
-}
-
static VkExtensionProperties *get_extension_property(const char *name, const struct loader_extension_list *list) {
for (uint32_t i = 0; i < list->count; i++) {
if (strcmp(name, list->list[i].extensionName) == 0) return &list->list[i];
@@ -1304,7 +1340,7 @@ static VkResult loader_scanned_icd_init(const struct loader_instance *inst, stru
static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
const char *filename, uint32_t api_version, enum loader_layer_library_status *lib_status) {
- loader_platform_dl_handle handle;
+ loader_platform_dl_handle handle = NULL;
PFN_vkCreateInstance fp_create_inst;
PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
PFN_vkGetInstanceProcAddr fp_get_proc_addr;
@@ -1372,10 +1408,10 @@ static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struc
}
fp_get_inst_ext_props = loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties");
if (NULL == fp_get_inst_ext_props) {
- loader_log(
- inst, VULKAN_LOADER_ERROR_BIT, 0,
- "loader_scanned_icd_add: Could not get \'vkEnumerateInstanceExtensionProperties\' via dlsym/loadlibrary for ICD %s",
- filename);
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
+ "loader_scanned_icd_add: Could not get \'vkEnumerateInstanceExtensionProperties\' via dlsym/loadlibrary "
+ "for ICD %s",
+ filename);
goto out;
}
} else {
@@ -1745,7 +1781,8 @@ static bool verify_meta_layer_component_layers(const struct loader_instance *ins
}
if (success) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "Meta-layer %s all %d component layers appear to be valid.", prop->info.layerName, prop->num_component_layers);
+ "Meta-layer \"%s\" all %d component layers appear to be valid.", prop->info.layerName,
+ prop->num_component_layers);
// If layer logging is on, list the internals included in the meta-layer
if ((loader_get_debug_level() & VULKAN_LOADER_LAYER_BIT) != 0) {
@@ -1758,8 +1795,9 @@ static bool verify_meta_layer_component_layers(const struct loader_instance *ins
}
// Verify that all meta-layers in a layer list are valid.
-static void verify_all_meta_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers,
- bool *override_layer_present) {
+static void verify_all_meta_layers(struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ struct loader_layer_list *instance_layers, bool *override_layer_present) {
*override_layer_present = false;
for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
struct loader_layer_properties *prop = &instance_layers->list[i];
@@ -1773,7 +1811,7 @@ static void verify_all_meta_layers(struct loader_instance *inst, struct loader_l
loader_remove_layer_in_list(inst, instance_layers, i);
i--;
- } else if (prop->is_override && loader_implicit_layer_is_enabled(inst, prop)) {
+ } else if (prop->is_override && loader_implicit_layer_is_enabled(inst, enable_filter, disable_filter, prop)) {
*override_layer_present = true;
}
}
@@ -1808,10 +1846,10 @@ static void remove_all_non_valid_override_layers(struct loader_instance *inst, s
if (!found_active_override_layer) {
found_active_override_layer = true;
} else {
- loader_log(
- inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "remove_all_non_valid_override_layers: Multiple override layers where the same path in app_keys "
- "was found. Using the first layer found");
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "remove_all_non_valid_override_layers: Multiple override layers where the same path in "
+ "app_keys "
+ "was found. Using the first layer found");
// Remove duplicate active override layers that have the same app_key_path
loader_remove_layer_in_list(inst, instance_layers, i);
@@ -2026,14 +2064,14 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
// This is now, officially, a meta-layer
props->type_flags |= VK_LAYER_TYPE_FLAG_META_LAYER;
- loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer %s", name);
+ loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Encountered meta-layer \"%s\"", name);
// Make sure we set up other things so we head down the correct branches below
library_path_str = NULL;
} else {
- loader_log(
- inst, VULKAN_LOADER_WARN_BIT, 0,
- "Layer missing both library_path and component_layers fields. One or the other MUST be defined. Skipping this layer");
+ loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
+ "Layer missing both library_path and component_layers fields. One or the other MUST be defined. Skipping "
+ "this layer");
goto out;
}
@@ -2043,7 +2081,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
if (blacklisted_layers != NULL) {
if (strcmp(name, VK_OVERRIDE_LAYER_NAME)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
- "Layer %s contains a blacklist, but a blacklist can only be provided by the override metalayer. This "
+ "Layer \"%s\" contains a blacklist, but a blacklist can only be provided by the override metalayer. This "
"blacklist will be ignored.",
name);
} else {
@@ -2144,7 +2182,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
// Make sure the layer's manifest doesn't contain a non zero variant value
if (VK_API_VERSION_VARIANT(props->info.specVersion) != 0) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "Layer %s has an \'api_version\' field which contains a non-zero variant value of %d. "
+ "Layer \"%s\" has an \'api_version\' field which contains a non-zero variant value of %d. "
" Skipping Layer.",
props->info.layerName, VK_API_VERSION_VARIANT(props->info.specVersion));
goto out;
@@ -3306,7 +3344,7 @@ VkResult loader_parse_icd_manifest(const struct loader_instance *inst, char *fil
}
// Print out the paths being searched if debugging is enabled
- loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Searching for ICD drivers named %s", library_path);
+ loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "Searching for ICD drivers named %s", library_path);
if (loader_platform_is_path(library_path)) {
// a relative or absolute path
char *name_copy = loader_stack_alloc(strlen(file_str) + 1);
@@ -3404,9 +3442,23 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
struct loader_data_files manifest_files;
VkResult res = VK_SUCCESS;
bool lockedMutex = false;
+ struct loader_envvar_filter select_filter;
+ struct loader_envvar_filter disable_filter;
+ // Before we begin anything, init manifest_files to avoid a delete of garbage memory if
+ // a failure occurs before allocating the manifest filename_list.
memset(&manifest_files, 0, sizeof(struct loader_data_files));
+ // 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 = parse_generic_filter_environment_var(inst, VK_DRIVERS_DISABLE_ENV_VAR, &disable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
res = loader_scanned_icd_init(inst, icd_tramp_list);
if (VK_SUCCESS != res) {
goto out;
@@ -3432,6 +3484,36 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
continue;
}
+ if (select_filter.count > 0 || disable_filter.count > 0) {
+ // Get only the filename for comparing to the filters
+ char *just_filename_str = strrchr(manifest_files.filename_list[i], DIRECTORY_SYMBOL);
+
+ // No directory symbol, just the filename
+ if (NULL == just_filename_str) {
+ just_filename_str = manifest_files.filename_list[i];
+ } else {
+ just_filename_str++;
+ }
+
+ bool name_matches_select =
+ (select_filter.count > 0 && check_name_matches_filter_environment_var(inst, just_filename_str, &select_filter));
+ bool name_matches_disable =
+ (disable_filter.count > 0 && check_name_matches_filter_environment_var(inst, just_filename_str, &disable_filter));
+
+ if (name_matches_disable && !name_matches_select) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "Driver \"%s\" ignored because it was disabled by env var \'%s\'", just_filename_str,
+ VK_DRIVERS_DISABLE_ENV_VAR);
+ continue;
+ }
+ if (select_filter.count != 0 && !name_matches_select) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "Driver \"%s\" ignored because not selected by env var \'%s\'", just_filename_str,
+ VK_DRIVERS_SELECT_ENV_VAR);
+ continue;
+ }
+ }
+
enum loader_layer_library_status lib_status;
icd_res = loader_scanned_icd_add(inst, icd_tramp_list, icd.full_library_path, icd.version, &lib_status);
if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_res) {
@@ -3475,23 +3557,39 @@ out:
return res;
}
-void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
+VkResult loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
+ VkResult res = VK_SUCCESS;
char *file_str;
struct loader_data_files manifest_files;
cJSON *json;
bool override_layer_valid = false;
char *override_paths = NULL;
uint32_t total_count = 0;
+ struct loader_envvar_filter enable_filter;
+ struct loader_envvar_disable_layers_filter disable_filter;
+ // Before we begin anything, init manifest_files to avoid a delete of garbage memory if
+ // a failure occurs before allocating the manifest filename_list.
memset(&manifest_files, 0, sizeof(struct loader_data_files));
+ // Parse the filter environment variables to determine if we have any special behavior
+ res = parse_generic_filter_environment_var(NULL, VK_LAYERS_ENABLE_ENV_VAR, &enable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = parse_layers_disable_filter_environment_var(NULL, &disable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
// Cleanup any previously scanned libraries
loader_delete_layer_list_and_properties(inst, instance_layers);
loader_platform_thread_lock_mutex(&loader_json_lock);
// Get a list of manifest files for any implicit layers
- if (VK_SUCCESS != loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &manifest_files)) {
+ res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &manifest_files);
+ if (VK_SUCCESS != res) {
goto out;
}
@@ -3504,7 +3602,7 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
}
// Parse file into JSON struct
- VkResult res = loader_get_json(inst, file_str, &json);
+ res = loader_get_json(inst, file_str, &json);
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
goto out;
} else if (VK_SUCCESS != res || NULL == json) {
@@ -3527,7 +3625,8 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
// Check to see if the override layer is present, and use it's override paths.
for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
struct loader_layer_properties *prop = &instance_layers->list[i];
- if (prop->is_override && loader_implicit_layer_is_enabled(inst, prop) && prop->num_override_paths > 0) {
+ if (prop->is_override && loader_implicit_layer_is_enabled(inst, &enable_filter, &disable_filter, prop) &&
+ prop->num_override_paths > 0) {
char *cur_write_ptr = NULL;
size_t override_path_size = 0;
for (uint32_t j = 0; j < prop->num_override_paths; j++) {
@@ -3535,6 +3634,7 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
}
override_paths = loader_instance_heap_alloc(inst, override_path_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (override_paths == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
cur_write_ptr = &override_paths[0];
@@ -3545,13 +3645,14 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
--cur_write_ptr;
assert(cur_write_ptr - override_paths < (ptrdiff_t)override_path_size);
*cur_write_ptr = '\0';
- loader_log(NULL, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_scan_for_layers: Override layer has override paths set to %s", override_paths);
+ loader_log(NULL, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Override layer has override paths set to %s",
+ override_paths);
}
}
// Get a list of manifest files for explicit layers
- if (VK_SUCCESS != loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, override_paths, &manifest_files)) {
+ res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER, override_paths, &manifest_files);
+ if (VK_SUCCESS != res) {
goto out;
}
@@ -3566,7 +3667,7 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
}
// Parse file into JSON struct
- VkResult res = loader_get_json(inst, file_str, &json);
+ res = loader_get_json(inst, file_str, &json);
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
goto out;
} else if (VK_SUCCESS != res || NULL == json) {
@@ -3578,6 +3679,7 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
// If the error is anything other than out of memory we still want to try to load the other layers
if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
+ res = local_res;
goto out;
}
}
@@ -3585,7 +3687,7 @@ void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_li
// Verify any meta-layers in the list are valid and all the component layers are
// actually present in the available layer list
- verify_all_meta_layers(inst, instance_layers, &override_layer_valid);
+ verify_all_meta_layers(inst, &enable_filter, &disable_filter, instance_layers, &override_layer_valid);
if (override_layer_valid) {
loader_remove_layers_in_blacklist(inst, instance_layers);
@@ -3604,9 +3706,13 @@ out:
loader_instance_heap_free(inst, manifest_files.filename_list);
}
loader_platform_thread_unlock_mutex(&loader_json_lock);
+ return res;
}
-void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers) {
+VkResult loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers,
+ loader_platform_dl_handle **libs) {
+ struct loader_envvar_filter enable_filter;
+ struct loader_envvar_disable_layers_filter disable_filter;
char *file_str;
struct loader_data_files manifest_files;
cJSON *json;
@@ -3614,12 +3720,23 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
char *override_paths = NULL;
bool implicit_metalayer_present = false;
bool have_json_lock = false;
+ VkResult res = VK_SUCCESS;
// Before we begin anything, init manifest_files to avoid a delete of garbage memory if
// a failure occurs before allocating the manifest filename_list.
memset(&manifest_files, 0, sizeof(struct loader_data_files));
- VkResult res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &manifest_files);
+ // Parse the filter environment variables to determine if we have any special behavior
+ res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &enable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = parse_layers_disable_filter_environment_var(inst, &disable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER, NULL, &manifest_files);
if (VK_SUCCESS != res || manifest_files.count == 0) {
goto out;
}
@@ -3637,20 +3754,22 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
}
// parse file into JSON struct
- res = loader_get_json(inst, file_str, &json);
- if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ VkResult temp_res = loader_get_json(inst, file_str, &json);
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == temp_res) {
+ res = temp_res;
goto out;
- } else if (VK_SUCCESS != res || NULL == json) {
+ } else if (VK_SUCCESS != temp_res || NULL == json) {
continue;
}
- res = loader_add_layer_properties(inst, instance_layers, json, true, file_str);
+ temp_res = loader_add_layer_properties(inst, instance_layers, json, true, file_str);
loader_instance_heap_free(inst, file_str);
manifest_files.filename_list[i] = NULL;
cJSON_Delete(json);
- if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == temp_res) {
+ res = temp_res;
goto out;
}
}
@@ -3662,7 +3781,7 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
// Each of these may require explicit layers to be enabled at this time.
for (int32_t i = 0; i < (int32_t)instance_layers->count; i++) {
struct loader_layer_properties *prop = &instance_layers->list[i];
- if (prop->is_override && loader_implicit_layer_is_enabled(inst, prop)) {
+ if (prop->is_override && loader_implicit_layer_is_enabled(inst, &enable_filter, &disable_filter, prop)) {
override_layer_valid = true;
if (prop->num_override_paths > 0) {
char *cur_write_ptr = NULL;
@@ -3682,8 +3801,8 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
--cur_write_ptr;
assert(cur_write_ptr - override_paths < (ptrdiff_t)override_path_size);
*cur_write_ptr = '\0';
- loader_log(NULL, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_scan_for_implicit_layers: Override layer has override paths set to %s", override_paths);
+ loader_log(NULL, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Override layer has override paths set to %s",
+ override_paths);
}
} else if (!prop->is_override && prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
implicit_metalayer_present = true;
@@ -3712,13 +3831,13 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
continue;
}
- res = loader_add_layer_properties(inst, instance_layers, json, false, file_str);
-
+ VkResult temp_res = loader_add_layer_properties(inst, instance_layers, json, false, file_str);
loader_instance_heap_free(inst, file_str);
manifest_files.filename_list[i] = NULL;
cJSON_Delete(json);
- if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
+ if (VK_ERROR_OUT_OF_HOST_MEMORY == temp_res) {
+ res = temp_res;
goto out;
}
}
@@ -3726,7 +3845,7 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
// Verify any meta-layers in the list are valid and all the component layers are
// actually present in the available layer list
- verify_all_meta_layers(inst, instance_layers, &override_layer_valid);
+ verify_all_meta_layers(inst, &enable_filter, &disable_filter, instance_layers, &override_layer_valid);
if (override_layer_valid || implicit_metalayer_present) {
loader_remove_layers_not_in_implicit_meta_layers(inst, instance_layers);
@@ -3735,6 +3854,23 @@ void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader
}
}
+ // Remove disabled layers
+ for (uint32_t i = 0; i < instance_layers->count; ++i) {
+ if (!loader_implicit_layer_is_enabled(inst, &enable_filter, &disable_filter, &instance_layers->list[i])) {
+ loader_remove_layer_in_list(inst, instance_layers, i);
+ i--;
+ }
+ }
+
+ // We'll need to save the dl handles so we can close them later
+ if (instance_layers->count > 0 && NULL != libs) {
+ *libs = loader_calloc(NULL, sizeof(loader_platform_dl_handle) * instance_layers->count, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (*libs == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ }
+
out:
loader_instance_heap_free(inst, override_paths);
@@ -3746,6 +3882,8 @@ out:
if (have_json_lock) {
loader_platform_thread_unlock_mutex(&loader_json_lock);
}
+
+ return res;
}
static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpdpa_instance_terminator(VkInstance inst, const char *pName) {
@@ -3933,86 +4071,66 @@ void loader_deactivate_layers(const struct loader_instance *instance, struct loa
// Go through the search_list and find any layers which match type. If layer
// type match is found in then add it to ext_list.
-static void loader_add_implicit_layers(const struct loader_instance *inst, struct loader_layer_list *target_list,
- struct loader_layer_list *expanded_target_list,
+static void loader_add_implicit_layers(const struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
const struct loader_layer_list *source_list) {
for (uint32_t src_layer = 0; src_layer < source_list->count; src_layer++) {
const struct loader_layer_properties *prop = &source_list->list[src_layer];
if (0 == (prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
- loader_add_implicit_layer(inst, prop, target_list, expanded_target_list, source_list);
+ loader_add_implicit_layer(inst, prop, enable_filter, disable_filter, target_list, expanded_target_list, source_list);
}
}
}
-// Get the layer name(s) from the env_name environment variable. If layer is found in
-// search_list then add it to layer_list. But only add it to layer_list if type_flags matches.
-static VkResult loader_add_environment_layers(struct loader_instance *inst, const enum layer_type_flags type_flags,
- const char *env_name, struct loader_layer_list *target_list,
- struct loader_layer_list *expanded_target_list,
- const struct loader_layer_list *source_list) {
- VkResult res = VK_SUCCESS;
- char *next, *name;
- char *layer_env = loader_getenv(env_name, inst);
- if (layer_env == NULL) {
- goto out;
- }
- name = loader_stack_alloc(strlen(layer_env) + 1);
- if (name == NULL) {
- goto out;
- }
- strcpy(name, layer_env);
-
- loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_add_environment_layers: Env Var %s defined and adding layers %s", env_name, name);
-
- while (name && *name) {
- next = loader_get_next_path(name);
- res = loader_add_layer_name_to_list(inst, name, type_flags, source_list, target_list, expanded_target_list);
- if (res != VK_SUCCESS) {
- goto out;
- }
- name = next;
- }
-
-out:
-
- if (layer_env != NULL) {
- loader_free_getenv(layer_env, inst);
- }
-
- return res;
-}
-
VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
const struct loader_layer_list *instance_layers) {
+ VkResult res = VK_SUCCESS;
+ struct loader_envvar_filter layers_enable_filter;
+ struct loader_envvar_disable_layers_filter layers_disable_filter;
+
assert(inst && "Cannot have null instance");
if (!loader_init_layer_list(inst, &inst->app_activated_layer_list)) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"loader_enable_instance_layers: Failed to initialize application version of the layer list");
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
}
if (!loader_init_layer_list(inst, &inst->expanded_activated_layer_list)) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"loader_enable_instance_layers: Failed to initialize expanded version of the layer list");
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+
+ // Parse the filter environment variables to determine if we have any special behavior
+ res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &layers_enable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = parse_layers_disable_filter_environment_var(inst, &layers_disable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
}
// Add any implicit layers first
- loader_add_implicit_layers(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
+ loader_add_implicit_layers(inst, &layers_enable_filter, &layers_disable_filter, &inst->app_activated_layer_list,
+ &inst->expanded_activated_layer_list, instance_layers);
// Add any layers specified via environment variable next
- VkResult err =
- loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS",
- &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
- if (err != VK_SUCCESS) {
- return err;
+ res = loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS", &layers_enable_filter,
+ &layers_disable_filter, &inst->app_activated_layer_list,
+ &inst->expanded_activated_layer_list, instance_layers);
+ if (res != VK_SUCCESS) {
+ goto out;
}
// Add layers specified by the application
- err = loader_add_layer_names_to_list(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list,
- pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers);
+ res = loader_add_layer_names_to_list(inst, &layers_enable_filter, &layers_disable_filter, &inst->app_activated_layer_list,
+ &inst->expanded_activated_layer_list, pCreateInfo->enabledLayerCount,
+ pCreateInfo->ppEnabledLayerNames, instance_layers);
for (uint32_t i = 0; i < inst->expanded_activated_layer_list.count; i++) {
// Verify that the layer api version is at least that of the application's request, if not, throw a warning since
@@ -4027,8 +4145,8 @@ VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkIns
inst->app_api_version.minor);
}
}
-
- return err;
+out:
+ return res;
}
// Determine the layer interface version to use.
@@ -4352,7 +4470,7 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c
if (NULL == cur_gipa) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_create_instance_chain: Failed to find \'vkGetInstanceProcAddr\' in layer %s",
+ "loader_create_instance_chain: Failed to find \'vkGetInstanceProcAddr\' in layer \"%s\"",
layer_prop->lib_name);
continue;
}
@@ -4362,7 +4480,7 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c
if (NULL == cur_gipa) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_create_instance_chain: Failed to find \'%s\' in layer %s",
+ "loader_create_instance_chain: Failed to find \'%s\' in layer \"%s\"",
layer_prop->functions.str_gipa, layer_prop->lib_name);
continue;
}
@@ -4396,7 +4514,7 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c
activated_layers[num_activated_layers].disable_env = layer_prop->disable_env_var.name;
}
- loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Insert instance layer %s (%s)",
+ loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Insert instance layer \"%s\" (%s)",
layer_prop->info.layerName, layer_prop->lib_name);
num_activated_layers++;
@@ -4433,15 +4551,17 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, c
}
switch (exp_layer_prop->lib_status) {
case LOADER_LAYER_LIB_NOT_LOADED:
- loader_log(inst, log_flag, 0, "Requested layer %s was not loaded%c", exp_layer_prop->info.layerName, ending);
+ loader_log(inst, log_flag, 0, "Requested layer \"%s\" was not loaded%c", exp_layer_prop->info.layerName,
+ ending);
break;
case LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE: {
- loader_log(inst, log_flag, 0, "Requested layer %s was wrong bit-type%c", exp_layer_prop->info.layerName,
+ loader_log(inst, log_flag, 0, "Requested layer \"%s\" was wrong bit-type%c", exp_layer_prop->info.layerName,
ending);
break;
}
case LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD:
- loader_log(inst, log_flag, 0, "Requested layer %s failed to load%c", exp_layer_prop->info.layerName, ending);
+ loader_log(inst, log_flag, 0, "Requested layer \"%s\" failed to load%c", exp_layer_prop->info.layerName,
+ ending);
break;
case LOADER_LAYER_LIB_SUCCESS_LOADED:
// Shouldn't be able to reach this but if it is, best to report a debug
@@ -4637,7 +4757,8 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
(PFN_vkGetInstanceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gipa);
if (!fpGIPA) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "loader_create_device_chain: Failed to find \'vkGetInstanceProcAddr\' in layer %s. Skipping layer.",
+ "loader_create_device_chain: Failed to find \'vkGetInstanceProcAddr\' in layer \"%s\". "
+ "Skipping layer.",
layer_prop->lib_name);
continue;
}
@@ -4660,7 +4781,7 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
fpGDPA = (PFN_vkGetDeviceProcAddr)loader_platform_get_proc_address(lib_handle, layer_prop->functions.str_gdpa);
if (!fpGDPA) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
- "Failed to find vkGetDeviceProcAddr in layer %s", layer_prop->lib_name);
+ "Failed to find vkGetDeviceProcAddr in layer \"%s\"", layer_prop->lib_name);
continue;
}
}
@@ -4680,7 +4801,7 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
activated_layers[num_activated_layers].disable_env = layer_prop->disable_env_var.name;
}
- loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Inserted device layer %s (%s)",
+ loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0, "Inserted device layer \"%s\" (%s)",
layer_prop->info.layerName, layer_prop->lib_name);
num_activated_layers++;
@@ -4799,6 +4920,8 @@ VkResult loader_validate_instance_extensions(struct loader_instance *inst, const
char *env_value;
bool check_if_known = true;
VkResult res = VK_SUCCESS;
+ struct loader_envvar_filter layers_enable_filter;
+ struct loader_envvar_disable_layers_filter layers_disable_filter;
struct loader_layer_list active_layers;
struct loader_layer_list expanded_layers;
@@ -4820,16 +4943,27 @@ VkResult loader_validate_instance_extensions(struct loader_instance *inst, const
goto out;
}
+ // Parse the filter environment variables to determine if we have any special behavior
+ res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &layers_enable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = parse_layers_disable_filter_environment_var(inst, &layers_disable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
// Build the lists of active layers (including metalayers) and expanded layers (with metalayers resolved to their
// components)
- loader_add_implicit_layers(inst, &active_layers, &expanded_layers, instance_layers);
- res = loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &active_layers,
- &expanded_layers, instance_layers);
+ loader_add_implicit_layers(inst, &layers_enable_filter, &layers_disable_filter, &active_layers, &expanded_layers,
+ instance_layers);
+ res = loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, ENABLED_LAYERS_ENV, &layers_enable_filter,
+ &layers_disable_filter, &active_layers, &expanded_layers, instance_layers);
if (res != VK_SUCCESS) {
goto out;
}
- res = loader_add_layer_names_to_list(inst, &active_layers, &expanded_layers, pCreateInfo->enabledLayerCount,
- pCreateInfo->ppEnabledLayerNames, instance_layers);
+ res = loader_add_layer_names_to_list(inst, &layers_enable_filter, &layers_disable_filter, &active_layers, &expanded_layers,
+ pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers);
if (VK_SUCCESS != res) {
goto out;
}
@@ -6132,6 +6266,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkP
const char *pLayerName, uint32_t *pPropertyCount,
VkExtensionProperties *pProperties) {
struct loader_physical_device_term *phys_dev_term;
+ struct loader_envvar_filter layers_enable_filter;
+ struct loader_envvar_disable_layers_filter layers_disable_filter;
struct loader_layer_list implicit_layer_list = {0};
struct loader_extension_list all_exts = {0};
@@ -6218,7 +6354,20 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkP
goto out;
}
- loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, NULL, &icd_term->this_instance->instance_layer_list);
+ // Parse the filter environment variables to determine if we have any special behavior
+ res = parse_generic_filter_environment_var(icd_term->this_instance, VK_LAYERS_ENABLE_ENV_VAR, &layers_enable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+ res = parse_layers_disable_filter_environment_var(icd_term->this_instance, &layers_disable_filter);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
+
+ if (!(layers_disable_filter.disable_all || layers_disable_filter.disable_all_implicit)) {
+ loader_add_implicit_layers(icd_term->this_instance, &layers_enable_filter, &layers_disable_filter, &implicit_layer_list,
+ NULL, &icd_term->this_instance->instance_layer_list);
+ }
// Initialize dev_extension list within the physicalDevice object
res = loader_init_device_extensions(icd_term->this_instance, phys_dev_term, icd_ext_count, icd_props_list, &icd_exts);
@@ -6233,7 +6382,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkP
goto out;
}
- loader_add_implicit_layers(icd_term->this_instance, &implicit_layer_list, NULL, &icd_term->this_instance->instance_layer_list);
+ if (!(layers_disable_filter.disable_all || layers_disable_filter.disable_all_implicit)) {
+ loader_add_implicit_layers(icd_term->this_instance, &layers_enable_filter, &layers_disable_filter, &implicit_layer_list,
+ NULL, &icd_term->this_instance->instance_layer_list);
+ }
for (uint32_t i = 0; i < implicit_layer_list.count; i++) {
for (uint32_t j = 0; j < implicit_layer_list.list[i].device_extension_list.count; j++) {
@@ -6351,7 +6503,10 @@ terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensi
goto out;
}
- loader_scan_for_layers(NULL, &instance_layers);
+ res = loader_scan_for_layers(NULL, &instance_layers);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
for (uint32_t i = 0; i < instance_layers.count; i++) {
struct loader_layer_properties *props = &instance_layers.list[i];
if (strcmp(props->info.layerName, pLayerName) == 0) {
@@ -6377,11 +6532,11 @@ terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensi
loader_scanned_icd_clear(NULL, &icd_tramp_list);
// Append enabled implicit layers.
- loader_scan_for_implicit_layers(NULL, &instance_layers);
+ res = loader_scan_for_implicit_layers(NULL, &instance_layers, NULL);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
for (uint32_t i = 0; i < instance_layers.count; i++) {
- if (!loader_implicit_layer_is_enabled(NULL, &instance_layers.list[i])) {
- continue;
- }
struct loader_extension_list *ext_list = &instance_layers.list[i].instance_extension_list;
loader_add_to_ext_list(NULL, &local_ext_list, ext_list->count, ext_list->list);
}
@@ -6429,7 +6584,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const
// Get layer libraries
memset(&instance_layer_list, 0, sizeof(instance_layer_list));
- loader_scan_for_layers(NULL, &instance_layer_list);
+ result = loader_scan_for_layers(NULL, &instance_layer_list);
+ if (VK_SUCCESS != result) {
+ goto out;
+ }
if (pProperties == NULL) {
*pPropertyCount = instance_layer_list.count;
diff --git a/loader/loader.h b/loader/loader.h
index 3022096b7..add6fb603 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -101,7 +101,13 @@ bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, c
const VkExtensionProperties *ext_array);
bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list);
+VkResult loader_add_layer_properties_to_list(const struct loader_instance *inst, struct loader_layer_list *list,
+ uint32_t prop_list_count, const struct loader_layer_properties *props);
void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties);
+bool loader_add_meta_layer(const struct loader_instance *inst, const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ const struct loader_layer_properties *prop, struct loader_layer_list *target_list,
+ struct loader_layer_list *expanded_target_list, const struct loader_layer_list *source_list);
VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
uint32_t prop_list_count, const VkExtensionProperties *props);
VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list,
@@ -115,17 +121,14 @@ void loader_destroy_generic_list(const struct loader_instance *inst, struct load
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_add_layer_name_to_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
- const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
- struct loader_layer_list *expanded_target_list);
-void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term,
- const VkAllocationCallbacks *pAllocator);
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);
-void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
-void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
-bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop);
+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);
+VkResult loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers,
+ loader_platform_dl_handle **libs);
VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
struct loader_extension_list *inst_exts);
struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index);
diff --git a/loader/loader_common.h b/loader/loader_common.h
index 29b71aca2..d79cca70e 100644
--- a/loader/loader_common.h
+++ b/loader/loader_common.h
@@ -452,3 +452,29 @@ struct loader_msg_callback_map_entry {
VkDebugReportCallbackEXT icd_obj;
VkDebugReportCallbackEXT loader_obj;
};
+
+typedef enum loader_filter_string_type {
+ FILTER_STRING_FULLNAME = 0,
+ FILTER_STRING_SUBSTRING,
+ FILTER_STRING_PREFIX,
+ FILTER_STRING_SUFFIX,
+ FILTER_STRING_SPECIAL,
+} loader_filter_string_type;
+
+struct loader_envvar_filter_value {
+ char value[VK_MAX_EXTENSION_NAME_SIZE];
+ size_t length;
+ loader_filter_string_type type;
+};
+
+#define MAX_ADDITIONAL_FILTERS 16
+struct loader_envvar_filter {
+ uint32_t count;
+ struct loader_envvar_filter_value filters[MAX_ADDITIONAL_FILTERS];
+};
+struct loader_envvar_disable_layers_filter {
+ struct loader_envvar_filter additional_filters;
+ bool disable_all;
+ bool disable_all_implicit;
+ bool disable_all_explicit;
+};
diff --git a/loader/loader_environment.c b/loader/loader_environment.c
new file mode 100644
index 000000000..6b1755dc8
--- /dev/null
+++ b/loader/loader_environment.c
@@ -0,0 +1,546 @@
+/*
+ *
+ * Copyright (c) 2014-2022 The Khronos Group Inc.
+ * Copyright (c) 2014-2022 Valve Corporation
+ * Copyright (c) 2014-2022 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Chia-I Wu <olvaffe@gmail.com>
+ * Author: Chia-I Wu <olv@lunarg.com>
+ * Author: Mark Lobodzinski <mark@LunarG.com>
+ * Author: Lenny Komow <lenny@lunarg.com>
+ * Author: Charles Giessen <charles@lunarg.com>
+ *
+ */
+
+#include "loader_environment.h"
+
+#include "allocation.h"
+#include "loader.h"
+#include "log.h"
+
+#include <ctype.h>
+
+// Environment variables
+#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || \
+ defined(__OpenBSD__)
+
+bool is_high_integrity() { return geteuid() != getuid() || getegid() != getgid(); }
+
+char *loader_getenv(const char *name, const struct loader_instance *inst) {
+ // No allocation of memory necessary for Linux, but we should at least touch
+ // the inst pointer to get rid of compiler warnings.
+ (void)inst;
+ return getenv(name);
+}
+
+char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ // Apple does not appear to have a secure getenv implementation.
+ // The main difference between secure getenv and getenv is that secure getenv
+ // returns NULL if the process is being run with elevated privileges by a normal user.
+ // The idea is to prevent the reading of malicious environment variables by a process
+ // that can do damage.
+ // This algorithm is derived from glibc code that sets an internal
+ // variable (__libc_enable_secure) if the process is running under setuid or setgid.
+ return is_high_integrity() ? NULL : loader_getenv(name, inst);
+#elif defined(__Fuchsia__)
+ return loader_getenv(name, inst);
+#else
+ // Linux
+ char *out;
+#if defined(HAVE_SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
+ (void)inst;
+ out = secure_getenv(name);
+#elif defined(HAVE___SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
+ (void)inst;
+ out = __secure_getenv(name);
+#else
+ out = loader_getenv(name, inst);
+#if !defined(USE_UNSAFE_FILE_SEARCH)
+ loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
+#endif
+#endif
+ return out;
+#endif
+}
+
+void loader_free_getenv(char *val, const struct loader_instance *inst) {
+ // No freeing of memory necessary for Linux, but we should at least touch
+ // the val and inst pointers to get rid of compiler warnings.
+ (void)val;
+ (void)inst;
+}
+
+#elif defined(WIN32)
+
+bool is_high_integrity() {
+ HANDLE process_token;
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
+ // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
+ uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)];
+ DWORD buffer_size;
+ if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer),
+ &buffer_size) != 0) {
+ const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer;
+ const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
+ const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1);
+
+ CloseHandle(process_token);
+ return integrity_level > SECURITY_MANDATORY_MEDIUM_RID;
+ }
+
+ CloseHandle(process_token);
+ }
+
+ return false;
+}
+
+char *loader_getenv(const char *name, const struct loader_instance *inst) {
+ int name_utf16_size = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
+ if (name_utf16_size <= 0) {
+ return NULL;
+ }
+ wchar_t *name_utf16 = (wchar_t *)loader_stack_alloc(name_utf16_size * sizeof(wchar_t));
+ if (MultiByteToWideChar(CP_UTF8, 0, name, -1, name_utf16, name_utf16_size) != name_utf16_size) {
+ return NULL;
+ }
+
+ DWORD val_size = GetEnvironmentVariableW(name_utf16, NULL, 0);
+ // val_size DOES include the null terminator, so for any set variable
+ // will always be at least 1. If it's 0, the variable wasn't set.
+ if (val_size == 0) {
+ return NULL;
+ }
+
+ wchar_t *val = (wchar_t *)loader_stack_alloc(val_size * sizeof(wchar_t));
+ if (GetEnvironmentVariableW(name_utf16, val, val_size) != val_size - 1) {
+ return NULL;
+ }
+
+ int val_utf8_size = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0, NULL, NULL);
+ if (val_utf8_size <= 0) {
+ return NULL;
+ }
+ char *val_utf8 = (char *)loader_instance_heap_alloc(inst, val_utf8_size * sizeof(char), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (val_utf8 == NULL) {
+ return NULL;
+ }
+ if (WideCharToMultiByte(CP_UTF8, 0, val, -1, val_utf8, val_utf8_size, NULL, NULL) != val_utf8_size) {
+ loader_instance_heap_free(inst, val_utf8);
+ return NULL;
+ }
+ return val_utf8;
+}
+
+char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
+#if !defined(USE_UNSAFE_FILE_SEARCH)
+ if (is_high_integrity()) {
+ loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
+ "Loader is running with elevated permissions. Environment variable %s will be ignored", name);
+ return NULL;
+ }
+#endif
+
+ return loader_getenv(name, inst);
+}
+
+void loader_free_getenv(char *val, const struct loader_instance *inst) { loader_instance_heap_free(inst, (void *)val); }
+
+#else
+
+char *loader_getenv(const char *name, const struct loader_instance *inst) {
+ // stub func
+ (void)inst;
+ (void)name;
+ return NULL;
+}
+void loader_free_getenv(char *val, const struct loader_instance *inst) {
+ // stub func
+ (void)val;
+ (void)inst;
+}
+
+#endif
+
+// Determine the type of filter string based on the contents of it.
+// This will properly check against:
+// - substrings "*string*"
+// - prefixes "string*"
+// - suffixes "*string"
+// - full string names "string"
+// It will also return the correct start and finish to remove any star '*' characters for the actual string compare
+void determine_filter_type(const char *filter_string, enum loader_filter_string_type *filter_type, const char **new_start,
+ size_t *new_length) {
+ size_t filter_length = strlen(filter_string);
+ bool star_begin = false;
+ bool star_end = false;
+ if ('~' == filter_string[0]) {
+ // One of the special identifiers like: ~all~, ~implicit~, or ~explicit~
+ *filter_type = FILTER_STRING_SPECIAL;
+ *new_start = filter_string;
+ *new_length = filter_length;
+ } else {
+ if ('*' == filter_string[0]) {
+ // Only the * means everything
+ if (filter_length == 1) {
+ *filter_type = FILTER_STRING_SPECIAL;
+ *new_start = filter_string;
+ *new_length = filter_length;
+ } else {
+ star_begin = true;
+ }
+ }
+ if ('*' == filter_string[filter_length - 1]) {
+ // Not really valid, but just catch this case so if someone accidentally types "**" it will also mean everything
+ if (filter_length == 2) {
+ *filter_type = FILTER_STRING_SPECIAL;
+ *new_start = filter_string;
+ *new_length = filter_length;
+ } else {
+ star_end = true;
+ }
+ }
+ if (star_begin && star_end) {
+ *filter_type = FILTER_STRING_SUBSTRING;
+ *new_start = &filter_string[1];
+ *new_length = filter_length - 2;
+ } else if (star_begin) {
+ *new_start = &filter_string[1];
+ *new_length = filter_length - 1;
+ *filter_type = FILTER_STRING_SUFFIX;
+ } else if (star_end) {
+ *filter_type = FILTER_STRING_PREFIX;
+ *new_start = filter_string;
+ *new_length = filter_length - 1;
+ } else {
+ *filter_type = FILTER_STRING_FULLNAME;
+ *new_start = filter_string;
+ *new_length = filter_length;
+ }
+ }
+}
+
+// Parse the provided filter string provided by the envrionment variable into the appropriate filter
+// struct variable.
+VkResult parse_generic_filter_environment_var(const struct loader_instance *inst, const char *env_var_name,
+ struct loader_envvar_filter *filter_struct) {
+ VkResult result = VK_SUCCESS;
+ memset(filter_struct, 0, sizeof(struct loader_envvar_filter));
+ char *env_var_value = loader_secure_getenv(env_var_name, inst);
+ if (NULL == env_var_value) {
+ return result;
+ }
+ if (strlen(env_var_value) > 0) {
+ const size_t env_var_len = strlen(env_var_value);
+ // Allocate a separate string since strtok modifies the original string
+ char *parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL != parsing_string) {
+ const char tokenizer[3] = ",";
+
+ for (uint32_t iii = 0; iii < env_var_len; ++iii) {
+ parsing_string[iii] = (char)tolower(env_var_value[iii]);
+ }
+ parsing_string[env_var_len] = '\0';
+
+ char *token = strtok(parsing_string, tokenizer);
+ while (NULL != token) {
+ enum loader_filter_string_type cur_filter_type;
+ const char *actual_start;
+ size_t actual_len;
+ determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
+ if (actual_len > VK_MAX_EXTENSION_NAME_SIZE) {
+ strncpy(filter_struct->filters[filter_struct->count].value, actual_start, VK_MAX_EXTENSION_NAME_SIZE);
+ } else {
+ strncpy(filter_struct->filters[filter_struct->count].value, actual_start, actual_len);
+ }
+ filter_struct->filters[filter_struct->count].length = actual_len;
+ filter_struct->filters[filter_struct->count++].type = cur_filter_type;
+ if (filter_struct->count >= MAX_ADDITIONAL_FILTERS) {
+ break;
+ }
+ token = strtok(NULL, tokenizer);
+ }
+ loader_instance_heap_free(inst, parsing_string);
+ } else {
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
+ "parse_generic_filter_environment_var: Failed to allocate space for parsing env var \'%s\'", env_var_name);
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+ loader_free_getenv(env_var_value, inst);
+ return result;
+}
+
+// Parse the disable layer string. The layer disable has some special behavior because we allow it to disable
+// all layers (either with "~all~", "*", or "**"), all implicit layers (with "~implicit~"), and all explicit layers
+// (with "~explicit~"), in addition to the other layer filtering behavior.
+VkResult parse_layers_disable_filter_environment_var(const struct loader_instance *inst,
+ struct loader_envvar_disable_layers_filter *disable_struct) {
+ VkResult result = VK_SUCCESS;
+ memset(disable_struct, 0, sizeof(struct loader_envvar_disable_layers_filter));
+ char *env_var_value = loader_secure_getenv(VK_LAYERS_DISABLE_ENV_VAR, inst);
+ if (NULL == env_var_value) {
+ goto out;
+ }
+ if (strlen(env_var_value) > 0) {
+ const size_t env_var_len = strlen(env_var_value);
+ // Allocate a separate string since strtok modifies the original string
+ char *parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (NULL != parsing_string) {
+ const char tokenizer[3] = ",";
+
+ for (uint32_t iii = 0; iii < env_var_len; ++iii) {
+ parsing_string[iii] = (char)tolower(env_var_value[iii]);
+ }
+ parsing_string[env_var_len] = '\0';
+
+ char *token = strtok(parsing_string, tokenizer);
+ while (NULL != token) {
+ uint32_t cur_count = disable_struct->additional_filters.count;
+ enum loader_filter_string_type cur_filter_type;
+ const char *actual_start;
+ size_t actual_len;
+ determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
+ if (cur_filter_type == FILTER_STRING_SPECIAL) {
+ if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, token) || !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, token) ||
+ !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, token)) {
+ disable_struct->disable_all = true;
+ } else if (!strcmp(VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR, token)) {
+ disable_struct->disable_all_implicit = true;
+ } else if (!strcmp(VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR, token)) {
+ disable_struct->disable_all_explicit = true;
+ }
+ } else {
+ if (actual_len > VK_MAX_EXTENSION_NAME_SIZE) {
+ strncpy(disable_struct->additional_filters.filters[cur_count].value, actual_start,
+ VK_MAX_EXTENSION_NAME_SIZE);
+ } else {
+ strncpy(disable_struct->additional_filters.filters[cur_count].value, actual_start, actual_len);
+ }
+ disable_struct->additional_filters.filters[cur_count].length = actual_len;
+ disable_struct->additional_filters.filters[cur_count].type = cur_filter_type;
+ disable_struct->additional_filters.count++;
+ if (disable_struct->additional_filters.count >= MAX_ADDITIONAL_FILTERS) {
+ break;
+ }
+ }
+ token = strtok(NULL, tokenizer);
+ }
+ loader_instance_heap_free(inst, parsing_string);
+ } else {
+ loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
+ "parse_layers_disable_filter_environment_var: Failed to allocate space for parsing env var "
+ "\'VK_LAYERS_DISABLE_ENV_VAR\'");
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ }
+ loader_free_getenv(env_var_value, inst);
+out:
+ return result;
+}
+
+// Check to see if the provided layer name matches any of the filter strings.
+// This will properly check against:
+// - substrings "*string*"
+// - prefixes "string*"
+// - suffixes "*string"
+// - full string names "string"
+bool check_name_matches_filter_environment_var(const struct loader_instance *inst, const char *name,
+ const struct loader_envvar_filter *filter_struct) {
+ bool ret_value = false;
+ const size_t name_len = strlen(name);
+ char lower_name[VK_MAX_EXTENSION_NAME_SIZE];
+ for (uint32_t iii = 0; iii < name_len; ++iii) {
+ lower_name[iii] = (char)tolower(name[iii]);
+ }
+ lower_name[name_len] = '\0';
+ for (uint32_t filt = 0; filt < filter_struct->count; ++filt) {
+ // Check if the filter name is longer (this is with all special characters removed), and if it is
+ // continue since it can't match.
+ if (filter_struct->filters[filt].length > name_len) {
+ continue;
+ }
+ switch (filter_struct->filters[filt].type) {
+ case FILTER_STRING_SPECIAL:
+ if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, filter_struct->filters[filt].value) ||
+ !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, filter_struct->filters[filt].value) ||
+ !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, filter_struct->filters[filt].value)) {
+ ret_value = true;
+ }
+ break;
+
+ case FILTER_STRING_SUBSTRING:
+ if (NULL != strstr(lower_name, filter_struct->filters[filt].value)) {
+ ret_value = true;
+ }
+ break;
+
+ case FILTER_STRING_SUFFIX:
+ if (0 == strncmp(lower_name + name_len - filter_struct->filters[filt].length, filter_struct->filters[filt].value,
+ filter_struct->filters[filt].length)) {
+ ret_value = true;
+ }
+ break;
+
+ case FILTER_STRING_PREFIX:
+ if (0 == strncmp(lower_name, filter_struct->filters[filt].value, filter_struct->filters[filt].length)) {
+ ret_value = true;
+ }
+ break;
+
+ case FILTER_STRING_FULLNAME:
+ if (0 == strncmp(lower_name, filter_struct->filters[filt].value, name_len)) {
+ ret_value = true;
+ }
+ break;
+ }
+ if (ret_value) {
+ break;
+ }
+ }
+ return ret_value;
+}
+
+// Get the layer name(s) from the env_name environment variable. If layer is found in
+// search_list then add it to layer_list. But only add it to layer_list if type_flags matches.
+VkResult loader_add_environment_layers(struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name,
+ const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
+ const struct loader_layer_list *source_list) {
+ VkResult res = VK_SUCCESS;
+ char *next, *name;
+ char *layer_env = loader_getenv(env_name, inst);
+ char **vk_inst_layers = NULL;
+ uint32_t vk_inst_layer_count = 0;
+ uint32_t separator_count = 0;
+
+ // If the layer environment variable is present (i.e. VK_INSTANCE_LAYERS), we will always add it to the layer list.
+ if (layer_env != NULL) {
+ name = loader_stack_alloc(strlen(layer_env) + 1);
+ if (name != NULL) {
+ separator_count = 1;
+ for (uint32_t c = 0; c < strlen(layer_env); ++c) {
+ if (c == PATH_SEPARATOR) {
+ separator_count++;
+ }
+ }
+
+ vk_inst_layers =
+ loader_instance_heap_calloc(inst, (separator_count * sizeof(char *)), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (vk_inst_layers == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ for (uint32_t cur_layer = 0; cur_layer < separator_count; ++cur_layer) {
+ vk_inst_layers[cur_layer] =
+ loader_instance_heap_calloc(inst, VK_MAX_EXTENSION_NAME_SIZE, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (vk_inst_layers[cur_layer] == NULL) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
+ }
+
+ strcpy(name, layer_env);
+
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "env var \'%s\' defined and adding layers \"%s\"",
+ env_name, name);
+
+ // First look for the old-fashion layers forced on with VK_INSTANCE_LAYERS
+ while (name && *name) {
+ next = loader_get_next_path(name);
+
+ if (strlen(name) > 0) {
+ strncpy(vk_inst_layers[vk_inst_layer_count++], name, VK_MAX_EXTENSION_NAME_SIZE);
+ }
+ name = next;
+ }
+ }
+ }
+
+ // Loop through all the layers and check the enable/disable filters as well as the VK_INSTANCE_LAYERS value.
+ for (uint32_t i = 0; i < source_list->count; i++) {
+ struct loader_layer_properties *source_prop = &source_list->list[i];
+
+ // If it doesn't match the type, or the name isn't what we're looking for, just continue
+ if ((source_prop->type_flags & type_flags) != type_flags) {
+ continue;
+ }
+
+ // We found a layer we're interested in, but has it been disabled...
+ bool adding = true;
+ bool is_implicit = (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
+ bool disabled_by_type = (is_implicit) ? (NULL != disable_filter && disable_filter->disable_all_implicit)
+ : (NULL != disable_filter && disable_filter->disable_all_explicit);
+ if (NULL != disable_filter &&
+ (disable_filter->disable_all || disabled_by_type ||
+ check_name_matches_filter_environment_var(inst, source_prop->info.layerName, &disable_filter->additional_filters))) {
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "Layer \"%s\" ignored because it has been disabled by env var \'%s\'", source_prop->info.layerName,
+ VK_LAYERS_DISABLE_ENV_VAR);
+ adding = false;
+ }
+
+ // If we are supposed to filter through all layers, we need to compare the layer name against the filter.
+ // This can override the disable above, so we want to do it second.
+ if (check_name_matches_filter_environment_var(inst, source_prop->info.layerName, enable_filter)) {
+ adding = true;
+ // Only way is_substring is true is if there are enable variables. If that's the case, and we're past the
+ // above, we should indicate that it was forced on in this way.
+ loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
+ "Layer \"%s\" forced enabled due to env var \'%s\'", source_prop->info.layerName, VK_LAYERS_ENABLE_ENV_VAR);
+ } else {
+ adding = false;
+ // If it's not in the enable filter, check the environment variable if it exists
+ if (vk_inst_layer_count > 0) {
+ for (uint32_t cur_layer = 0; cur_layer < vk_inst_layer_count; ++cur_layer) {
+ if (!strcmp(vk_inst_layers[cur_layer], source_prop->info.layerName)) {
+ adding = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!adding) {
+ continue;
+ }
+
+ // If not a meta-layer, simply add it.
+ if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
+ loader_add_layer_properties_to_list(inst, target_list, 1, source_prop);
+ loader_add_layer_properties_to_list(inst, expanded_target_list, 1, source_prop);
+ } else {
+ loader_add_meta_layer(inst, enable_filter, disable_filter, source_prop, target_list, expanded_target_list, source_list);
+ }
+ }
+
+out:
+
+ if (NULL != vk_inst_layers) {
+ for (uint32_t cur_layer = 0; cur_layer < separator_count; ++cur_layer) {
+ loader_instance_heap_free(inst, vk_inst_layers[cur_layer]);
+ }
+ loader_instance_heap_free(inst, vk_inst_layers);
+ }
+
+ if (layer_env != NULL) {
+ loader_free_getenv(layer_env, inst);
+ }
+
+ return res;
+}
diff --git a/loader/get_environment.h b/loader/loader_environment.h
index 2b1663b41..2eb61d583 100644
--- a/loader/get_environment.h
+++ b/loader/loader_environment.h
@@ -35,10 +35,23 @@
char *loader_getenv(const char *name, const struct loader_instance *inst);
void loader_free_getenv(char *val, const struct loader_instance *inst);
-#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || \
+ defined(__FreeBSD__) || defined(__OpenBSD__)
bool is_high_integrity();
char *loader_secure_getenv(const char *name, const struct loader_instance *inst);
#endif
+
+VkResult parse_generic_filter_environment_var(const struct loader_instance *inst, const char *env_var_name,
+ struct loader_envvar_filter *filter_struct);
+VkResult parse_layers_disable_filter_environment_var(const struct loader_instance *inst,
+ struct loader_envvar_disable_layers_filter *disable_struct);
+bool check_name_matches_filter_environment_var(const struct loader_instance *inst, const char *name,
+ const struct loader_envvar_filter *filter_struct);
+VkResult loader_add_environment_layers(struct loader_instance *inst, const enum layer_type_flags type_flags, const char *env_name,
+ const struct loader_envvar_filter *enable_filter,
+ const struct loader_envvar_disable_layers_filter *disable_filter,
+ struct loader_layer_list *target_list, struct loader_layer_list *expanded_target_list,
+ const struct loader_layer_list *source_list); \ No newline at end of file
diff --git a/loader/loader_linux.c b/loader/loader_linux.c
index 4a31da623..9f1a16841 100644
--- a/loader/loader_linux.c
+++ b/loader/loader_linux.c
@@ -30,7 +30,7 @@
#include "loader_linux.h"
#include "allocation.h"
-#include "get_environment.h"
+#include "loader_environment.h"
#include "loader.h"
#include "log.h"
@@ -209,7 +209,7 @@ static void linux_env_var_default_device(struct loader_instance *inst, uint32_t
char *selection = loader_getenv("VK_LOADER_DEVICE_SELECT", inst);
if (NULL != selection) {
loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
- "linux_env_var_default_device: Found VK_LOADER_DEVICE_SELECT set to %s", selection);
+ "linux_env_var_default_device: Found \'VK_LOADER_DEVICE_SELECT\' set to %s", selection);
// The environment variable exists, so grab the vendor ID and device ID of the
// selected default device
diff --git a/loader/loader_windows.c b/loader/loader_windows.c
index 068e21147..db8b69104 100644
--- a/loader/loader_windows.c
+++ b/loader/loader_windows.c
@@ -36,7 +36,7 @@
#include "loader_windows.h"
#include "allocation.h"
-#include "get_environment.h"
+#include "loader_environment.h"
#include "loader.h"
#include "log.h"
diff --git a/loader/log.c b/loader/log.c
index ab64f6336..33ed3ce6d 100644
--- a/loader/log.c
+++ b/loader/log.c
@@ -32,7 +32,7 @@
#include <stdarg.h>
#include "debug_utils.h"
-#include "get_environment.h"
+#include "loader_environment.h"
uint32_t g_loader_debug = 0;
diff --git a/loader/trampoline.c b/loader/trampoline.c
index fa07218da..b8d76322a 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -160,21 +160,19 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionPropert
// Get the implicit layers
struct loader_layer_list layers;
+ loader_platform_dl_handle *libs = NULL;
+ size_t lib_count = 0;
memset(&layers, 0, sizeof(layers));
- loader_scan_for_implicit_layers(NULL, &layers);
- // We'll need to save the dl handles so we can close them later
- loader_platform_dl_handle *libs =
- loader_calloc(NULL, sizeof(loader_platform_dl_handle) * layers.count, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (libs == NULL && layers.count > 0) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = loader_scan_for_implicit_layers(NULL, &layers, &libs);
+ if (VK_SUCCESS != res) {
+ return res;
}
- size_t lib_count = 0;
// Prepend layers onto the chain if they implement this entry point
for (uint32_t i = 0; i < layers.count; ++i) {
- if (!loader_implicit_layer_is_enabled(NULL, layers.list + i) ||
- layers.list[i].pre_instance_functions.enumerate_instance_extension_properties[0] == '\0') {
+ // Skip this layer if it doesn't expose the entry-point
+ if (layers.list[i].pre_instance_functions.enumerate_instance_extension_properties[0] == '\0') {
continue;
}
@@ -255,24 +253,17 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
// Get the implicit layers
struct loader_layer_list layers;
+ loader_platform_dl_handle *libs = NULL;
+ size_t lib_count = 0;
memset(&layers, 0, sizeof(layers));
- loader_scan_for_implicit_layers(NULL, &layers);
- // We'll need to save the dl handles so we can close them later
- loader_platform_dl_handle *libs =
- loader_calloc(NULL, sizeof(loader_platform_dl_handle) * layers.count, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (libs == NULL && layers.count > 0) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = loader_scan_for_implicit_layers(NULL, &layers, &libs);
+ if (VK_SUCCESS != res) {
+ return res;
}
- size_t lib_count = 0;
// Prepend layers onto the chain if they implement this entry point
for (uint32_t i = 0; i < layers.count; ++i) {
- if (!loader_implicit_layer_is_enabled(NULL, layers.list + i) ||
- layers.list[i].pre_instance_functions.enumerate_instance_layer_properties[0] == '\0') {
- continue;
- }
-
loader_platform_dl_handle layer_lib = loader_platform_open_library(layers.list[i].lib_name);
if (layer_lib == NULL) {
loader_log(NULL, VULKAN_LOADER_WARN_BIT, 0, "%s: Unable to load implicit layer library \"%s\"", __FUNCTION__,
@@ -357,21 +348,19 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(uint32_t
// Get the implicit layers
struct loader_layer_list layers;
+ loader_platform_dl_handle *libs = NULL;
+ size_t lib_count = 0;
memset(&layers, 0, sizeof(layers));
- loader_scan_for_implicit_layers(NULL, &layers);
- // We'll need to save the dl handles so we can close them later
- loader_platform_dl_handle *libs =
- loader_calloc(NULL, sizeof(loader_platform_dl_handle) * layers.count, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (libs == NULL && layers.count > 0) {
- return VK_ERROR_OUT_OF_HOST_MEMORY;
+ res = loader_scan_for_implicit_layers(NULL, &layers, &libs);
+ if (VK_SUCCESS != res) {
+ return res;
}
- size_t lib_count = 0;
// Prepend layers onto the chain if they implement this entry point
for (uint32_t i = 0; i < layers.count; ++i) {
- if (!loader_implicit_layer_is_enabled(NULL, layers.list + i) ||
- layers.list[i].pre_instance_functions.enumerate_instance_version[0] == '\0') {
+ // Skip this layer if it doesn't expose the entry-point
+ if (layers.list[i].pre_instance_functions.enumerate_instance_version[0] == '\0') {
continue;
}
@@ -520,7 +509,10 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
// enabledLayerCount == 0 and VK_INSTANCE_LAYERS is unset. For now always
// get layer list via loader_scan_for_layers().
memset(&ptr_instance->instance_layer_list, 0, sizeof(ptr_instance->instance_layer_list));
- loader_scan_for_layers(ptr_instance, &ptr_instance->instance_layer_list);
+ res = loader_scan_for_layers(ptr_instance, &ptr_instance->instance_layer_list);
+ if (VK_SUCCESS != res) {
+ goto out;
+ }
// Validate the app requested layers to be enabled
if (pCreateInfo->enabledLayerCount > 0) {
diff --git a/loader/vk_loader_platform.h b/loader/vk_loader_platform.h
index ebfa2ebfb..cfdc6660e 100644
--- a/loader/vk_loader_platform.h
+++ b/loader/vk_loader_platform.h
@@ -86,11 +86,22 @@
#endif
// Environment Variable information
-#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES" // Deprecated
+#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES" // Deprecated in v1.3.207 loader
#define VK_DRIVER_FILES_ENV_VAR "VK_DRIVER_FILES"
-#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
#define VK_LAYER_PATH_ENV_VAR "VK_LAYER_PATH"
+// Support added in v1.3.207 loader
+#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
#define VK_ADDITIONAL_LAYER_PATH_ENV_VAR "VK_ADD_LAYER_PATH"
+// Support added in v1.3.217 loader
+#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
+#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
+#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
+#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
+#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
+#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
+#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
+#define VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR "~implicit~"
+#define VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR "~explicit~"
// Override layer information
#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
diff --git a/tests/framework/test_environment.cpp b/tests/framework/test_environment.cpp
index bb9b6a9b9..4fc316dd2 100644
--- a/tests/framework/test_environment.cpp
+++ b/tests/framework/test_environment.cpp
@@ -136,6 +136,24 @@ void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrap
create_info.instance_info.pNext = wrapper.get();
}
+// Look through the event log. If you find a line containing the prefix we're interested in, look for the end of
+// line character, and then see if the postfix occurs in it as well.
+bool FindPrefixPostfixStringOnLine(DebugUtilsLogger& env_log, const char* prefix, const char* postfix) {
+ size_t new_start = 0;
+ size_t postfix_index = 0;
+ size_t next_eol = 0;
+ while ((new_start = env_log.returned_output.find(prefix, new_start)) != std::string::npos) {
+ next_eol = env_log.returned_output.find("\n", new_start);
+ if ((postfix_index = env_log.returned_output.find(postfix, new_start)) != std::string::npos) {
+ if (postfix_index < next_eol) {
+ return true;
+ }
+ }
+ new_start = next_eol + 1;
+ }
+ return false;
+}
+
PlatformShimWrapper::PlatformShimWrapper(std::vector<fs::FolderManager>* folders, bool enable_log) noexcept {
#if defined(WIN32) || defined(__APPLE__)
shim_library = LibraryWrapper(SHIM_LIBRARY_NAME);
@@ -151,6 +169,7 @@ PlatformShimWrapper::PlatformShimWrapper(std::vector<fs::FolderManager>* folders
set_env_var("VK_LOADER_DEBUG", "all");
}
}
+
PlatformShimWrapper::~PlatformShimWrapper() noexcept { platform_shim->reset(); }
TestICDHandle::TestICDHandle() noexcept {}
@@ -224,7 +243,11 @@ void FrameworkEnvironment::add_icd(TestICDDetails icd_details) noexcept {
icds.back().reset_icd();
icd_details.icd_manifest.lib_path = new_driver_location.str();
}
- std::string full_json_name = icd_details.json_name + "_" + std::to_string(cur_icd_index) + ".json";
+ 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) {
diff --git a/tests/framework/test_environment.h b/tests/framework/test_environment.h
index b814cfb4b..e8edc47a9 100644
--- a/tests/framework/test_environment.h
+++ b/tests/framework/test_environment.h
@@ -259,6 +259,10 @@ VkResult CreateDebugUtilsMessenger(DebugUtilsWrapper& debug_utils);
void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsLogger& logger);
void FillDebugUtilsCreateDetails(InstanceCreateInfo& create_info, DebugUtilsWrapper& wrapper);
+// Look through the event log. If you find a line containing the prefix we're interested in, look for the end of
+// line character, and then see if the postfix occurs in it as well.
+bool FindPrefixPostfixStringOnLine(DebugUtilsLogger& env_log, const char* prefix, const char* postfix);
+
struct FrameworkEnvironment; // forward declaration
struct PlatformShimWrapper {
@@ -319,6 +323,7 @@ struct TestICDDetails {
}
BUILDER_VALUE(TestICDDetails, ManifestICD, icd_manifest, {});
BUILDER_VALUE(TestICDDetails, std::string, json_name, "test_icd");
+ BUILDER_VALUE(TestICDDetails, bool, disable_icd_inc, false);
BUILDER_VALUE(TestICDDetails, ManifestDiscoveryType, discovery_type, ManifestDiscoveryType::generic);
BUILDER_VALUE(TestICDDetails, bool, is_fake, false);
};
diff --git a/tests/loader_envvar_tests.cpp b/tests/loader_envvar_tests.cpp
index 63e050c9b..47c1deb6f 100644
--- a/tests/loader_envvar_tests.cpp
+++ b/tests/loader_envvar_tests.cpp
@@ -355,3 +355,357 @@ TEST(EnvVarICDOverrideSetup, TestOnlyAddLayerEnvVar) {
}
#endif
+
+// 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";
+
+ 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"));
+ env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_disable_icd_inc(true).set_json_name("CDE_ICD"));
+
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match full-name
+ env.debug_log.clear();
+ set_env_var(filter_select_env_var, "ABC_ICD.json");
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match prefix
+ env.debug_log.clear();
+ set_env_var(filter_select_env_var, "ABC*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match suffix
+ env.debug_log.clear();
+ set_env_var(filter_select_env_var, "*C_ICD.json");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match sub-string
+ env.debug_log.clear();
+ set_env_var(filter_select_env_var, "*BC*");
+
+ InstWrapper inst5{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match all with star '*'
+ env.debug_log.clear();
+ set_env_var(filter_select_env_var, "*");
+
+ InstWrapper inst6{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match all with special name
+ env.debug_log.clear();
+ set_env_var(filter_select_env_var, "~all~");
+
+ InstWrapper inst7{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ remove_env_var(filter_select_env_var);
+}
+
+// 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";
+
+ 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"));
+ env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_disable_icd_inc(true).set_json_name("CDE_ICD"));
+
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match full-name
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "ABC_ICD.json");
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match prefix
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "ABC_*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match suffix
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "*C_ICD.json");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match substring
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "*BC*");
+
+ InstWrapper inst5{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match all with star '*'
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "*");
+
+ InstWrapper inst6{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Match all with special name
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "~all~");
+
+ InstWrapper inst7{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ remove_env_var(filter_disable_env_var);
+}
+
+// Test that the when both driver filter select and disable environment variables are present, that the
+// 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";
+
+ 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"));
+ env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_disable_icd_inc(true).set_json_name("CDE_ICD"));
+
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // 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*");
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Disable all, but enable two
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "*");
+ set_env_var(filter_select_env_var, "*BC*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ // Disable all, but enable all
+ env.debug_log.clear();
+ set_env_var(filter_disable_env_var, "*");
+ set_env_var(filter_select_env_var, "*");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "ABC_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "ABC_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "BCD_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "BCD_ICD.json", "ignored because it was disabled by env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found ICD manifest file", "CDE_ICD.json"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because not selected by env var"));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "CDE_ICD.json", "ignored because it was disabled by env var"));
+
+ remove_env_var(filter_select_env_var);
+ remove_env_var(filter_disable_env_var);
+}
diff --git a/tests/loader_layer_tests.cpp b/tests/loader_layer_tests.cpp
index ec0750047..339d46ff5 100644
--- a/tests/loader_layer_tests.cpp
+++ b/tests/loader_layer_tests.cpp
@@ -33,9 +33,9 @@ void CheckLogForLayerString(FrameworkEnvironment& env, const char* implicit_laye
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate(VK_SUCCESS);
if (check_for_enable) {
- ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + implicit_layer_name));
+ ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + implicit_layer_name));
} else {
- ASSERT_FALSE(env.debug_log.find(std::string("Insert instance layer ") + implicit_layer_name));
+ ASSERT_FALSE(env.debug_log.find(std::string("Insert instance layer \"") + implicit_layer_name));
}
}
env.debug_log.clear();
@@ -123,7 +123,7 @@ TEST(ImplicitLayers, OnlyDisableEnvVar) {
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.create_info.add_layer(implicit_layer_name);
inst.CheckCreate(VK_SUCCESS);
- ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + implicit_layer_name));
+ ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + implicit_layer_name));
}
remove_env_var(disable_env_var);
}
@@ -281,6 +281,656 @@ TEST(ImplicitLayers, OverrideGetInstanceProcAddr) {
remove_env_var(disable_env_var);
}
+// Force enable with filter env var
+TEST(ImplicitLayers, EnableWithFilter) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* implicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* implicit_json_name_1 = "First_layer.json";
+ const char* disable_layer_name_1 = "DISABLE_FIRST";
+ const char* enable_layer_name_1 = "ENABLE_FIRST";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_enable_environment(enable_layer_name_1)
+ .set_disable_environment(disable_layer_name_1)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_1);
+
+ const char* implicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* implicit_json_name_2 = "Second_layer.json";
+ const char* disable_layer_name_2 = "DISABLE_SECOND";
+ const char* enable_layer_name_2 = "ENABLE_SECOND";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_enable_environment(enable_layer_name_2)
+ .set_disable_environment(disable_layer_name_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_2);
+
+ const char* implicit_layer_name_3 = "VK_LAYER_LUNARG_Second_test_layer";
+ const char* implicit_json_name_3 = "Second_test_layer.json";
+ const char* disable_layer_name_3 = "DISABLE_THIRD";
+ const char* enable_layer_name_3 = "ENABLE_THIRD";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_3)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_enable_environment(enable_layer_name_3)
+ .set_disable_environment(disable_layer_name_3)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_3);
+
+ // First, test an instance/device without the layer forced on.
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Now force on one layer with its full name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", implicit_layer_name_1);
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match prefix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "VK_LAYER_LUNARG_*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match suffix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second_layer");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match substring
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+
+ InstWrapper inst5{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with star '*'
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+
+ InstWrapper inst6{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with special name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "~all~");
+
+ InstWrapper inst7{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ InstWrapper inst8{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst8.create_info, env.debug_log);
+ inst8.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_LOADER_LAYERS_ENABLE");
+ remove_env_var(enable_layer_name_1);
+}
+
+// Force disabled with new filter env var
+TEST(ImplicitLayers, DisableWithFilter) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* implicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* implicit_json_name_1 = "First_layer.json";
+ const char* disable_layer_name_1 = "DISABLE_FIRST";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment(disable_layer_name_1)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_1);
+
+ const char* implicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* implicit_json_name_2 = "Second_layer.json";
+ const char* disable_layer_name_2 = "DISABLE_SECOND";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment(disable_layer_name_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_2);
+
+ const char* implicit_layer_name_3 = "VK_LAYER_LUNARG_Second_test_layer";
+ const char* implicit_json_name_3 = "Second_test_layer.json";
+ const char* disable_layer_name_3 = "DISABLE_THIRD";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_3)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment(disable_layer_name_3)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_3);
+
+ // First, test an instance/device
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Now force off one layer with its full name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", implicit_layer_name_1);
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match prefix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "VK_LAYER_LUNARG_*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match suffix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second_layer");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match substring
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*Second*");
+
+ InstWrapper inst5{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with star '*'
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+
+ InstWrapper inst6{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with special name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "~all~");
+
+ InstWrapper inst7{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_LOADER_LAYERS_DISABLE");
+}
+
+// Test interaction between both the enable and disable filter environment variables. The enable should always
+// override the disable.
+TEST(ImplicitLayers, EnableAndDisableWithFilter) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* implicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* implicit_json_name_1 = "First_layer.json";
+ const char* disable_layer_name_1 = "DISABLE_FIRST";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment(disable_layer_name_1)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_1);
+
+ const char* implicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* implicit_json_name_2 = "Second_layer.json";
+ const char* disable_layer_name_2 = "DISABLE_SECOND";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment(disable_layer_name_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_2);
+
+ const char* implicit_layer_name_3 = "VK_LAYER_LUNARG_Second_test_layer";
+ const char* implicit_json_name_3 = "Second_test_layer.json";
+ const char* disable_layer_name_3 = "DISABLE_THIRD";
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(implicit_layer_name_3)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment(disable_layer_name_3)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ implicit_json_name_3);
+
+ // 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");
+
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Disable all but enable 2
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ InstWrapper inst5{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Disable implicit but enable all
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "~implicit~");
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+
+ InstWrapper inst6{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", implicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", implicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, implicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_LOADER_LAYERS_ENABLE");
+ remove_env_var("VK_LOADER_LAYERS_DISABLE");
+}
+
// Meta layer which contains component layers that do not exist.
TEST(MetaLayers, InvalidComponentLayer) {
FrameworkEnvironment env;
@@ -580,6 +1230,7 @@ TEST(MetaLayers, DeviceExtensionInComponentLayer) {
EXPECT_TRUE(string_eq(extensions[0].extensionName, device_ext_name));
}
}
+
// Override meta layer missing disable environment variable still enables the layer
TEST(OverrideMetaLayer, InvalidDisableEnvironment) {
FrameworkEnvironment env;
@@ -599,9 +1250,9 @@ TEST(OverrideMetaLayer, InvalidDisableEnvironment) {
.set_name(lunarg_meta_layer_name)
.set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0))
.add_component_layers({regular_layer_name})),
- "meta_test_layer.json");
+ "meta_test_layer.json");
- uint32_t layer_count = 0;
+ uint32_t layer_count = 0;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, nullptr));
EXPECT_EQ(layer_count, 1U);
@@ -612,7 +1263,7 @@ TEST(OverrideMetaLayer, InvalidDisableEnvironment) {
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
-}
+ }
// Override meta layer whose version is less than the api version of the instance
TEST(OverrideMetaLayer, OlderVersionThanInstance) {
@@ -790,7 +1441,7 @@ TEST(OverrideMetaLayer, NewerComponentLayerInMetaLayer) {
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
// Newer component is allowed now
- EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
env.debug_log.clear();
uint32_t count = 0;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
@@ -810,7 +1461,7 @@ TEST(OverrideMetaLayer, NewerComponentLayerInMetaLayer) {
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
// Newer component is allowed now
- EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
env.debug_log.clear();
uint32_t count = 0;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
@@ -979,7 +1630,7 @@ TEST(OverrideMetaLayer, BasicOverridePaths) {
inst.create_info.set_api_version(1, 1, 0);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
- ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+ ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
env.layers.clear();
}
@@ -1022,7 +1673,7 @@ TEST(OverrideMetaLayer, BasicOverridePathsIgnoreOtherLayers) {
inst.create_info.add_layer(regular_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 ") + regular_layer_name));
+ ASSERT_FALSE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
env.layers.clear();
}
@@ -1067,7 +1718,7 @@ TEST(OverrideMetaLayer, OverridePathsInteractionWithVK_LAYER_PATH) {
inst.create_info.add_layer(env_var_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_FALSE(env.debug_log.find(std::string("Insert instance layer \"") + env_var_layer_name));
env.layers.clear();
remove_env_var("VK_LAYER_PATH");
@@ -1112,7 +1763,7 @@ TEST(OverrideMetaLayer, OverridePathsEnableImplicitLayerInDefaultPaths) {
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.create_info.set_api_version(1, 1, 0);
inst.CheckCreate();
- ASSERT_FALSE(env.debug_log.find(std::string("Insert instance layer ") + implicit_layer_name));
+ ASSERT_FALSE(env.debug_log.find(std::string("Insert instance layer \"") + implicit_layer_name));
ASSERT_TRUE(
env.debug_log.find("Removing meta-layer VK_LAYER_LUNARG_override from instance layer list since it appears invalid."));
env.layers.clear();
@@ -1147,7 +1798,7 @@ TEST(OverrideMetaLayer, ManifestFileFormatVersionTooOld) {
inst.create_info.set_api_version(1, 1, 0);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
- ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+ ASSERT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
ASSERT_TRUE(env.debug_log.find("Indicating meta-layer-specific override paths, but using older JSON file version."));
env.layers.clear();
}
@@ -2558,7 +3209,7 @@ TEST(TestLayers, NewerInstanceVersionThanImplicitLayer) {
inst.create_info.set_api_version(1, 1, 0);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
- EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
env.debug_log.clear();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
@@ -2575,7 +3226,7 @@ TEST(TestLayers, NewerInstanceVersionThanImplicitLayer) {
inst.create_info.set_api_version(1, 2, 0);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
- EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer \"") + regular_layer_name));
env.debug_log.clear();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
@@ -2622,7 +3273,7 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
inst.create_info.set_api_version(1, 0, 0);
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
- EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(log.find(std::string("Insert instance layer \"") + regular_layer_name));
VkPhysicalDevice phys_dev = inst.GetPhysDev();
uint32_t count = 0;
@@ -2639,7 +3290,7 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
inst.create_info.set_api_version(1, 1, 0);
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
- EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(log.find(std::string("Insert instance layer \"") + regular_layer_name));
VkPhysicalDevice phys_dev = inst.GetPhysDev();
uint32_t count = 0;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
@@ -2656,7 +3307,7 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(log.find(std::string("Insert instance layer \"") + regular_layer_name));
uint32_t count = 0;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
EXPECT_EQ(1U, count);
@@ -2671,7 +3322,7 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
inst.create_info.set_fill_in_application_info(false);
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
- EXPECT_TRUE(log.find(std::string("Insert instance layer ") + regular_layer_name));
+ EXPECT_TRUE(log.find(std::string("Insert instance layer \"") + regular_layer_name));
VkPhysicalDevice phys_dev = inst.GetPhysDev();
uint32_t count = 0;
@@ -2686,7 +3337,7 @@ TEST(TestLayers, ImplicitLayerPre10APIVersion) {
// Verify that VK_INSTANCE_LAYERS work. To test this, make sure that an explicit layer does not affect an instance until
// it is set with VK_INSTANCE_LAYERS
-TEST(TestLayers, EnvironEnableExplicitLayer) {
+TEST(TestLayers, InstEnvironEnableExplicitLayer) {
FrameworkEnvironment env;
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
@@ -2775,6 +3426,780 @@ TEST(TestLayers, EnvironEnableExplicitLayer) {
remove_env_var("VK_INSTANCE_LAYERS");
}
+// Verify that VK_LOADER_LAYERS_ENABLE work. To test this, make sure that an explicit layer does not affect an instance until
+// it is set with VK_LOADER_LAYERS_ENABLE
+TEST(TestLayers, EnvironLayerEnableExplicitLayer) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* explicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* explicit_json_name_1 = "First_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_1);
+
+ const char* explicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* explicit_json_name_2 = "Second_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_2);
+
+ const char* explicit_layer_name_3 = "VK_LAYER_LUNARG_Second_test_layer";
+ const char* explicit_json_name_3 = "Second_test_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_3)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_3);
+
+ // First, test an instance/device without the layer forced on.
+ InstWrapper inst1{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Now force on one layer with its full name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", explicit_layer_name_1);
+
+ InstWrapper inst2{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match prefix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "VK_LAYER_LUNARG_*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match suffix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second_layer");
+
+ InstWrapper inst4{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match substring
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+
+ InstWrapper inst5{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with star '*'
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+
+ InstWrapper inst6{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with special name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "~all~");
+
+ InstWrapper inst7{env.vulkan_functions};
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_LOADER_LAYERS_ENABLE");
+}
+
+// Verify that VK_LOADER_LAYERS_DISABLE work. To test this, make sure that an explicit layer does not affect an instance until
+// it is set with VK_LOADER_LAYERS_DISABLE
+TEST(TestLayers, EnvironLayerDisableExplicitLayer) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* explicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* explicit_json_name_1 = "First_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_1);
+
+ const char* explicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* explicit_json_name_2 = "Second_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_2);
+
+ const char* explicit_layer_name_3 = "VK_LAYER_LUNARG_Second_test_layer";
+ const char* explicit_json_name_3 = "Second_test_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_3)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_3);
+
+ // First, test an instance/device without the layer forced on.
+ InstWrapper inst1{env.vulkan_functions};
+ inst1.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Now force on one layer with its full name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", 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);
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match prefix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "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);
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match suffix
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*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);
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match substring
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*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);
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with star '*'
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match all with special name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "~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);
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Match explicit special name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "~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);
+ FillDebugUtilsCreateDetails(inst8.create_info, env.debug_log);
+ inst8.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // No match implicit special name
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "~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);
+ FillDebugUtilsCreateDetails(inst9.create_info, env.debug_log);
+ inst9.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_LOADER_LAYERS_DISABLE");
+}
+
+// Verify that VK_LOADER_LAYERS_ENABLE + VK_LOADER_LAYERS_DISABLE work.(results in the layer still being
+// enabled)
+TEST(TestLayers, EnvironLayerEnableDisableExplicitLayer) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* explicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* explicit_json_name_1 = "First_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_1);
+
+ const char* explicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* explicit_json_name_2 = "Second_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_2);
+
+ const char* explicit_layer_name_3 = "VK_LAYER_LUNARG_Second_test_layer";
+ const char* explicit_json_name_3 = "Second_test_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_3)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_3);
+
+ // First, test an instance/device without the layer forced on.
+ InstWrapper inst1{env.vulkan_functions};
+ inst1.create_info.add_layer(explicit_layer_name_1).add_layer(explicit_layer_name_2).add_layer(explicit_layer_name_3);
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Disable all but enable 2
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*Second*");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst3.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst4.create_info, env.debug_log);
+ inst4.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst5.create_info, env.debug_log);
+ inst5.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // 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*");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst6.create_info, env.debug_log);
+ inst6.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ // Disable explicit but enable all
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "~explicit~");
+ set_env_var("VK_LOADER_LAYERS_ENABLE", "*");
+
+ 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);
+ FillDebugUtilsCreateDetails(inst7.create_info, env.debug_log);
+ inst7.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_3));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_3, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_LOADER_LAYERS_ENABLE");
+ remove_env_var("VK_LOADER_LAYERS_DISABLE");
+}
+
+// Verify that VK_INSTANCE_LAYERS + VK_LOADER_LAYERS_DISABLE work.(results in the layer still being
+// enabled)
+TEST(TestLayers, EnvironVkInstancdAndDisableFilters) {
+ FrameworkEnvironment env;
+ env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 2, 0)));
+ env.get_test_icd().icd_api_version = VK_MAKE_API_VERSION(0, 1, 2, 0);
+
+ const char* explicit_layer_name_1 = "VK_LAYER_LUNARG_First_layer";
+ const char* explicit_json_name_1 = "First_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_1)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_1);
+
+ const char* explicit_layer_name_2 = "VK_LAYER_LUNARG_Second_layer";
+ const char* explicit_json_name_2 = "Second_layer.json";
+ env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name(explicit_layer_name_2)
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))),
+ explicit_json_name_2);
+
+ // First, test an instance/device without the layer forced on.
+ InstWrapper inst1{env.vulkan_functions};
+ inst1.create_info.add_layer(explicit_layer_name_1);
+ FillDebugUtilsCreateDetails(inst1.create_info, env.debug_log);
+ inst1.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+
+ // Enable the non-default enabled layer with VK_INSTANCE_LAYERS
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_INSTANCE_LAYERS", explicit_layer_name_2);
+
+ InstWrapper inst2{env.vulkan_functions};
+ inst2.create_info.add_layer(explicit_layer_name_1);
+ FillDebugUtilsCreateDetails(inst2.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+
+ // Try to disable all
+ // ------------------------------------------
+ env.debug_log.clear();
+ set_env_var("VK_LOADER_LAYERS_DISABLE", "*");
+
+ InstWrapper inst3{env.vulkan_functions};
+ inst3.create_info.add_layer(explicit_layer_name_1);
+ FillDebugUtilsCreateDetails(inst3.create_info, env.debug_log);
+ inst2.CheckCreate();
+
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_1));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "forced enabled due to env var"));
+ ASSERT_TRUE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_1, "disabled because name matches filter of env var"));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Found manifest file", explicit_json_name_2));
+ ASSERT_TRUE(FindPrefixPostfixStringOnLine(env.debug_log, "Insert instance layer", explicit_layer_name_2));
+ ASSERT_FALSE(FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "forced enabled due to env var"));
+ ASSERT_FALSE(
+ FindPrefixPostfixStringOnLine(env.debug_log, explicit_layer_name_2, "disabled because name matches filter of env var"));
+
+ remove_env_var("VK_INSTANCE_LAYERS");
+ remove_env_var("VK_LOADER_LAYERS_DISABLE");
+}
+
// Add a device layer, should not work
TEST(TestLayers, DoNotUseDeviceLayer) {
FrameworkEnvironment env;
diff --git a/tests/loader_regression_tests.cpp b/tests/loader_regression_tests.cpp
index 7390596bd..fa8b0e4c0 100644
--- a/tests/loader_regression_tests.cpp
+++ b/tests/loader_regression_tests.cpp
@@ -1069,10 +1069,10 @@ TEST(TryLoadWrongBinaries, WrongExplicit) {
// Should get an error message for the explicit layer
#ifndef __APPLE__
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name) + std::string(" was wrong bit-type!")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" was wrong bit-type!")));
#else // __APPLE__
// Apple only throws a wrong library type of error
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name) + std::string(" failed to load!")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load!")));
#endif // __APPLE__
}
@@ -1106,10 +1106,10 @@ TEST(TryLoadWrongBinaries, WrongImplicit) {
#ifndef __APPLE__
// Should get an info message for the bad implicit layer
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name) + std::string(" was wrong bit-type.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" was wrong bit-type.")));
#else // __APPLE__
// Apple only throws a wrong library type of error
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name) + std::string(" failed to load.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load.")));
#endif // __APPLE__
}
@@ -1149,12 +1149,12 @@ TEST(TryLoadWrongBinaries, WrongExplicitAndImplicit) {
#ifndef __APPLE__
// Should get error messages for both (the explicit is second and we don't want the implicit to return before the explicit
// triggers a failure during vkCreateInstance)
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_0) + std::string(" was wrong bit-type!")));
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_1) + std::string(" was wrong bit-type.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" was wrong bit-type!")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" was wrong bit-type.")));
#else // __APPLE__
// Apple only throws a wrong library type of error
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_0) + std::string(" failed to load!")));
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_1) + std::string(" failed to load.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
#endif // __APPLE__
}
@@ -1193,12 +1193,12 @@ TEST(TryLoadWrongBinaries, WrongExplicitAndImplicitErrorOnly) {
#ifndef __APPLE__
// Should not get an error messages for either
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_0) + std::string(" was wrong bit-type!")));
- ASSERT_FALSE(log.find(std::string("Requested layer ") + std::string(layer_name_1) + std::string(" was wrong bit-type.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" was wrong bit-type!")));
+ ASSERT_FALSE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" was wrong bit-type.")));
#else // __APPLE__
// Apple only throws a wrong library type of error
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_0) + std::string(" failed to load!")));
- ASSERT_FALSE(log.find(std::string("Requested layer ") + std::string(layer_name_1) + std::string(" failed to load.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
+ ASSERT_FALSE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
#endif // __APPLE__
}
@@ -1230,7 +1230,7 @@ TEST(TryLoadWrongBinaries, BadExplicit) {
inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
// Should get an error message for the bad explicit
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name) + std::string(" failed to load!")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load!")));
}
TEST(TryLoadWrongBinaries, BadImplicit) {
@@ -1262,7 +1262,7 @@ TEST(TryLoadWrongBinaries, BadImplicit) {
inst.CheckCreate(VK_SUCCESS);
// Should get an info message for the bad implicit
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name) + std::string(" failed to load.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name) + std::string("\" failed to load.")));
}
TEST(TryLoadWrongBinaries, BadExplicitAndImplicit) {
@@ -1299,8 +1299,8 @@ TEST(TryLoadWrongBinaries, BadExplicitAndImplicit) {
inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
// Apple only throws a wrong library type of error
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_0) + std::string(" failed to load!")));
- ASSERT_TRUE(log.find(std::string("Requested layer ") + std::string(layer_name_1) + std::string(" failed to load.")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_0) + std::string("\" failed to load!")));
+ ASSERT_TRUE(log.find(std::string("Requested layer \"") + std::string(layer_name_1) + std::string("\" failed to load.")));
}
TEST(TryLoadWrongBinaries, WrongArchDriver) {
diff --git a/tests/loader_testing_main.cpp b/tests/loader_testing_main.cpp
index eb2c8f836..d1a3a09c9 100644
--- a/tests/loader_testing_main.cpp
+++ b/tests/loader_testing_main.cpp
@@ -55,6 +55,10 @@ int main(int argc, char** argv) {
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");
diff --git a/tests/loader_version_tests.cpp b/tests/loader_version_tests.cpp
index 3cf094c39..815c7bb07 100644
--- a/tests/loader_version_tests.cpp
+++ b/tests/loader_version_tests.cpp
@@ -855,8 +855,8 @@ TEST(LayerManifest, ImplicitNonVulkanVariant) {
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
- ASSERT_TRUE(log.find(std::string("Layer ") + implicit_layer_name +
- " has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
+ ASSERT_TRUE(log.find(std::string("Layer \"") + implicit_layer_name +
+ "\" has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
}
TEST(LayerManifest, ExplicitNonVulkanVariant) {
@@ -876,8 +876,8 @@ TEST(LayerManifest, ExplicitNonVulkanVariant) {
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0)).add_layer(explicit_layer_name);
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
- ASSERT_TRUE(log.find(std::string("Layer ") + explicit_layer_name +
- " has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
+ ASSERT_TRUE(log.find(std::string("Layer \"") + explicit_layer_name +
+ "\" has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
}
TEST(DriverManifest, UnknownManifestVersion) {