Vulkan API 调用 GPU 驱动程序

Vulkan API calls to GPU drivers

背景:
我一直在关注编写一个需要非常基本但快速的图形的应用程序(只是绘制线条和正方形),如果我要使用 Rust,我可能会使用诸如 GLFW 或 Vulkano 之类的库。

我想了解 Vulkan API 的具体细节,我想这很实用。我知道 GPU 可能是一个相当复杂的话题,但我想强调的是,我没有任何 low-level 图形或 Vulkan 的背景知识,所以我理解如果我的问题无法得到解答,或者我的问题没有甚至有道理。我会尽力使用正确的术语。我不得不承认,我不是最擅长浏览和查看大量我不太了解的源代码并且仍然掌握整体概念的人,这就是为什么我希望能在这里找到我的答案。我试过查看 Vulkan 和 Mesa drivers 的源代码,但没有结果。

原始问题:
我想了解 API 调用如何传播到 GPU driver。

我四处搜索,但找不到我要搜索的具体内容。我找到的最接近的帖子是这两个:
https://softwareengineering.stackexchange.com/questions/279069/how-does-a-program-talk-to-a-graphics-card
https://superuser.com/questions/461022/how-does-the-cpu-and-gpu-interact-in-displaying-computer-graphics

他们都提到了类似于“为了让 GPU 做某事,你必须通过支持的 API 进行调用”的内容。我知道这一点,但两者都没有深入研究 API 调用的具体细节。希望下图能说明我的问题。

MyVulkanProgram.c with "#include <vulkan/vulkan.h>"
|
| (Makes call via Vulkan API)
v
This is the part I don't understand!
|
v
Driver (Mesa, for example) takes the request sent via the Vulkan API.
|
| (Driver asks GPU to perform task)
v
GPU does task

我不关心 GPU 做什么或如何做某事。它是如何通过 Vulkan 通过 API 调用调用的,以及它是如何在系统中传播的。理想情况下,我正在寻找的是 code-snippet 或 link 到 Vulkan 源代码中实际请求发送到 driver.

的位置

还是我都弄错了? Vulkan 是否比我意识到的更像是 driver 的一部分? driver 是否包含与我的“MyVulkanProgram.c”相同的 Vulkan header 并且 driver 与库文件 link 一起编辑,例如libvulkan.so 等人?是不是更像下图?

MyVulkanProgram.c with "#include <vulkan/vulkan.h>"
|
| (Makes call via Vulkan API)
v
Driver (Mesa, for example, which includes the vulkan headers and is linked with the Vulkan shared object-files) takes the request sent via the Vulkan API.
|
| (Driver asks GPU to perform task)
v
GPU does task

可能是一个基本问题,也可能不是,但我还是很困惑。非常感谢任何答案!

更新问题:
在阅读@krOoze () 的回答,并给出上述文档中的“Vulkan loader”概览图后,我可以更准确地表达我的问题。

通过 Vulkan API 进行调用的应用程序如何通过 Vulkan 加载程序到达 ICD?

您正在查找 Vulkan-Loader/LoaderAndLayerInterface.md 文档。

该应用程序与 The Loader(有时称为 Vulkan RT,或 Vulkan Runtime)交互。即vulkan-1.dll(或so)。

Loader还有vulkan-1.lib,这是经典的dll shim。这是加载核心版本和 WSI 命令的地方,但您可以跳过 lib 并使用 vkGetInstanceProcAddr.

直接从 dll 手动完成所有操作

那么你就有了 ICD(可安装的客户端驱动程序)。这些类似于 nvoglv64.dll,您可以在 PC 上安装更多(例如 Intel iGPU + NV)。该名称是任意的且特定于供应商。加载程序通过配置文件找到它们。

现在,当您对通过 vkGetInstanceProcAddress 获得的命令调用某些内容时(如果仅使用 *.lib,这就是一切),您将进入加载器蹦床,它调用层链,之后调用相关的 ICD(或所有 ICD)。然后调用堆栈被解开,所以它走向另一个方向,直到返回到应用程序。加载程序互斥并将输入和输出合并到 ICD。

通过 vkGetDeviceProcAddress 获得的命令更加精简,因为它们不需要互斥或合并,并且无需加载程序的太多干预就可以传递给 ICD。

代码也在同一个仓库中:trampoline.c, and loader.c。这很简单;每一层只是调用它下面的层。从蹦床开始,到终止层结束,终止层又将调用 ICD 层。