KhronosGroup / KhronosGroup/Vulkan-Loader
Relative path ICD is not deterministic, can return duplicate entry
- Dominant language
- C
- Stars
- 695
- Forks
- 343
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 17
Description
**Describe the bug**
I am helping conda-forge in integrating other directories for ICDs so that we can have:
1. THe system ICDs
2. The conda-forge installed ICDs
However, the problem is that the ubuntu ICD loader reads:
```
/usr/share/vulkan/icd.d $ cat intel_icd.json
{
"ICD": {
"api_version": "1.4.318",
"library_path": "libvulkan_intel.so"
},
"file_format_version": "1.0.1"
}
```
With conda installing its own `libvulkan_intel.so` this will eventually resolve to conda's version. My claim is that we can't do anything about this other than ask ubuntu to use the full path for ICD libraries (which they likely won't do)
Conda will also install its own icd.json file, to its own `${CONDA_PREFIX}/share/vulkan/icd.d`, and thus the same library will appear twice.
I think we should filter it out, just to keep the output less confusing.
- xref: https://github.com/conda-forge/vulkan-loader-feedstock/pull/35
- xref: https://github.com/conda-forge/mesalib-feedstock/pull/150
**Environment (please complete the following information):**
- OS: ubuntu 24 + conda(-forge)
- Bitdepth: 64bit
- GPU: intel (well anything really)
- Graphics Driver: mesa 26
- SDK or header version if building from repo: 1.4.357.0
- Enabled layers:
**To Reproduce**
```
diff --git a/loader/loader.c b/loader/loader.c
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -2145,6 +2145,31 @@
goto out;
}
+ // Skip a driver we have already scanned. Two different manifests can name the same
+ // library: a distribution manifest using a bare "library_path" resolved through the
+ // dynamic linker search path, and one using an absolute path, can both end up at the
+ // same file. The duplicate checks elsewhere in the loader only compare path strings,
+ // so nothing catches this and the driver is scanned twice, which reports every
+ // physical device it owns twice from vkEnumeratePhysicalDevices.
+ //
+ // dlopen/LoadLibrary returns the same handle for an object that is already loaded, so
+ // comparing handles identifies the duplicate exactly, without resolving paths or
+ // stat()ing anything. Keep the entry already in the list: the search order puts the
+ // more specific manifest first.
+ for (uint32_t i = 0; i < icd_tramp_list->count; i++) {
+ if (icd_tramp_list->scanned_list[i].handle == handle) {
+ loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "loader_scanned_icd_add: Driver %s is the same library as already loaded driver %s, skipping duplicate",
+ filename, icd_tramp_list->scanned_list[i].lib_name);
+ // Release the reference the open above took; the existing entry owns the one
+ // that loader_scanned_icd_clear will release.
+ loader_platform_close_library(handle);
+ handle = NULL;
+ res = VK_SUCCESS;
+ goto out;
+ }
+ }
+
// Try to load the driver's exported vk_icdNegotiateLoaderICDInterfaceVersion
fp_negotiate_icd_version = loader_platform_get_proc_address(handle, "vk_icdNegotiateLoaderICDInterfaceVersion");
```
**VK_LOADER_DEBUG output**
Attach output when running with the environment variable VK_LOADER_DEBUG=all
**Additional context**
Contributor guide
Research direction
Start in loader/loader.c around the ICD scanning code shown in the reproduction, especially loader_scanned_icd_add. Reproduce the Ubuntu and conda-forge manifests with VK_LOADER_DEBUG=all, then verify that manifests resolving to the same library produce one driver and one set of physical devices rather than duplicates.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100