关于Vulkan的physical device(物理设备)

Number of views 17

我正在通过 API 规范 学习 Vulkan,但对 Vulkan 中的物理设备部分有些困惑。我的电脑只有一块 Intel 的物理显卡,但 vkEnumeratePhysicalDevices 返回的结果却显示有 2 个物理设备。这两个设备看起来是相同的,但它们的队列标志(queue flags)似乎有所不同,并且这些标志没有完全文档化(实际上文档中只解释到了标志 8,而在第二个队列中,我看到的标志值是 16 和 32)。

以下是 VkQueueFlagBits 的定义:

typedef enum VkQueueFlagBits {
VK_QUEUE_GRAPHICS_BIT = 0x00000001, // 图形队列
VK_QUEUE_COMPUTE_BIT = 0x00000002, // 计算队列
VK_QUEUE_TRANSFER_BIT = 0x00000004, // 转移队列
VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008, // 稀疏绑定队列
} VkQueueFlagBits;

这是我的 Vulkan 代码输出结果:

GPU count: 2 ( physical devices )
Physical Device 0:
        Device API version: 1.0.42 - 4194346
        Device Vendor Id: 0x8086
        Device Id: 1916
        Device Driver version: 0.0.1 - 1
        Device type: 1
        Device Name: Intel(R) HD Graphics 520 (Skylake GT2)
        Device Pipeline UID: f557cfd4
        Queue Properties:
                Flags: 7
                Count: 1
                ts Valid Bits: 24
Physical Device 1:
        Device API version: 1.0.42 - 4194346
        Device Vendor Id: 0x8086
        Device Id: 1916
        Device Driver version: 0.0.1 - 1
        Device type: 1
        Device Name: Intel(R) HD Graphics 520 (Skylake GT2)
        Device Pipeline UID: f557cfd4
        Queue Properties:
                Flags: 49
                Count: 0
                ts Valid Bits: 1

有人可以帮我理解下为什么同一个实际设备会返回两个物理设备,以及那些未记录的标志是什么吗?

2 Answers

在 Vulkan 中,vkEnumeratePhysicalDevices 函数返回的是系统中的所有物理设备,这包括了所有可能支持 Vulkan API 的硬件设备。即使你的系统中只有一个显卡,它也可能包含多个物理设备。这些物理设备通常指的是不同的 GPU 实例或 GPU 功能集。

从你提供的信息来看,你系统中返回的两个物理设备实际上是同一个显卡的不同功能集合。具体来说:

  1. 物理设备 0:这个设备的队列标志为 7,这意味着它支持图形队列、计算队列和转移队列(VK_QUEUE_GRAPHICS_BIT, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT)。队列计数为 1,表示该设备有一个队列家族,支持上述三种类型的队列。

  2. 物理设备 1:这个设备的队列标志为 49,即 0x31(二进制表示为 111001),这意味着它支持图形队列、稀疏绑定队列和一个未知的队列类型(可能是某种扩展功能)。队列计数为 0,表示该设备没有队列家族。

队列标志解释

  • 7 (0b00000111) 表示支持图形队列、计算队列和转移队列。
  • 49 (0b110001) 表示支持图形队列、稀疏绑定队列和另一个未知的队列类型。

为什么会有两个物理设备

尽管你的系统中只有一个显卡,但显卡内部可能有不同的硬件单元或功能集合。例如,某些 GPU 可能有专门用于稀疏绑定操作的硬件,或者有一些特定的功能不直接与传统的图形/计算/转移队列相关联。这些不同的功能集合可能会被 Vulkan 视为不同的物理设备。

如何处理

当你在创建 Vulkan 设备时,需要选择一个物理设备及其对应的队列家族。你可以选择第一个物理设备(支持图形、计算和转移队列),或者根据你的应用需求选择第二个物理设备(如果它提供了你需要的特定功能)。

如果你的应用不需要稀疏绑定或其他特殊功能,通常选择第一个物理设备就足够了。确保在创建 Vulkan 设备时指定正确的队列家族和队列计数即可。

总结

  • 物理设备 0 支持图形、计算和转移队列。
  • 物理设备 1 支持图形和稀疏绑定队列(以及一个未知的队列类型)。

你可以根据应用的需求选择合适的物理设备。

兄弟,你是不是在stackflow直接搬过来的呀?算了,我也搬运下吧。

第二个设备的 count=0 很奇怪。更严重的是,它的 flagstsVB 值已损坏(flags49 是无效值,tsVB1 也是无效的)。

这基本可以确定,你的系统上有一个多余的 *.json 文件。

这些 *.json 文件存储了机器上存在的 安装式客户端驱动(ICD) 的信息。它们通常存放在标准路径下。

vkEnumeratePhysicalDevicesvkGetPhysicalDeviceProperties 是相对简单的命令,其作用基本上只是读取这些 *.json 文件并返回其内容。不过我认为,如果调用更“实际”的操作(比如 vkCreateDevice),在安装错误的驱动上是无法工作的。

具体是什么原因导致了这个问题,需要进一步查看。首先,在 Linux 发行版中,通常可以通过命令查询某个文件属于哪个软件包。这很可能是由于之前驱动的清理不彻底,或者是新驱动安装脚本的 bug。之前至少有一人遇到过类似问题。

根据我的解释,我认为这是一个相对无害的 bug。第一个设备应该可以正常工作,你可以直接忽略第二个设备。或者直接删除其对应的 *.json 清单文件,防止它在 vkEnumeratePhysicalDevices 中显示。

  1. 检查 /usr/share/vulkan/icd.d/~/.local/share/vulkan/icd.d/ 目录,删除可疑的 JSON 文件。
  2. 使用 dpkg -S <文件名>(Debian/Ubuntu)或 rpm -qf <文件名>(Fedora/RHEL)查找文件所属的软件包,判断是否需要卸载冲突的驱动包。
  3. 如果问题由旧驱动残留引起,清理后重启系统即可。