KhronosGroup / MoltenVK

MoltenVK is a Vulkan Portability implementation. It layers a subset of the high-performance, industry-standard Vulkan graphics and compute API over Apple's Metal graphics framework, enabling Vulkan applications to run on macOS, iOS and tvOS.
Apache License 2.0
4.64k stars 402 forks source link

Incorrect ICD Path Resolution when loaded from After FX Plugin #2165

Closed mmdurrant closed 4 months ago

mmdurrant commented 4 months ago

BACKGROUND: libVulkan is a dependency of an Adobe After Effects plugin. After Effects loads plugins at runtime via dlopen.
PROBLEM: This is actually 2-fold. The spec says that the loader looks in <bundle>/Contents/Resources/vulkan for layer and driver manifests. Which as you can see in the log below - it does. The problem is <bundle> in this case is After Effects and not the path of our plugin bundle as we would hope and expect.

INFO:             Portability enumeration bit was set, enumerating portability drivers.
LAYER:            Searching for layer manifest files
LAYER:               In following locations:
LAYER:                  /Applications/Adobe After Effects 2023/Adobe After Effects 2023.app/Contents/Resources/vulkan/implicit_layer.d
LAYER:                  /$HOMEDIR/.config/vulkan/implicit_layer.d
LAYER:                  /etc/xdg/vulkan/implicit_layer.d
LAYER:                  /Users/lunarg/Dev/macos-sdk-build/Vulkan-Loader/build/install/etc/vulkan/implicit_layer.d
LAYER:                  /etc/vulkan/implicit_layer.d
LAYER:                  /$HOMEDIR/.local/share/vulkan/implicit_layer.d
LAYER:                  /usr/local/share/vulkan/implicit_layer.d
LAYER:                  /usr/share/vulkan/implicit_layer.d
LAYER:               Found no files
LAYER:            Searching for layer manifest files
LAYER:               In following locations:
LAYER:                  /Applications/Adobe After Effects 2023/Adobe After Effects 2023.app/Contents/Resources/vulkan/explicit_layer.d
LAYER:                  /$HOMEDIR/.config/vulkan/explicit_layer.d
LAYER:                  /etc/xdg/vulkan/explicit_layer.d
LAYER:                  /Users/lunarg/Dev/macos-sdk-build/Vulkan-Loader/build/install/etc/vulkan/explicit_layer.d
LAYER:                  /etc/vulkan/explicit_layer.d
LAYER:                  /$HOMEDIR/.local/share/vulkan/explicit_layer.d
LAYER:                  /usr/local/share/vulkan/explicit_layer.d
LAYER:                  /usr/share/vulkan/explicit_layer.d
LAYER:               Found no files
DRIVER:           Searching for driver manifest files
DRIVER:              In following locations:
DRIVER:                 /Applications/Adobe After Effects 2023/Adobe After Effects 2023.app/Contents/Resources/vulkan/icd.d
DRIVER:                 /$HOMEDIR/.config/vulkan/icd.d
DRIVER:                 /etc/xdg/vulkan/icd.d
DRIVER:                 /Users/lunarg/Dev/macos-sdk-build/Vulkan-Loader/build/install/etc/vulkan/icd.d
DRIVER:                 /etc/vulkan/icd.d
DRIVER:                 /$HOMEDIR/.local/share/vulkan/icd.d
DRIVER:                 /usr/local/share/vulkan/icd.d
DRIVER:                 /usr/share/vulkan/icd.d
DRIVER:              Found no files
ERROR | DRIVER:   vkCreateInstance: Found no drivers!

BUT the log file tells us a few locations where we can put the files! We drop our trusty MoltenVK_icd.json file in $USER/.config/vulkan/icd.d. And we're off to the races!

DRIVER:           Found ICD manifest file /$HOMEDIR/.config/vulkan/icd.d/MoltenVK_icd.json, version 1.0.0
DEBUG | DRIVER:   Searching for ICD drivers named ../../../Frameworks/libMoltenVK.dylib
ERROR:            dlopen(/$HOMEDIR/.config/vulkan/icd.d/../../../Frameworks/libMoltenVK.dylib, 0x0005): tried: '/$HOMEDIR/.config/vulkan/icd.d/../../../Frameworks/libMoltenVK.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/$HOMEDIR/.config/vulkan/icd.d/../../../Frameworks/libMoltenVK.dylib' (no such file), '/$HOMEDIR/.config/vulkan/icd.d/../../../Frameworks/libMoltenVK.dylib' (no such file)
ERROR | DRIVER:   loader_icd_scan: Failed loading library associated with ICD JSON /$HOMEDIR/.config/vulkan/icd.d/../../../Frameworks/libMoltenVK.dylib. Ignoring this JSON
ERROR | DRIVER:   vkCreateInstance: Found no drivers!```

*sad trombone*.  But wait! If we point it at where it should be able to find `libMoltenVK.dylib`, it works! 

```{
    "file_format_version": "1.0.0",
    "ICD": {
        "library_path": "/Applications/Adobe After Effects 2023/Plug-ins/Vulkanator.plugin/Contents/Frameworks/libMoltenVK.dylib",
        "api_version": "1.2.0",
        "is_portability_driver": true
    }
}

It also works flawlessly if I have the Vulkan SDK installed. It finds the ICD in the usual place in /usr/local/share and gets the MoltenVK path from there.

In theory, I could set an environment variable to tell the loader the right path to the ICD and do the hacky thing I did in the JSON above and have it work. I talked to some folks in the official Vulkan Discord and they recommend I create an issue here to see if perhaps there is a better solution.

For reference, here is the plugin in question:

https://github.com/Wunkolo/Vulkanator

Please let me know if I can provide more info. Thanks!

cdavis5e commented 4 months ago

OK... what do you want us to do? We can't really control the way the OS loads the MoltenVK dylib, nor the way the Vulkan loader goes about searching for ICD descriptions and loading the corresponding ICDs. All of that happens before MoltenVK gets to execute any code.

If I may make a suggestion, have you tried using a pathname relative to @loader_path in the ICD description? This is a special dyld(1) variable used in dependencies that expands to the directory containing the binary that requested the load. I don't know if it will work with dlopen(3), but it might be worth a shot.

In any case, this would seem to be a problem with the Vulkan loader. You should probably file this on that project.

mmdurrant commented 4 months ago

I was expecting a response close to this. I wasn't certain if it was a Vulkan Loader issue or specific to MoltenVK and appreciate the clarity there. Thank you for the clear direction.

What I ended up doing - I thought it was important to share my solution because this comes up in search results - the loader allows specification of the driver ICD JSON path by way of VK_DRIVER_FILES environment variable. I used dladdr to locate the path to my library and was able to locate my bundle's Resources directory from there. I used setenv to specify the environment variable and everything works as I would hope. This ensures the loader is able to correctly locate the manifest and everything works as we would hope.

Closing issue per @cdavis5e - this is not a problem that can be resolved in MoltenVK and must be resolved by informing the loader of additional path locations via VK_DRIVER_FILES.