Reputation: 327
I am getting into Vulkan and stumbled on my first problem. When trying to create a debug report callback (validation layers and debug extensions are available on my intel hd vulkan driver, at least it says so), it fails telling me vkCreateDebugReportCallbackEXT
is an unresolved symbol. When trying to get the function pointer it fails telling me vkCreateDebugReportCallbackEXT
is already defined.
Which it is, in the Vulkan header. I could set VK_NO_PROTOTYPES but then I would have to load everything by hand. Is there a way around this? Just using a different name for the function pointer won't work, since I am using Vulkan-Hpp and it uses vkCreateDebugReportCallbackEXT
as it is.
Is this a driver bug, telling me debug extensions are available, but there are not?
Btw, I am using VS2015.
Thanks for any help
Upvotes: 3
Views: 3494
Reputation: 1180
I had same issue, couldn't find solution so i solved it this way (might be wrong, but i just want to share in case it will help somebody):
struct DebugDispatch {
//KHRONOS
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = 0;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = 0;
//LUNARG
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = 0;
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = 0;
}
VKAPI_ATTR vk::Bool32 VKAPI_CALL debugReportCallback(...){...}
VKAPI_ATTR vk::Bool32 VKAPI_CALL debugUtilsMessengerCallback(...){...}
enum class ValidationFlagsBits : unsigned int {
NONE = 0,
KHRONOS = 1,
LUNARG = 1 << 1
};
typedef vk::Flags<ValidationFlagsBits> ValidationFlags;
void Example(){
...
vk::Instance instance;
instance = vk::createInstance(...);
DebugDispatch debug_dispatch;
vk::DebugReportCallbackEXT debug_report_callback;
vk::DebugUtilsMessengerEXT debug_utils_messenger;
if(validation_flags & ValidationFlagsBits::KHRONOS){
debug_dispatch.vkCreateDebugReportCallbackEXT =
(PFN_vkCreateDebugReportCallbackEXT)instance.getProcAddr("vkCreateDebugReportCallbackEXT");
debug_dispatch.vkDestroyDebugReportCallbackEXT =
(PFN_vkDestroyDebugReportCallbackEXT)instance.getProcAddr("vkDestroyDebugReportCallbackEXT");
vk::DebugUtilsMessengerCreateInfoEXT create_info{};
create_info.messageSeverity = ...;
create_info.messageType = ...;
create_info.pfnUserCallback = reinterpret_cast<PFN_vkDebugUtilsMessengerCallbackEXT>(&debugUtilsMessengerCallback);
debug_utils_messenger = instance.createDebugUtilsMessengerEXT(create_info, nullptr, debug_dispatch);
}
if(validation_flags & ValidationFlagsBits::LUNARG){
debug_dispatch.vkCreateDebugUtilsMessengerEXT =
(PFN_vkCreateDebugUtilsMessengerEXT)instance.getProcAddr("vkCreateDebugUtilsMessengerEXT");
debug_dispatch.vkDestroyDebugUtilsMessengerEXT =
(PFN_vkDestroyDebugUtilsMessengerEXT)instance.getProcAddr("vkDestroyDebugUtilsMessengerEXT");
vk::DebugReportCallbackCreateInfoEXT create_info{};
create_info.flags = ...;
create_info.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(&debugReportCallback);
debug_report_callback = instance.createDebugReportCallbackEXT(create_info, nullptr, debug_dispatch);
}
...
if(validation_flags & ValidationFlagsBits::KHRONOS){
instance.destroyDebugUtilsMessengerEXT(debug_utils_messenger, nullptr, debug_dispatch);
}
if(validation_flags & ValidationFlagsBits::LUNARG){
instance.destroyDebugReportCallbackEXT(debug_report_callback, nullptr, debug_dispatch);
}
instance.destroy();
}
Upvotes: 0
Reputation: 13246
That's normal. vulkan.h
defines them as a global functions. But the loader commands obviously return function pointer.
Normally you would just use a different name you like. But I like to have the canonical names too...
I solve it by defining the function myself (using the declaration from vulkan.h
) which in turn calls the loaded pointer:
VKAPI_ATTR VkResult VKAPI_CALL vkCommandEXT( /*...*/ ){
return fpCommandEXT( /*...*/ );
}
(Shameless self-promotion) Like so:
https://github.com/krOoze/Hello_Triangle/blob/8227220/ErrorHandling.h#L181
I make the command to self-load on its first use — if you don't like that, in older commit I had more conventional loader:
https://github.com/krOoze/Hello_Triangle/blob/699ab57/HelloTriangle.cpp#L731
PS:
Khronos themselves just added loader code that illustrates that nicely:
https://github.com/KhronosGroup/Vulkan-Docs/blob/1.0/src/ext_loader/vulkan_ext.c
If you handle multiple VkInstance
s or VkDevice
s the loaded functions have to be dispatched to the correct instance or device. For example, I do that (likely inefficiently) here:
https://github.com/krOoze/Hello_Triangle/blob/a691de5/ExtensionLoader.h
Upvotes: 4