Vulkan 加载 vkCreateDebugReportCallbackEXT

Vulkan load vkCreateDebugReportCallbackEXT

我正在使用 Vulkan 并偶然发现了我的第一个问题。尝试创建调试报告回调时(验证层和调试扩展在我的 intel hd vulkan driver 上可用,至少它是这么说的),它没有告诉我 vkCreateDebugReportCallbackEXT 是一个未解析的符号。当试图获取函数指针时,它告诉我 vkCreateDebugReportCallbackEXT 已经定义。

在 Vulkan 中就是这样 header。我可以设置 VK_NO_PROTOTYPES 但我必须手动加载所有内容。有没有解决的办法?仅仅为函数指针使用不同的名称是行不通的,因为我正在使用 Vulkan-Hpp 而它按原样使用 vkCreateDebugReportCallbackEXT 。 这是一个 driver 错误,告诉我调试扩展可用,但没有?

顺便说一下,我正在使用 VS2015。

感谢您的帮助

这很正常。 vulkan.h 将它们定义为全局函数。但是加载器命令显然 return function pointer.

通常您会使用您喜欢的其他名称。但我也喜欢有规范的名字...

我通过自己 定义 函数(使用 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

我遇到了同样的问题,找不到解决办法所以我这样解决了 (可能是错误的,但我只是想分享一下以防对某人有所帮助):

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();
}