VK_LUNARG_direct_driver_loading
添加一个扩展,允许应用程序在实例创建期间向加载器提供驱动程序。
1. 问题陈述
有几种用例导致应用程序希望自带驱动程序。在许多 Web 浏览器中,添加备用 CPU 驱动程序对于支持不支持 Vulkan 的硬件是必要的,并且对于可能没有硬件可用的测试基础设施也是必要的。虽然目前有几种桌面 Vulkan 加载器机制允许应用程序提供驱动程序,但它们都存在各种缺点。下面详细介绍了一个不全面的列表。
-
有些需要运行安装程序。这需要卸载程序,并使驱动程序对系统或用户“全局化”。
-
它们可能需要提升的权限才能使用,例如使用安装程序,或者在以提升的权限运行时会导致解决方案失败,例如使用环境变量。
2. 当前解决方案空间
-
安装到操作系统特定位置
-
需要运行显式安装程序和卸载程序
-
对所有应用程序全局
-
在大多数情况下需要提升的权限
-
-
环境变量
-
由于安全问题,在以提升的权限运行时禁用
-
设置繁琐,因为它们需要驱动程序清单的完整路径
-
-
MacOS 包 - 允许将 .dylib 放置在可重定位的包中,加载器知道如何在其中查找
-
不适用于任何其他平台
-
-
在当前工作目录中查找
-
当以提升的权限运行时禁用,因为这是一种攻击媒介
-
3. 提议
VK_LUNARG_direct_driver_loading
扩展了 VkInstanceCreateInfo 的 pNext 链,以提供一个结构列表,其中包含加载器加载驱动程序所需的信息。这是通过提供驱动程序的 vkGetInstanceProcAddr 实现的,绕过了加载器使用系统动态链接器加载驱动程序函数的需求。
该扩展还允许应用程序专门使用提供的驱动程序,因此不会加载系统上找到的任何驱动程序。
这满足了要求
-
与所有其他正在运行的进程隔离。
-
无需安装。
-
当应用程序以提升的权限运行时有效。
该扩展的目的是在桌面 Vulkan 加载器中实现。
typedef struct VkDirectDriverLoadingInfoLUNARG {
VkStructureType sType;
const void* pNext;
VkDirectDriverLoadingFlagsLUNARG flags;
PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
} VkDirectDriverLoadingInfoLUNARG;
typedef struct VkDirectDriverLoadingListLUNARG {
VkStructureType sType;
const void* pNext;
VkDirectDriverLoadingModeLUNARG mode;
uint32_t driverCount;
const VkDirectDriverLoadingInfoLUNARG* pDrivers;
} VkDirectDriverLoadingListLUNARG;
typedef enum VkDirectDriverLoadingModeLUNARG {
VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG = 0,
VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG = 1,
VK_DIRECT_DRIVER_LOADING_MODE_MAX_ENUM_LUNARG = 0x7FFFFFFF
} VkDirectDriverLoadingModeLUNARG;
VkDirectDriverLoadingModeLUNARG
允许应用程序选择仅加载它们提供的驱动程序,还是将它们提供的驱动程序与 Vulkan 加载器在系统上找到的所有驱动程序一起加载。
此扩展存在已知缺陷。当应用程序查询实例扩展列表时,无法向 Vulkan 加载器提供应用程序提供的驱动程序列表,以将驱动程序的扩展与系统上驱动程序和隐式层支持的扩展相结合。作为一种解决方法,应用程序可以从提供的驱动程序加载 vkEnumerateInstanceExtensionProperties 入口点,以获取它们的扩展列表。
当所有以下条件都为真时,此解决方法存在已知缺陷
-
应用程序使用 VK_LUNARG_direct_driver_loading 来添加驱动程序。
-
一个层(将被启用)在调用 vkEnumerateInstanceExtensionProperties 入口点期间过滤掉不支持的扩展。
-
应用程序在 VkInstanceCreateInfo 中启用了应用程序提供的驱动程序支持但层不支持的实例扩展。
由于应用程序直接调用驱动程序的 vkEnumerateInstanceExtensionProperties,而不是加载程序的,这会阻止层修改扩展列表。由于层将无法过滤掉不支持的实例扩展,该层可能无法工作、在其他地方导致错误或崩溃。
4. 示例用法
此示例展示了典型的用法,其中提供的驱动程序应该是唯一找到的驱动程序。它使用 VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG
来防止加载程序加载系统上的任何驱动程序,这对于在测试条件下运行时很有用。
VkDirectDriverLoadingInfoLUNARG app_provided_driver{};
app_provided_driver.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
app_provided_driver.pfnGetInstanceProcAddr = /* address of drivers function pointer*/
VkDirectDriverLoadingListLUNARG direct_driver_loading{};
direct_driver_loading.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
direct_driver_loading.mode = VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG; // Do not load any other drivers
direct_driver_loading.driverCount = 1;
direct_driver_loading.pDrivers = &app_provided_driver;
VkInstanceCreateInfo instance_info{};
instance_info.pNext = &direct_driver_loading;
vkCreateInstance(&instance_info, NULL, inst);
5. 问题
5.1. 已解决:全局函数不可扩展
由于此提案允许添加驱动程序,并且 vkEnumerateInstanceExtensionProperties 返回系统上驱动程序支持的扩展列表,因此应用程序必须“知道”所提供的驱动程序支持哪些扩展,或者直接查询它们,然后在 VkInstanceCreateInfo 中手动启用这些扩展。虽然对于大多数用例来说,这是一个足够的解决方案,但当存在修改实例扩展列表的层时,它会产生一个边缘情况。从根本上说,这是扩展枚举和实例创建设计的问题。虽然可以向此扩展添加解决此问题的功能,但最好使用其自身的扩展来解决,因为实例创建存在比此扩展所能解决的更多问题。