1
votes

Been stuck with this issue for the past few days. I'm trying to use the Vulkan API's debug layers I've sucessfully fetched the function pointers for the PFN_vkCreateDebugReportCallbackEXT and PFN_vkDestroyDebugReportCallbackEXT.

But when creating the struct to use as an argument for the vkCreateDebugReportCallback I'm having issues with the pfnCallback part of the struct.

Visual studio is giving me this error when trying to compile, and I have tried typecasting it as follows :

dbgReportCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT) debugFunction;

and

dbgReportCreateInfo.pfnCallback = reinterpret_cast<PFN_vkDebugReportCallbackEXT>(debugFunction);

which both cause a memory access violation when the vkCreateDebugReportCallback function is called.

What should work

From the textbook Learning Vulkan and the supplied repository the proper declaration for the PFN_vkDebugReportCallbackEXT pfn part of the struct should be as shown in their repository here.

VKAPI_ATTR VkBool32 VKAPI_CALL debugFunction(
    VkFlags                    msgFlags, 
    VkDebugReportObjectTypeEXT objType, 
    uint64_t                   srcObject, 
    size_t                     location, 
    uint32_t                   msgCode, 
    const char *               layerPrefix, 
    const char *               msg, 
    void *                     userData);

Vulkan Header file

Which is just as is defined in the Vulkan header file, vulkan.h

typdef uint32_t VkBool32;

typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)(
    VkDebugReportFlagsEXT                       flags,
    VkDebugReportObjectTypeEXT                  objectType,
    uint64_t                                    object,
    size_t                                      location,
    int32_t                                     messageCode,
    const char*                                 pLayerPrefix,
    const char*                                 pMessage,
    void*                                       pUserData);


typedef struct VkDebugReportCallbackCreateInfoEXT {
    VkStructureType                 sType;
    const void*                     pNext;
    VkDebugReportFlagsEXT           flags;
    PFN_vkDebugReportCallbackEXT    pfnCallback;
    void*                           pUserData;
} VkDebugReportCallbackCreateInfoEXT;

Visual Studio Error

Severity Code Description Project File Line Source Suppression State Error C2440 '=': cannot convert from 'VkBool32 (__cdecl *)(VkDebugReportFlagsEXT,VkDebugReportObjectTypeEXT,uint64_t,std::size_t,uint32_t,const char *,const char *,void *)' to 'PFN_vkDebugReportCallbackEXT' vulkanproject C:\Users\Alec\workspace\cpp\vulkanproject\source\VulkanLayerAndExtension.cpp 287 Build

My code

Full project available in my Github repository

VulkanLayerAndExtension.h

class VulkanLayerAndExtension {
    // Some stuff before
    VkResult createDebugReportCallback();
    void destroyDebugReportCallback();
    static VKAPI_ATTR VkBool32 VKAPI_CALL debugFunction(VkDebugReportFlagsEXT msgFlags,
        VkDebugReportObjectTypeEXT objType,
        uint64_t srcObject,
        size_t location,
        uint32_t msgCode,
        const char * layerPrefix,
        const char * msg,
        void * userData);

private:
    PFN_vkCreateDebugReportCallbackEXT dbgCreateDebugReportCallback;
    PFN_vkDestroyDebugReportCallbackEXT dbgDestroyDebugReportCallback;
    VkDebugReportCallbackEXT debugReportCallback;
public:
    VkDebugReportCallbackCreateInfoEXT dbgReportCreateInfo = {};

VulkanLayerAndExtension.cpp

// stuff before

VKAPI_ATTR VkBool32 VKAPI_CALL
VulkanLayerAndExtension::debugFunction(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, uint32_t msgCode, const char * layerPrefix, const char * msg, void * userData)
{
    std::cout << "[VK_DEBUG_REPORT] ";
    if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
        std::cout << "ERROR";
    }
    else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
        std::cout << "WARNING";
    }
    else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
        std::cout << "INFORMATION";
    }
    else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
        std::cout << "PERFORMANCE";
    }
    else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
        std::cout << "DEBUG";
    }
    else {
        return VK_FALSE;
    }
    std::cout << ": [" << layerPrefix << "] Code" << msgCode << ":" << msg << std::endl;
    return VK_TRUE;
}

VkResult VulkanLayerAndExtension::createDebugReportCallback()
{
    VkResult result;

    VulkanApplication * appObj = VulkanApplication::GetInstance();
    VkInstance* instance = &appObj->instanceObj.instance;

    // Get vkCreateDebugReportCallbackEXT API
    dbgCreateDebugReportCallback = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(*instance, "vkCreateDebugReportCallbackEXT");
    if (!dbgCreateDebugReportCallback) {
        std::cout << "Error: GetInstanceProcAddr unable to locate vkCreateDebugReportCallbackEXT function.\n";
        return VK_ERROR_INITIALIZATION_FAILED;
    }
    std::cout << "GetInstanceProcAddr loaded dbgCreateDebugReportCallback function.\n";

    // Get vkDestroyDebugReportCallbackEXT API
    dbgDestroyDebugReportCallback = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(*instance, "vkDestroyDebugReportCallbackEXT");
    if (!dbgDestroyDebugReportCallback) {
        std::cout << "Error: GetInstanceProcAddr unable to locate vkDestroyDebugReportCallbackEXT function.\n";
        return VK_ERROR_INITIALIZATION_FAILED;
    }
    std::cout << "GetInstanceProcAddr loaded dbgDestroyDebugReportCallback function.\n";

    dbgReportCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    // Type error occurs on this line below
    dbgReportCreateInfo.pfnCallback =   VulkanLayerAndExtension::debugFunction;
    dbgReportCreateInfo.pUserData =     NULL;
    dbgReportCreateInfo.pNext =         NULL;
    dbgReportCreateInfo.flags =         VK_DEBUG_REPORT_WARNING_BIT_EXT |
                                        VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
                                        VK_DEBUG_REPORT_ERROR_BIT_EXT |
                                        VK_DEBUG_REPORT_DEBUG_BIT_EXT;

    // Create the debug report callback object
    result = dbgCreateDebugReportCallback(*instance, &dbgReportCreateInfo, NULL, &debugReportCallback);
    if (result == VK_SUCCESS) {
        std::cout << "Debug report callback object created successfully.\n";
    }

    return result;
}

void VulkanLayerAndExtension::destroyDebugReportCallback()
{
    VulkanApplication * appObj = VulkanApplication::GetInstance();
    VkInstance & instance = appObj->instanceObj.instance;
    if (debugReportCallback) {
        dbgDestroyDebugReportCallback(instance, debugReportCallback, NULL);
    }
}
1
Thanks for the edit Anju! - Alec C

1 Answers

2
votes

Why are you casting the function?? You should not! The function already has to be the required type.

I also do debug programmatically in my example project, and it works, so lets have it here for comparison:

VKAPI_ATTR VkBool32 VKAPI_CALL genericDebugCallback(
    VkDebugReportFlagsEXT msgFlags,
    VkDebugReportObjectTypeEXT objType,
    uint64_t srcObject,
    size_t /*location*/,
    int32_t msgCode,
    const char* pLayerPrefix,
    const char* pMsg,
    void* /*pUserData*/
){
    // just print everything
    return VK_FALSE;
}

//// elsewhere
VkDebugReportCallbackCreateInfoEXT debugCreateInfo{
    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
    nullptr,
    debugAmount,
    genericDebugCallback,
    nullptr
};

VkDebugReportCallbackEXT debug;
VkResult errorCode = vkCreateDebugReportCallbackEXT( instance, &debugCreateInfo, nullptr, &debug );
RESULT_HANDLER( errorCode, "vkCreateDebugReportCallbackEXT" );

So scanning your code I see these problems:

  1. You are casting function type.
  2. PFN_vkDebugReportCallbackEXT::msgCode is int32_t not uint32_t
  3. You should probably not return VK_TRUE from the callback unless you know what you are doing.
  4. Why is there a *instance and also VkInstance&?? There's no point to it. It is a handle. Use the VkInstance directly; no pointers, not dereferencing and no references needed.
  5. In dbgReportCreateInfo.flags do you really want VK_DEBUG_REPORT_DEBUG_BIT_EXT? It is bit of a odd choice considering you are not also accepting INFO.

1 and 2 should fix your immediate problem.