Use a nested Vulkan Loader when GFXSTREAM_VK_ env var found
... and add script to build a version of the Vulkan Loader which
uses "GFXSTREAM" prefixed env vars and logging.
Bug: b/315317383
Test: deqp-vk w/ Gfxstream ICD
Change-Id: I7202379dbc27a9519b55434e889139810078020d
diff --git a/host/vulkan/VulkanDispatch.cpp b/host/vulkan/VulkanDispatch.cpp
index 7d0fedc..7d2b6a5 100644
--- a/host/vulkan/VulkanDispatch.cpp
+++ b/host/vulkan/VulkanDispatch.cpp
@@ -183,18 +183,56 @@
void initialize(bool forTesting);
static std::vector<std::string> getPossibleLoaderPathBasenames() {
- return std::vector<std::string>{
#if defined(__APPLE__)
- "libvulkan.dylib"
-#elif defined(__linux)
- "libvulkan.so",
- "libvulkan.so.1",
+ return std::vector<std::string>{"libvulkan.dylib"};
+#elif defined(__linux__)
+ // When running applications with Gfxstream as the Vulkan ICD, i.e. with
+ //
+ // App -> Vulkan Loader -> Gfxstream ICD -> Vulkan Loader -> Driver ICD
+ //
+ // Gfxstream needs to use a different nested loader library to avoid issues with
+ // conflating/deadlock with the first level loader. Detect that here and look for
+ // a "libvulkan_gfxstream" which can be generated with the provided
+ // scripts/build-nested-vulkan-loader.sh script.
+ const std::vector<std::string> nestedVulkanLoaderVars = {
+ "GFXSTREAM_VK_ADD_DRIVER_FILES",
+ "GFXSTREAM_VK_ADD_LAYER_PATH",
+ "GFXSTREAM_VK_DRIVER_FILES",
+ "GFXSTREAM_VK_ICD_FILENAMES",
+ "GFXSTREAM_VK_INSTANCE_LAYERS",
+ "GFXSTREAM_VK_LAYER_PATH",
+ "GFXSTREAM_VK_LAYER_PATH",
+ "GFXSTREAM_VK_LOADER_DEBUG",
+ "GFXSTREAM_VK_LOADER_DRIVERS_DISABLE",
+ "GFXSTREAM_VK_LOADER_DRIVERS_SELECT",
+ "GFXSTREAM_VK_LOADER_LAYERS_ALLOW",
+ "GFXSTREAM_VK_LOADER_LAYERS_DISABLE",
+ "GFXSTREAM_VK_LOADER_LAYERS_ENABLE",
+ };
+ bool usesNestedVulkanLoader = false;
+ for (const std::string& var : nestedVulkanLoaderVars) {
+ if (android::base::getEnvironmentVariable(var) != "") {
+ usesNestedVulkanLoader = true;
+ break;
+ }
+ }
+ if (usesNestedVulkanLoader) {
+ return std::vector<std::string>{
+ "libvulkan_gfxstream.so",
+ "libvulkan_gfxstream.so.1",
+ };
+ } else {
+ return std::vector<std::string>{
+ "libvulkan.so",
+ "libvulkan.so.1",
+ };
+ }
+
#elif defined(_WIN32)
- "vulkan-1.dll"
+ return std::vector<std::string>{"vulkan-1.dll"};
#else
#error "Unhandled platform in VulkanDispatchImpl."
#endif
- };
}
std::vector<std::string> getPossibleLoaderPaths() {
diff --git a/scripts/build-nested-vulkan-loader.sh b/scripts/build-nested-vulkan-loader.sh
new file mode 100755
index 0000000..b67362e
--- /dev/null
+++ b/scripts/build-nested-vulkan-loader.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+# Copyright 2023 The Android Open Source Project
+#
+# 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.
+
+set -o errexit
+
+WORKING_DIRECTORY="/tmp/gfxstream-nested-vulkan-loader"
+if [ ! -z "$1" ]; then
+ WORKING_DIRECTORY=$1
+fi
+
+if [ ! -d $WORKING_DIRECTORY ]; then
+ echo "Creating working directory $WORKING_DIRECTORY."
+ mkdir -p $WORKING_DIRECTORY
+ cd $WORKING_DIRECTORY
+ git clone https://github.com/KhronosGroup/Vulkan-Loader.git .
+ git checkout -b v1.3.273 tags/v1.3.273
+else
+ echo "Reusing existing working directory $WORKING_DIRECTORY."
+ cd $WORKING_DIRECTORY
+fi
+
+echo "Applying edits for Gfxstream."
+VK_LOADER_ENV_VARS=(
+ "VK_ADD_DRIVER_FILES"
+ "VK_ADD_LAYER_PATH"
+ "VK_DRIVER_FILES"
+ "VK_ICD_FILENAMES"
+ "VK_INSTANCE_LAYERS"
+ "VK_LAYER_PATH"
+ "VK_LAYER_PATH"
+ "VK_LOADER_DEBUG"
+ "VK_LOADER_DRIVERS_DISABLE"
+ "VK_LOADER_DRIVERS_SELECT"
+ "VK_LOADER_LAYERS_ALLOW"
+ "VK_LOADER_LAYERS_DISABLE"
+ "VK_LOADER_LAYERS_ENABLE"
+)
+for var in ${VK_LOADER_ENV_VARS[@]}; do
+ echo "- Replacing occurrences of \"$var\" with \"GFXSTREAM_$var\"."
+ sed -i -e "s/\\\"$var\\\"/\\\"GFXSTREAM_$var\\\"/g" loader/*.c
+ sed -i -e "s/\\\"$var\\\"/\\\"GFXSTREAM_$var\\\"/g" loader/*.h
+done
+echo "- Adding in \"GFXSTREAM\" prefix to logging."
+sed -i -e "s/ fputs(cmd_line_msg, stderr);/ fputs(\\\"GFXSTREAM-LOADER: \\\", stderr); fputs(cmd_line_msg, stderr);/g" loader/log.c
+
+if [ ! -d build ]; then
+ echo "Creating build directory."
+ mkdir build
+ cd build
+ python ../scripts/update_deps.py
+ cmake -C helper.cmake -D CMAKE_BUILD_TYPE=Debug ..
+else
+ echo "Reusing existing build directory."
+ cd build
+fi
+
+echo "Building."
+cmake --build .
+
+cp loader/libvulkan.so loader/libvulkan_gfxstream.so
+
+echo "Use export LD_LIBRARY_PATH=\"\$LD_LIBRARY_PATH:$(pwd)/loader\" to add to your path."