我正在进入Vulkan并偶然发现了我的第一个问题。在尝试创建调试报告回调时(我的intel hd vulkan驱动程序上提供了验证层和调试扩展,至少它是这样说的),它无法告诉我vkCreateDebugReportCallbackEXT
是一个未解析的符号。当试图获取函数指针时,它失败告诉我vkCreateDebugReportCallbackEXT
已经定义。
在Vulkan标题中它是什么。我可以设置VK_NO_PROTOTYPES但是我必须手动加载所有内容。有没有解决的办法?只是为函数指针使用不同的名称不会起作用,因为我使用的是Vulkan-Hpp,它使用vkCreateDebugReportCallbackEXT
。
这是一个驱动程序错误,告诉我调试扩展是可用的,但没有?
感谢您的帮助
答案 0 :(得分:4)
这是正常的。 vulkan.h
将它们定义为全局函数。但是加载器命令显然会返回函数指针。
通常你会使用你喜欢的其他名字。但我也喜欢这些规范的名字......
我通过定义函数来解决它(使用vulkan.h
中的声明),然后调用加载的指针:
VKAPI_ATTR VkResult VKAPI_CALL vkCommandEXT( /*...*/ ){
return fpCommandEXT( /*...*/ );
}
(无耻的自我推销)同样如此:
https://github.com/krOoze/Hello_Triangle/blob/8227220/ErrorHandling.h#L181
我让命令在第一次使用时自动加载 - 如果你不喜欢它,在旧的提交中我有更多传统的加载器:
https://github.com/krOoze/Hello_Triangle/blob/699ab57/HelloTriangle.cpp#L731
PS:
Khronos本身只是添加了加载器代码,很好地说明了这一点:
https://github.com/KhronosGroup/Vulkan-Docs/blob/1.0/src/ext_loader/vulkan_ext.c
如果处理多个VkInstance
或VkDevice
,则必须将已加载的函数分派到正确的实例或设备。例如,我这样做(可能效率低下):
https://github.com/krOoze/Hello_Triangle/blob/a691de5/ExtensionLoader.h
答案 1 :(得分:0)
我遇到了同样的问题,找不到解决方案,所以我这样解决了 (可能是错的,但我只是想分享一下,以防它对某人有帮助):
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();
}