在Vulkan中,我们有两个需要使用dlopen / LoadLibrary加载的全局函数。它们是vkGetInstanceProcAddr和vkGetDeviceProcAddr。
我有一个gpu并安装了vulkan驱动程序。我应该在运行时或链接时更好地加载库吗?我给差异逻辑设备(从相同的gpu创建)到vkGetDeviceProcAddr以查询相同的函数。他们都给我回复了同样的地址。我认为重新加载可能会浪费。
我的问题是这个想法是如何产生的?它是多实现还是多gpus?
我的加载器功能目前如下:
class VulkanDevice
{
public:
VkDevice m_Device;
void LoadAllCoreFunctions();
void LoadExtension(const char *name);
void LoadExtensions(const char *postfix); // for example: "KHR"
PFN_vkCreateCommandBuffers vkCreateCommandBuffers;
// Then a lot of function pointers.....
}
int main() {
// After creating instance and creating device with vkCreateDevice
VulkanDevice vkd(device);
vkd.LoadAllCoreFunctions();
vkd.vkCreateCommandBuffers(vkd.m_Device, ....);
}
正如你所看到的,如果我有多个设备,那么重新加载会非常浪费...而且函数指针也可能会占用大量内存....
答案 0 :(得分:4)
"实例函数指针和#34;之间的区别和"设备功能指针"适用于需要更快的函数调用性能的人。
只有vkGetInstanceProcAddr
才能使用Vulkan。此函数将检索所有 Vulkan函数的函数指针。这些函数指针将使用存储在您传递的各种Vulkan对象中的调度信息,以确定您正在与之通信的设备。这些指针可以与任何实例,设备或设备相关对象一起使用。
您从vkGetDeviceProcAddr
获得的指示知道他们使用特定设备。他们不需要使用调度逻辑来调用该设备。所以他们会略低一些。缺点是您只能 将它们与特定的VkDevice
或设备派生对象一起使用。
对于大多数人来说,调度开销可能不会非常重要。如果你真的关心这些事情,你可以选择避免它。
如果我有多个设备,重新加载将非常浪费...而且函数指针也可能使用大量内存....
无论你是否查询指针,这些函数都存在;因此获取它们的指针只会占用用于存储指针的内存。 Vulkan的API包含大约140个函数。每个函数指针8个字节,即1120个字节,仅超过1KB。
至于加载它们的时间......如果加载140个函数指针花费的时间超过几个微秒,我会感到震惊。你在启动时做一次。
答案 1 :(得分:4)
在Vulkan中,我们有两个需要使用dlopen / LoadLibrary加载的全局函数。它们是vkGetInstanceProcAddr和vkGetDeviceProcAddr。
错误。只有1个}}。 vkGetInstanceProcAddr
本身可以从vkGetDeviceProcAddr
加载。
从我应该在运行时或链接时更好地加载库吗?我给差异逻辑设备(从相同的gpu创建)到vkGetDeviceProcAddr以查询相同的函数。他们都给我同样的地址。
vkGetInstanceProcAddr
获取的命令的 VkInstance
仅限于用于获取命令的vkGetInstanceProcAddr
。
同样,从instance
获得的命令只能用于获取它们的vkGetDeviceProcAddr
(类型为VkDevice)。
他们可能,而且往往是相同的,但你不能提前知道,并在每个平台/ PC上以这种方式工作。你可以只加载单个命令,测试它是同一个指针并推断其他指针也是如此 - 但是这样做很少,没有合理的好处。
为方便起见,请在与官方装载机的链接时间进行,除非您有理由不这样做。
我认为重新加载可能会浪费。
除非您计划使用数百万个不断连接和断开连接的GPU来制作硬件,否则请不要担心并正确加载命令。这是一个很小的一个(或几个)时间成本,它将在你无疑会做的所有渲染中快速摊销。
也没有“重装”。新指针可以与旧指针和平共存。在C ++中,您可能会创建实例或设备的成员函数...
我的问题是这个想法是如何产生的?它是多实现还是多gpus?
是的,有点。
你肯定会看到,如果你有两个GPU(来自不同的供应商),使用不同的驱动程序文件(通常是一些* .dll或其他平台上的等价物),那么必须以某种方式选择指向正确文件的指针。
device
解决它,以便它为您提供指向另一个选择并调用右指针的函数的指针。 (“一切都可以通过另一层次的间接解决”,对吧?)。静态加载Khronos / Official / LunargSDK加载器可能会做类似的事情。
要vkGetInstanceProcAddr
,您只需提供确切的设备,反过来它只会为您提供指向该特定GPU驱动程序的直接函数指针。
实例也可能发生(加载器必须只导出vkGetDeviceProcAddr
,其余的可以在其他地方)。虽然通常(如在Loader的情况下)它导出所有实例级甚至间接设备级函数指针以方便使用。
正如你所看到的,如果我有多个设备,那么重新加载会非常浪费...而且函数指针也可能会占用大量内存....
如前所述,并没有那么多CPU时间浪费。
如果指针中没有那么少的kB,那么无论如何你可能无法做出可行的基于Vulkan的应用程序。您只能加载实际使用的那些命令,但我没有看到这种类型的过早优化的原因。您是否有一些特殊的硬件,需要这样的绝望措施或进行64K演示?