Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading Vulkan functions globally

Tags:

c++

vulkan

With Vulkan released, I decided to write (as a hobby) a Vulkan based GUI. However, I'm currently stuck at the very first step - loading Vulkan functions. I'm using Nvidia's C++ Vulkan wrapper which requires, as far as I can see, Vulkan functions to be loaded globally.

I can load local functions successfully, however ::vkCreateInstance fails:

void loadInstanceFunctions() {
    PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)vkGetInstanceProcAddr(nullptr, "vkCreateInstance"); //works

    ::vkCreateInstance = (PFN_vkCreateInstance)vkGetInstanceProcAddr(nullptr, "vkCreateInstance");  //does not work
}

Trying to assign new function pointer globally gives me 2 compile-time errors (compiled using VS2015):

  • expression must be a modifiable lvalue.
  • '=': function as left operand.

There are function prototypes declared in vulkan.h header, for example:

VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
    const VkInstanceCreateInfo*                 pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkInstance*                                 pInstance);

This is what might prevent me from loading functions globally. If I were to define VK_NO_PROTOTYPES, then these prototypes would be skipped and I believe that I could just re-declare them as PFN_vkCreateInstance vkCreateInstance = nullptr; and so on. But is this the correct way?

So, my question - what is the correct way to load Vulkan functions globally?

like image 371
FrogTheFrog Avatar asked Mar 13 '23 19:03

FrogTheFrog


1 Answers

::vkCreateInstance = (PFN_vkCreateInstance)vkGetInstanceProcAddr(nullptr, "vkCreateInstance");  //does not work

You are trying to assign a function pointer to the symbol vkCreateInstance which, by default, is defined as a prototype in vulkan.h.

Defining VK_NO_PROTOTYPES will pre-process out all prototypes:

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
    const VkInstanceCreateInfo*                 pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkInstance*                                 pInstance);
...
#endif

Once the prototypes are gone you can load vkCreateInstance globally as per the documentation:

#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>

#ifdef __cplusplus
extern "C" {
#endif
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *pName);
#ifdef __cplusplus
}
#endif

PFN_vkCreateInstance vkCreateInstance;

int main()
{
        vkCreateInstance = (PFN_vkCreateInstance) vkGetInstanceProcAddr(NULL, "vkCreateInstance");

        return 0;
}
like image 172
alteous Avatar answered Mar 25 '23 09:03

alteous