Tim Hsu Tim Hsu - 1 year ago 63
C++ Question

About function loader in Vulkan

In Vulkan, we have two global functions that need to load with dlopen/LoadLibrary. They are vkGetInstanceProcAddr and vkGetDeviceProcAddr.

I have one gpu and install vulkan driver. Should I better load library at runtime or linktime? I give difference logical devices(created from the same gpu) to vkGetDeviceProcAddr to query the same function. They both return the same address to me. I think the reload could be wasteful.

My question is how this idea come from? Is it for multi-implementation or multi-gpus?

My loader function currently look like this:

class VulkanDevice
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.vkCreateCommandBuffers(vkd.m_Device, ....);

As you can see, if I have multiple device it will be pretty wasteful to reload... and the function pointer could use a lot of memory too....

Answer Source

The distinction between "instance function pointers" and "device function pointers" is for people who want faster function call performance.

You can use Vulkan just fine with only vkGetInstanceProcAddr. This function will retrieve function pointers for all Vulkan functions. Those function pointers will use dispatch information stored in the various Vulkan objects you pass in order to determine which device you're talking to. These pointers can be used with any instance, device, or device-dependent object.

The pointers you get from vkGetDeviceProcAddr know that they work with a specific device. They don't need to use dispatch logic to call into that device. So they're slightly lower-level. The downside is that you can only use them with that specific VkDevice or device-derived objects.

The dispatch overhead probably won't be significant enough to be worth the bother for most people. If you really care about such things however, you have the option to avoid it.

if I have multiple device it will be pretty wasteful to reload... and the function pointer could use a lot of memory too....

Those functions exist whether you query their pointers or not; getting their pointers therefore only takes up the memory you use to store the pointers to them. Vulkan's API contains about 140 functions. At 8 bytes per function pointer, that's 1120 bytes, barely 1KB.

As for the time spent loading them... I would be shocked if loading 140 function pointers took more than a few microseconds. Which you do once at start-up time.