Vulkan加载vkCreateDebugReportCallbackEXT

时间:2016-08-23 16:38:31

标签: vulkan

我正在进入Vulkan并偶然发现了我的第一个问题。在尝试创建调试报告回调时(我的intel hd vulkan驱动程序上提供了验证层和调试扩展,至少它是这样说的),它无法告诉我vkCreateDebugReportCallbackEXT是一个未解析的符号。当试图获取函数指针时,它失败告诉我vkCreateDebugReportCallbackEXT已经定义。

在Vulkan标题中它是什么。我可以设置VK_NO_PROTOTYPES但是我必须手动加载所有内容。有没有解决的办法?只是为函数指针使用不同的名称不会起作用,因为我使用的是Vulkan-Hpp,它使用vkCreateDebugReportCallbackEXT。 这是一个驱动程序错误,告诉我调试扩展是可用的,但没有?

是的,我正在使用VS2015。

感谢您的帮助

2 个答案:

答案 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

如果处理多个VkInstanceVkDevice,则必须将已加载的函数分派到正确的实例或设备。例如,我这样做(可能效率低下):
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();
}