Reputation: 9540
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
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
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