英文:
How does the Vulkan Validation Layer assignment work?
问题
The provided text discusses using a callback function in Vulkan for validation layers. Here's the translated code part:
我已经开始使用Vulkan,并刚刚完成了[Validation Layers][1]部分。
在这里,他们在.cpp文件中添加了一个静态函数`static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(...)`,然后简单地赋值:
createInfo.pfnUserCallback = debugCallback;
这是如何(以及为什么)工作的呢?我当然知道回调函数,但我尝试将这个函数添加到我的渲染器类而不是仅仅在.cpp文件中“本地”(?)定义,首先在头文件中:
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
void* pUserData);
然后在.cpp文件中:
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanRenderer::DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
void* pUserData)
{
//...
}
最后,使用以下方式分配它:
createInfo.pfnUserCallback = &VulkanRenderer::DebugCallback;
实际上,我的版本不起作用,所以我可能在这里考虑了错误的事情。但我不知道教程中他们是如何做的,甚至不知道要搜索什么来理解这一点。
[1]: https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers
Please note that this is the translated code portion, and I have excluded the request to avoid answering translation questions.
英文:
I have started with Vulkan and just did the Validation Layers.
In here, they add a static function static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(...)
to the .cpp file, then simply assign
createInfo.pfnUserCallback = debugCallback;
How (/why) does this work? I know of callbacks of course, but I tried to add this function to my renderer class instead of just "locally"(?) in the .cpp file, first in the header file:
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
void* pUserData);
And then in the .cpp file:
VKAPI_ATTR VkBool32 VKAPI_CALL VulkanRenderer::DebugCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* callbackData,
void* pUserData)
{
//...
}
And finally using assigning it like this:
createInfo.pfnUserCallback = &VulkanRenderer::DebugCallback;
My version does in fact not work, so I probably am thinking about the wrong thing here. But I don't know what they did in the tutorial or even what to search for to understand this.
I do know what code to write to make it work like they have it, I just don't know why.
答案1
得分: 3
Here is the translated content without the code parts:
当DebugCallback
是一个非静态成员函数时,&VulkanRenderer::DebugCallback
是一个成员函数指针。
成员函数指针并不是函数指针,但pfnUserCallback
需要一个函数指针。
成员函数指针和函数指针不能工作相同,因为非静态成员函数需要知道它被调用在哪个对象上,这对于自由函数来说并不成立。
现在,Vulkan是一个C API,而不是C++ API,因此它不了解成员函数,而且还使用C习惯来实现回调接口,而不是C++习惯。
不过,这个C习惯仍然允许传递关于要调用成员函数的对象的信息。这就是pUserData
的作用。它将不经修改地传递到回调函数中,回调函数可以使用它来进行成员函数调用:
createInfo.pUserData = this;
createInfo.pfnUserCallback = [](auto a, auto b, auto c, void* pUserData){ return static_cast<VulkanRenderer*>(pUserData)->DebugCallback(a, b, c); };
(无捕获的通用lambda可以转换为具有特定参数类型的函数指针。)
(我实际上对Vulkan了解不多。如果Vulkan调用的函数需要VKAPI_CALL
和VKAPI_ATTR
,那么lambda可能不起作用。在这种情况下,可以使用一个具有可以应用宏的名称的静态成员函数,而不是一个没有名称的lambda,可能不能使用宏。)
或者,如果DebugCallback
不需要是非静态的,当然也可以将它声明为静态成员函数。然后你的方法也会起作用。静态成员函数不需要关于调用它的对象的任何额外信息,因此形成与自由函数类似的普通函数指针。
英文:
When DebugCallback
is a non-static member function, then &VulkanRenderer::DebugCallback
is a member function pointer.
A member function pointer is not a function pointer, but pfnUserCallback
wants a function pointer.
Member function pointers and function pointers can't work the same because a non-static member function needs to know on which object it is being called, which isn't the case for a free function.
Now, Vulkan is a C API, not a C++ API, so it isn't aware of member functions at all and also uses a C idiom to implement the callback interface instead of a C++ one.
The C idiom however still allows passing information about the object on which you want to call your member function. That's what pUserData
is for. It will be passed through unchanged to your callback and the callback can use it to e.g. do a member function call:
createInfo.pUserData = this;
createInfo.pfnUserCallback = [](auto a, auto b, auto c, void* pUserData){ return static_cast<VulkanRenderer*>(pUserData)->DebugCallback(a, b, c); };
(capture-less generic lamdbas can be converted into function pointers for specific argument types.)
(I don't actually know much about Vulkan. If VKAPI_CALL
and VKAPI_ATTR
are required on the function that will be called by Vulkan, then a lambda might not work. In that case use a static member function with a name on which you can apply the macros instead of an nameless lambda on which you likely can't.)
Alternatively, if DebugCallback
doesn't need to be non-static, you can of course also declare it as static
member function. Then your approach will also work. A static member function doesn't need any additional information about an object on which it is called and therefore forms normal function pointers like free functions.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论