Я следовал другому учебнику;Тем не менее, у меня есть набор файлов Validation.h
и Validation.cpp
, которые используются для Vulkan's
ValidationLayers
. Они довольно просты, поскольку содержат только отдельную функцию.Файлы для использования ValidationLayers
выглядят так:
-Validation.h-
#pragma once
#include <vulkan\vulkan.h>
void ErrorCheck( VkResult res );
-Validation.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 <vulkan\vulkan.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;
}
Поскольку у этого класса выше есть пара зависимостей, я покажу вам VulkanConfiguration
и Initializers
.VulkanConfiguration
- это только заголовок, а Initializers
- набор автономных функций для создания объектов типа Vulkan
, заключенных в namespace
.Я покажу полный заголовок Initializers
, но я покажу только соответствующие объявления функций, которые необходимы для ValidationLayers
и VulkanInstance
.
-VulkanConfiguration.h-
#pragma once
#include <vulkan\vulkan.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 );
};
-Initializer.h-
#pragma once
#include <vulkan\vulkan.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 );
}
-Intializers.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
.
Теперь, чтобы получитьВулкан полностью запущен, вам нужны VulkanDevice
, VulkanPhysicalDevice
и QueueFamilyIndices
, однако я уверен, что, поскольку вы, вероятно, уже рисуете треугольник, вы должны иметь их на месте.Чтобы продемонстрировать, как заставить работать 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
);
}
Здесь вы можете видеть, что в конструкторе я вызываю vkCreateDevice()
и vkCreateCommandPool()
в свободной функции ErrorCheck()
.На данный момент моя кодовая база, когда я компилирую и запускаю ее, возвращается со значением 0 и без ошибок.Однако в деструкторе этого класса;если я закомментирую одну из функций vkDestroy...
, либо для CommandPool
, либо для Device
:
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.