Makogan
Makogan

Reputation: 9540

vulkan.hpp unique handles for extensions

I am trying to create a unique handle for a vk::DebugUtilsMessengerEXT object.

To this effect I have loaded VkCreateDebugUtilsMessenger() into a function pointer and then call it to create the plain C structure, which I then turn into a unique vulkan.hpp object through

vk::UniqueDebugUtilsMessengerEXT(messenger, instance);

This is where the issue begins. This kind of object calls the destructor implicitely, that is to say it will attempt to call vkDestroyDebugUtilsMessengerEXT when the variable leaves the scope. However this function cannot be loaded into a pointer with the same name.

i.e defining a function pointer as vkDestroyDebugUtilsMessengerEXT

And then setting it as

vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT) instance.getProcAddr(
        "vkDestroyDebugUtilsMessengerEXT");

Will result in a compilation error as I am redefining the symbol.

error: ‘void (* vkDestroyDebugUtilsMessengerEXT)(VkInstance, VkDebugUtilsMessengerEXT, VkAllocationCallbacks)’ redeclared as different kind of symbol

However not defining it causes a linker error, as the linker cannot find the symbol to link against for the destruction of the unique handle.

/usr/bin/ld: obj/Debug/main.o: in function `vk::DispatchLoaderStatic::vkDestroyDebugUtilsMessengerEXT(VkInstance_T*, VkDebugUtilsMessengerEXT_T*, VkAllocationCallbacks const*) const':
/home/kronos/Desktop/Vulkan/Generated/../libraries/vulkansdk-linux/1.1.97.0/x86_64/include/vulkan/vulkan.hpp:1770: undefined reference to `vkDestroyDebugUtilsMessengerEXT'

How do I get around this? How can i expose that symbol to allow for compilation?

Upvotes: 0

Views: 1654

Answers (2)

C0nstexpr
C0nstexpr

Reputation: 94

Besides the answer upwards, it could be better like the following code:

using unique_debug_utils_messenger_ext = UniqueHandle<DebugUtilsMessengerEXT, DispatchLoaderDynamic>;
...
UniqueInstance instance_{nullptr};
UniqueDevice device_;
unique_debug_utils_messenger_ext debug_messenger_;
DebugUtilsMessengerCreateInfoEXT debug_messenger_create_info;
DispatchLoaderDynamic dispatch_loader_dynamic_;
...
dispatch_loader_dynamic_ = {*instance_, *device_};
debug_messenger_ = instance_->createDebugUtilsMessengerEXTUnique(
            debug_messenger_create_info,
            nullptr,
            dispatch_loader_dynamic_);

The code enables you to still use the smart pointer feature. More details are provided in DispatchLoaderDynamic implementation in vulkan.hpp.

Upvotes: 4

Makogan
Makogan

Reputation: 9540

I found the solution.

Defining a function with the same name as the requested function and calling the pointer inside of it allows for compilation and linking.

In essence:

void (*vkDestroyDebugUtilsMessenger)(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator);
void vkDestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator)
{
    vkDestroyDebugUtilsMessenger(instance, debugMessenger, pAllocator);
}

Creates the symbols needed for linikng and compilation and:

vkDestroyDebugUtilsMessenger =
        (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(
            instance, "vkDestroyDebugUtilsMessengerEXT");

Will properly initialize the pointer.

Upvotes: 0

Related Questions