破坏vulkan以测试调试回调是否正确设置的好方法是什么

What is a good way to break vulkan to test if a debug callback was setup properly?

本文关键字:设置 是什么 方法 是否 vulkan 测试 调试 回调 破坏      更新时间:2023-10-16

我是第一次学习vulkan,现在是vulkan教程的第二步。绘制三角形->设置->验证层。

我完成了错误回调的设置,现在我想测试它是否真的有效(我无法获得任何错误消息)。

我已经检查了我的所有函数是否都被调用了(唯一不打印任何内容的是debugCallBack本身)。

似乎什么都没坏。我该如何破解东西来测试错误回调是否设置正确?

如果这是OpenGL,我会尝试在标准程序(0)中设置一个随机的统一名称。

提前谢谢。

我在https://github.com/KhronosGroup/Vulkan-Loader/issues/123.

在此期间,我做了两件事:

1) 我分别使用vkDebugReportMessageEXTvkSubmitDebugUtilsMessageEXT打印介绍消息。这表明调试回调是有效的。

2) 破解验证的简单方法是vkEnumeratePhysicalDevices( instance, nullptr, nullptr );

我一直在学习不同的教程;然而,我有一组用于Vulkan'sValidationLayers的文件Validation.hValidation.cpp。它们非常简单,因为它们只包含一个独立的函数。使用ValidationLayers的文件如下所示:

-验证.h-

#pragma once
#include <vulkanvulkan.h>
void ErrorCheck( VkResult res );

-验证.cpp-

#include "Validation.h"
#include <assert.h>
#include <iostream>
void ErrorCheck( VkResult res ) {
if ( res != VK_SUCCESS ) {
std::cout << "Error" << std::endl;
assert( 0 && "There Was An Error" );
}
}

这只是一个简单的函数,用于将消息打印到控制台并断言存在错误。实际的ValidationLayers位于不同的位置,如下所示。


现在要设置Validation Layers,我有一个名为VulkanInstance的类。类看起来是这样的:

-VulkanInstance.h-

#pragma once
#include "VulkanConfiguration.h"
#include <vector>
#include <vulkanvulkan.h>
class VulkanInstance {
private:
VkInstance m_instance;
std::vector<const char*> m_layers;
std::vector<const char*> m_extensions;
public:
VulkanInstance( VulkanConfiguration& vulkan_config );
~VulkanInstance();
VkInstance& getInstance();
};

-VulkanInstance.cpp-

#include "VulkanInstance.h"
#include "Validation.h"
#include "Initializers.h"
#include <iostream>
VulkanInstance::VulkanInstance( VulkanConfiguration& vulkan_config ) {
m_layers.push_back("VK_LAYER_LUNARG_standard_validation");
m_extensions.push_back("VK_EXT_debug_report");
VkApplicationInfo application_info = Initializers::applicationInfo( vulkan_config );
VkInstanceCreateInfo instance_info = Initializers::instanceCreateInfo( application_info, m_layers, m_extensions );
ErrorCheck( vkCreateInstance( &instance_info, NULL, &m_instance ) );
}
VulkanInstance::~VulkanInstance() {
vkDestroyInstance( m_instance, NULL );
}
VkInstance& VulkanInstance::getInstance() {
return m_instance;
}

由于上面的这个类确实有几个依赖项,我将向您展示VulkanConfigurationInitializersVulkanConfiguration仅是一个标头,而Initializers是用于创建封装在namespace中的Vulkan类型对象的一组独立函数。我将显示完整的Initializers标头,但只显示ValidationLayersVulkanInstance所需的相关函数声明。


-VulkanConfiguration.h-

#pragma once
#include <vulkanvulkan.h>
struct VulkanConfiguration {
const char* application_name = "";
uint32_t application_version = VK_MAKE_VERSION( 0, 0, 0 );
const char* engine_name = "My Vulkan Engine";
const uint32_t engine_version = VK_MAKE_VERSION( 0, 0, 0 );
const uint32_t api_version = VK_MAKE_VERSION( 1, 1, 82 );
};

-初始化程序.h-

#pragma once
#include <vulkanvulkan.h>
#include <vector>
struct VulkanConfiguration;
namespace Initializers {    
VkApplicationInfo applicationInfo( VulkanConfiguration& config );
VkInstanceCreateInfo instanceCreateInfo( VkApplicationInfo& app_info, std::vector<const char*>& layers, std::vector<const char*>& extensions );
VkDeviceQueueCreateInfo deviceQueueCreateInfo( uint32_t queue_family_index, float& priority );
VkDeviceCreateInfo deviceCreateInfo( std::vector<VkDeviceQueueCreateInfo>& queue_create_infos, VkPhysicalDeviceFeatures& device_features );
VkCommandPoolCreateInfo commandPoolCreateInfo( uint32_t queue_family_index, VkCommandPoolCreateFlags flags = 0 );
VkCommandBufferAllocateInfo commandBufferAllocateInfo( VkCommandPool pool, uint32_t count );
VkBufferCreateInfo bufferCreate( VkDeviceSize size, VkBufferUsageFlags usage );
VkMemoryAllocateInfo memoryAllocateInfo( VkDeviceSize size, uint32_t memory_type_index );
}

-初始化程序.cpp-

#include "Initializers.h"
#include "VulkanConfiguration.h"
VkApplicationInfo Initializers::applicationInfo( VulkanConfiguration& config ) {
VkApplicationInfo info = {};
info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
info.pApplicationName = config.application_name;
info.pEngineName = config.engine_name;
info.applicationVersion = config.application_version;
info.engineVersion = config.engine_version;
info.apiVersion = config.api_version;
return info;
}
VkInstanceCreateInfo Initializers::instanceCreateInfo( VkApplicationInfo& app_info, std::vector<const char*>& layers, std::vector<const char*>& extensions ) {
VkInstanceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
info.pApplicationInfo = &app_info;
info.enabledExtensionCount = extensions.size();
info.enabledLayerCount = layers.size();
info.ppEnabledExtensionNames = extensions.data();
info.ppEnabledLayerNames = layers.data();
return info;
} 

这将为我们提供设置ValidationLayers所需的一切。


现在要让Vulkan完全运行,您确实需要VulkanDeviceVulkanPhysicalDeviceQueueFamilyIndices,但我确信,由于您可能已经在渲染三角形,因此应该将它们放置到位。为了演示如何使ValidationLayers工作,我将向您展示VulkanDevice类的构造函数和析构函数。。。

-VulkanDevice.cpp--部分源代码

#include "VulkanDevice.h"
#include "Initializers.h"
#include "Validation.h"
#include "VulkanPhysicalDevice.h"
#include <vector>
VulkanDevice::VulkanDevice( VulkanInstance* instance, VulkanPhysicalDevice* physical_device ) {
m_instance = instance;
m_vulkan_physical_device = physical_device;
std::vector<VkDeviceQueueCreateInfo> queue_create_infos;
float priority = 1.0f;
queue_create_infos.push_back( Initializers::deviceQueueCreateInfo( m_vulkan_physical_device->getQueueFamilyIndices().compute_indices, priority ) );
VkDeviceCreateInfo create_info = Initializers::deviceCreateInfo( queue_create_infos, m_vulkan_physical_device->getPhysicalDeviceFeatures() );
ErrorCheck( vkCreateDevice(
m_vulkan_physical_device->getPhysicalDevice(),
&create_info,
nullptr,
&m_device
) );
vkGetDeviceQueue(
m_device,
m_vulkan_physical_device->getQueueFamilyIndices().compute_indices,
0,
&m_compute_queue
);
VkCommandPoolCreateInfo compute_pool_info = Initializers::commandPoolCreateInfo( m_vulkan_physical_device->getQueueFamilyIndices().compute_indices );
ErrorCheck( vkCreateCommandPool(
m_device,
&compute_pool_info,
nullptr,
&m_compute_command_pool
) );
}
VulkanDevice::~VulkanDevice() {
vkDestroyCommandPool(
m_device,
m_compute_command_pool,
nullptr
);
vkDestroyDevice(
m_device,
nullptr
);
}

在这里您可以看到,在构造函数中,我正在调用自由函数ErrorCheck()中的vkCreateDevice()vkCreateCommandPool()。到目前为止,当我编译和运行我的代码库时,它返回的值为0,没有错误。但是,在这个类的析构函数中;如果我为CommandPoolDevice:注释掉vkDestroy...函数中的任何一个

VulkanDevice::~VulkanDevice() {
/*
vkDestroyCommandPool(
m_device,
m_compute_command_pool,
nullptr
);
*/
vkDestroyDevice(
m_device,
nullptr
);
}

VulkanDevice::~VulkanDevice() {
vkDestroyCommandPool(
m_device,
m_compute_command_pool,
nullptr
);
/*
vkDestroyDevice(
m_device,
nullptr
);
*/
}

它将分别向控制台提供这些打印信息:

VUID-vkDestroyDevice-device-00378(ERROR / SPEC): msgNum: 614466292 - OBJ ERROR : For device 0x42af310, CommandPool objec
t 0x1 has not been destroyed. The spec valid usage text states 'All child objects created on device must have been destr
oyed prior to destroying device' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkDestroyDevic
e-device-00378)
Objects: 1
[0] 0x1, type: 25, name: (null)
Validation(ERROR): msg_code: 614466292:  [ VUID-vkDestroyDevice-device-00378 ]  [ VUID-vkDestroyDevice-device-00378 ] Ob
ject: 0x1 (Type = 25) | OBJ ERROR : For device 0x42af310, CommandPool object 0x1 has not been destroyed. The spec valid
usage text states 'All child objects created on device must have been destroyed prior to destroying device' (https://www
.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-vkDestroyDevice-device-00378)
C:Users...Vulkan Tutorial.exe (process 1256) exited w
ith code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the conso
le when debugging stops.
Press any key to close this window . . .

UNASSIGNED-ObjectTracker-ObjectLeak(ERROR / SPEC): msgNum: -1 - OBJ ERROR : VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT objec
t 0x4139590 has not been destroyed.
Objects: 1
[0] 0x4139590, type: 3, name: (null)
Validation(ERROR): msg_code: -1:  [ UNASSIGNED-ObjectTracker-ObjectLeak ]  [ UNASSIGNED-ObjectTracker-ObjectLeak ] Objec
t: 0x4139590 (Type = 3) | OBJ ERROR : VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT object 0x4139590 has not been destroyed.
C:Users...Vulkan Tutorial.exe (process 2480) exited w
ith code 0.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the conso
le when debugging stops.
Press any key to close this window . . .

希望这能让你从一般意义上深入了解Vulkan及其ValidationLayers的工作原理。上面的代码不是我自己的,因为它来自Youtube频道的在线教程。