单个command buffer代码
#include "Renderer.h"
int main() {
Renderer r;
// need to send command into command pool when creating a window
auto device = r._device;
auto queue = r._queue;
// Fence
// wait for the gpu to be ready on the cpu side?
// cpu wait for gpu
VkFence fence;
VkFenceCreateInfo fence_create_info{};
fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkCreateFence(device, &fence_create_info, nullptr, &fence);
// Semaphore
// semaphore tells gpu when other process completed
VkSemaphore semaphore;
VkSemaphoreCreateInfo semaphore_create_info{};
semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vkCreateSemaphore(device ,&semaphore_create_info, nullptr, &semaphore);
//semaphore_create_info.flag
// Command Pool
// allocate command buffers in a pool
// as destroy pool, also destroy all buffers
VkCommandPool command_pool;
VkCommandPoolCreateInfo pool_create_info{};
pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_create_info.queueFamilyIndex = r._graphics_family_index;// probably which queue to execute the commmand
pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
std::cout << "Command Pool Created" << std::endl;
ErrorCheck(vkCreateCommandPool(device, &pool_create_info, nullptr, &command_pool));
// Command Buffer
VkCommandBuffer command_buffer;
VkCommandBufferAllocateInfo command_buffer_allocate_info{};
command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_buffer_allocate_info.commandPool = command_pool;
command_buffer_allocate_info.commandBufferCount = 1;// how many command buffer to allocate for the pool
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;//
// initial state
vkAllocateCommandBuffers(device, &command_buffer_allocate_info, &command_buffer);
{
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
//begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
// recording state
vkBeginCommandBuffer(command_buffer, &begin_info);
// vkCmd...
// need to set viewport per command buffer
VkViewport viewport{};
viewport.maxDepth = 1.0f;
viewport.minDepth = 0.0f;
viewport.width = 512;
viewport.height = 512;
viewport.x = 0;
viewport.y = 0;
vkCmdSetViewport(command_buffer, 0, 1, &viewport);
// executable state, end recording compile the cb on gpu??
vkEndCommandBuffer(command_buffer);
}
{
// submit command buffer to gpu
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer;
// submit command buffer to gpu
vkQueueSubmit(queue, 1, &submit_info, fence);
}
// true: need to wait for all fence to complete before continue, false: wait only 1 fence
vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
// gpu works concurrently with cpu, wait for the queue
// wait for the submit to be done
// if commented , error: Attempt to destroy command pool with VkCommandBuffer 0x2109f440ab0[] which is in use.
// because command buffer wasn't complete on gpu when cpu tries to delete it,need to wait on cpu side
vkQueueWaitIdle(queue);
// destroy command pool
vkDestroyCommandPool(device, command_pool, nullptr);
vkDestroyFence(device, fence, nullptr);
}
多个command buffer,将如下部分替换(//***)
用semaphore做不同gpu command buffer间的同步
// Command Buffer
VkCommandBuffer command_buffer[2];//***
VkCommandBufferAllocateInfo command_buffer_allocate_info{};
command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_buffer_allocate_info.commandPool = command_pool;
command_buffer_allocate_info.commandBufferCount = 2;// ***
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
// initial state
vkAllocateCommandBuffers(device, &command_buffer_allocate_info, command_buffer);// ***
{
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
//begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
// recording state
vkBeginCommandBuffer(command_buffer[0], &begin_info);// ***
// vkCmd...
// need to set viewport per command buffer
VkViewport viewport{};
viewport.maxDepth = 1.0f;
viewport.minDepth = 0.0f;
viewport.width = 512;
viewport.height = 512;
viewport.x = 0;
viewport.y = 0;
vkCmdSetViewport(command_buffer[0], 0, 1, &viewport);// ***
// executable state, end recording compile the cb on gpu??
vkEndCommandBuffer(command_buffer[0]);// ***
}
{
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
//begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
// recording state
vkBeginCommandBuffer(command_buffer[1], &begin_info);// ***
// vkCmd...
// need to set viewport per command buffer
VkViewport viewport{};
viewport.maxDepth = 1.0f;
viewport.minDepth = 0.0f;
viewport.width = 512;
viewport.height = 512;
viewport.x = 0;
viewport.y = 0;
vkCmdSetViewport(command_buffer[1], 0, 1, &viewport);// ***
// executable state, end recording compile the cb on gpu??
vkEndCommandBuffer(command_buffer[1]);// ***
}
{
// submit command buffer to gpu
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer[0];// ***
submit_info.signalSemaphoreCount = 1;// ***
submit_info.pSignalSemaphores = &semaphore;// signal the semaphore// ***
vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);// ***
}
{
//VkPipelineStageFlags flags[]{ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT };
VkPipelineStageFlags flags[]{ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT };// all need to be done after signaled// ***
// submit command buffer to gpu
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer[1];// ***
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore;// ***
// where we are going to wait for semaphores, as signaled then access certain stage
// as the command buffer reaches fragment shader stage, it wait for the semaphore
submit_info.pWaitDstStageMask = flags;// pipeline stage mask// ***
// submit command buffer to gpu
vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);// ***
}
// true: need to wait for all fence to complete before continue, false: wait only 1 fence
//vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
vkQueueWaitIdle(queue);
// destroy command pool
vkDestroyCommandPool(device, command_pool, nullptr);
vkDestroyFence(device, fence, nullptr);
vkDestroySemaphore(device, semaphore, nullptr);
课程结束完整代码
main.cpp
#include "Renderer.h"
int main() {
Renderer r;
// need to send command into command pool when creating a window
auto device = r._device;
auto queue = r._queue;
// Fence
// wait for the gpu to be ready on the cpu side?
// cpu wait for gpu
VkFence fence;
VkFenceCreateInfo fence_create_info{};
fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkCreateFence(device, &fence_create_info, nullptr, &fence);
// Semaphore
// semaphore tells gpu when other process completed
VkSemaphore semaphore;
VkSemaphoreCreateInfo semaphore_create_info{};
semaphore_create_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vkCreateSemaphore(device ,&semaphore_create_info, nullptr, &semaphore);
//semaphore_create_info.flag
// Command Pool
// allocate command buffers in a pool
// as destroy pool, also destroy all buffers
VkCommandPool command_pool;
VkCommandPoolCreateInfo pool_create_info{};
pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_create_info.queueFamilyIndex = r._graphics_family_index;// probably which queue to execute the commmand
pool_create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
std::cout << "Command Pool Created" << std::endl;
ErrorCheck(vkCreateCommandPool(device, &pool_create_info, nullptr, &command_pool));
// Command Buffer
VkCommandBuffer command_buffer[2];
VkCommandBufferAllocateInfo command_buffer_allocate_info{};
command_buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_buffer_allocate_info.commandPool = command_pool;
command_buffer_allocate_info.commandBufferCount = 2;// how many command buffer to allocate for the pool
command_buffer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;//
// initial state
vkAllocateCommandBuffers(device, &command_buffer_allocate_info, command_buffer);
{
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
//begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
// recording state
vkBeginCommandBuffer(command_buffer[0], &begin_info);
// vkCmd...
vkCmdPipelineBarrier(command_buffer[0], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 0, nullptr);
// need to set viewport per command buffer
VkViewport viewport{};
viewport.maxDepth = 1.0f;
viewport.minDepth = 0.0f;
viewport.width = 512;
viewport.height = 512;
viewport.x = 0;
viewport.y = 0;
vkCmdSetViewport(command_buffer[0], 0, 1, &viewport);
// executable state, end recording compile the cb on gpu??
vkEndCommandBuffer(command_buffer[0]);
}
{
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
//begin_info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
// recording state
vkBeginCommandBuffer(command_buffer[1], &begin_info);
// vkCmd...
// need to set viewport per command buffer
VkViewport viewport{};
viewport.maxDepth = 1.0f;
viewport.minDepth = 0.0f;
viewport.width = 512;
viewport.height = 512;
viewport.x = 0;
viewport.y = 0;
vkCmdSetViewport(command_buffer[1], 0, 1, &viewport);
// executable state, end recording compile the cb on gpu??
vkEndCommandBuffer(command_buffer[1]);
}
{
// submit command buffer to gpu
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer[0];
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &semaphore;// signal the semaphore
// submit command buffer to gpu
//vkQueueSubmit(queue, 1, &submit_info, fence);
vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
}
{
//VkPipelineStageFlags flags[]{ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT };
VkPipelineStageFlags flags[]{ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT };// all need to be done after signaled
// submit command buffer to gpu
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer[1];
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &semaphore;
// where we are going to wait for semaphores, as signaled then access certain stage
// as the command buffer reaches fragment shader stage, it wait for the semaphore
submit_info.pWaitDstStageMask = flags;// pipeline stage mask
// submit command buffer to gpu
vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
}
// true: need to wait for all fence to complete before continue, false: wait only 1 fence
//vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
// gpu works concurrently with cpu, wait for the queue
// wait for the submit to be done
// if commented , error: Attempt to destroy command pool with VkCommandBuffer 0x2109f440ab0[] which is in use.
// because command buffer wasn't complete on gpu when cpu tries to delete it,need to wait on cpu side
vkQueueWaitIdle(queue);
// destroy command pool
vkDestroyCommandPool(device, command_pool, nullptr);
vkDestroyFence(device, fence, nullptr);
vkDestroySemaphore(device, semaphore, nullptr);
}
Render.cpp
#include "Renderer.h"
Renderer::Renderer() {
_SetupDebug();
_InitInstance();
_InitDebug();
_InitDevice();
}
Renderer::~Renderer() {
_DeInitDevice();
_DeInitDebug();
_DeInitInstance();
}
void Renderer::_InitInstance()
{
VkApplicationInfo application_info{};
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
application_info.apiVersion = VK_API_VERSION_1_3;//tells driver api version
application_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
application_info.pApplicationName = "Vulkan_tutorial_1";
VkInstanceCreateInfo instance_create_info{};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.pApplicationInfo = &application_info;
instance_create_info.enabledLayerCount = _instance_layers.size();
instance_create_info.ppEnabledLayerNames = _instance_layers.data();
instance_create_info.enabledExtensionCount = _instance_extensions.size();
instance_create_info.ppEnabledExtensionNames = _instance_extensions.data();
//instance_create_info.pNext = &debug_callback_create_info;// add loader message
//std::cout << "Vulkan Instance create error check" << std::endl;
ErrorCheck(vkCreateInstance(&instance_create_info, nullptr, &_Instance));
}
void Renderer::_DeInitInstance() {
vkDestroyInstance(_Instance, nullptr);
_Instance = nullptr;
}
void Renderer::_InitDevice()
{
// give the logical device used to render
{
uint32_t gpu_count = 0;
// return gpu_count
vkEnumeratePhysicalDevices(_Instance, &gpu_count, nullptr);
std::vector<VkPhysicalDevice> gpu_list(gpu_count);
// return the number of handles actually written to pPhysicalDevices
vkEnumeratePhysicalDevices(_Instance, &gpu_count, gpu_list.data());
_gpu = gpu_list[0];
// properties are returned
vkGetPhysicalDeviceProperties(_gpu, &_gpu_properties);
}
{
// get _graphics_family_index
// similarly query properties of queues available on a physical device
uint32_t family_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, nullptr);
std::vector<VkQueueFamilyProperties> family_property_list{ family_count };
vkGetPhysicalDeviceQueueFamilyProperties(_gpu, &family_count, family_property_list.data());
bool found = false;
for (uint32_t i = 0; i < family_count; ++i) {
// VK_QUEUE_GRAPHICS_BIT specifies that queues in this queue family support graphics operations.
if (family_property_list[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
found = true;
_graphics_family_index = i;
}
}
if (!found) {
assert(0 && "VULKAN ERROR: QUEUE FAMILY SUPPORT NOT FOUND");
std::cout << "VULKAN ERROR: QUEUE FAMILY SUPPORT NOT FOUND " << std::endl;
std::exit(-1);
}
}
{
// how many instance layers, instances
uint32_t layer_count = 0;
vkEnumerateInstanceLayerProperties(&layer_count, nullptr);
std::vector<VkLayerProperties> layer_property_list(layer_count);
// gives the layer currently installed in the system
vkEnumerateInstanceLayerProperties(&layer_count, layer_property_list.data());
std::cout << "instance_layers " << std::endl;
for (auto& i : layer_property_list) {
std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl;
}
std::cout << std::endl;
/*
instance_layers
VK_LAYER_AMD_switchable_graphics | AMD switchable graphics layer
VK_LAYER_RENDERDOC_Capture | Debugging capture layer for RenderDoc
VK_LAYER_LUNARG_api_dump | LunarG API dump layer
VK_LAYER_LUNARG_gfxreconstruct | GFXReconstruct Capture Layer Version 0.9.15
VK_LAYER_KHRONOS_synchronization2 | Khronos Synchronization2 layer
VK_LAYER_KHRONOS_validation | Khronos Validation Layer
VK_LAYER_LUNARG_monitor | Execution Monitoring Layer
VK_LAYER_LUNARG_screenshot | LunarG image capture layer
VK_LAYER_KHRONOS_profiles | Khronos Profiles layer
*/
}
{
// how many instance layers, instances
uint32_t layer_count = 0;
vkEnumerateDeviceLayerProperties(_gpu, &layer_count, nullptr);
std::vector<VkLayerProperties> layer_property_list(layer_count);
// gives the layer currently installed in the system
vkEnumerateDeviceLayerProperties(_gpu, &layer_count, layer_property_list.data());
std::cout << "device_layers " << std::endl;
for (auto& i : layer_property_list) {
std::cout << " " << i.layerName << "\t\t | " << i.description << std::endl;
}
std::cout << std::endl;
}
float queue_priorities[]{ 1.0f };
VkDeviceQueueCreateInfo device_queue_create_info{};
device_queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
device_queue_create_info.queueFamilyIndex = _graphics_family_index;
device_queue_create_info.queueCount = 1;
device_queue_create_info.pQueuePriorities = queue_priorities;
VkDeviceCreateInfo device_create_info{};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.queueCreateInfoCount = 1;
device_create_info.pQueueCreateInfos = &device_queue_create_info;
device_create_info.enabledLayerCount = _device_layers.size();
device_create_info.ppEnabledLayerNames = _device_layers.data();
device_create_info.enabledExtensionCount = _device_extensions.size();
device_create_info.ppEnabledExtensionNames = _device_extensions.data();
// return device
//std::cout << "VULKAN ERROR: QUEUE FAMILY SUPPORTING GRAPHICS NOT FOUND CHECK" << std::endl;
ErrorCheck(vkCreateDevice(_gpu, &device_create_info, nullptr, &_device));
// fetch the queue handle
vkGetDeviceQueue(_device, _graphics_family_index, 0, &_queue);// 0 < queue_count_family = 1
}
void Renderer::_DeInitDevice() {
vkDestroyDevice(_device, nullptr);
_device = nullptr;
}
VKAPI_ATTR VkBool32 VKAPI_CALL
VulkanDebugCallBack(
VkDebugReportFlagsEXT flags,// VkDebugReportCallbackCreateInfoEXT.flags
VkDebugReportObjectTypeEXT obj_type,
uint64_t src_obj,
size_t location,
int32_t msg_code,
const char* layer_prefix,
const char* msg,
void* user_data
)
{
// flags has bit on xxx
if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
std::cout << "DEBUG INFO: ";
}
if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
std::cout << "DEBUG WARNING: ";
}
if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
std::cout << "DEBUG PERFORMANCE_WARNING: ";
}
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
std::cout << "DEBUG ERROR: ";
}
if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
std::cout << "DEBUG DEBUG: ";
}
std::cout << "@[ " << layer_prefix << " ]: ";
std::cout << msg << std::endl;
return false;
}
void Renderer::_SetupDebug()
{
debug_callback_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
debug_callback_create_info.pfnCallback = VulkanDebugCallBack;// PFN_vkDebugReportCallbackEXT
debug_callback_create_info.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT | \
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;
// layer needed to use is in the device, must be in the instance
_instance_layers.push_back("VK_LAYER_KHRONOS_validation");
_device_layers.push_back("VK_LAYER_KHRONOS_validation");
//_instance_layers.push_back("VK_LAYER_AMD_switchable_graphics");
//_device_layers.push_back("VK_LAYER_AMD_switchable_graphics");
_instance_layers.push_back("VK_LAYER_RENDERDOC_Capture");
_device_layers.push_back("VK_LAYER_RENDERDOC_Capture");
// too much info
//_instance_layers.push_back("VK_LAYER_LUNARG_api_dump");
//_device_layers.push_back("VK_LAYER_LUNARG_api_dump");
_instance_layers.push_back("VK_LAYER_LUNARG_gfxreconstruct");
_device_layers.push_back("VK_LAYER_LUNARG_gfxreconstruct");
// VK_ERROR_LAYER_NOT_PRESENT
//_instance_layers.push_back(" VK_LAYER_KHRONOS_synchronization2");
//_device_layers.push_back(" VK_LAYER_KHRONOS_synchronization2");
//_instance_layers.push_back("VK_LAYER_LUNARG_monitor");
//_device_layers.push_back("VK_LAYER_LUNARG_monitor");
//_instance_layers.push_back("VK_LAYER_LUNARG_screenshot");
//_device_layers.push_back("VK_LAYER_LUNARG_screenshot");
//_instance_layers.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
_instance_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
//_device_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
// VK_ERROR_LAYER_NOT_PRESENT
//_instance_layers.push_back(" VK_LAYER_KHRONOS_profiles");
//_device_layers.push_back(" VK_LAYER_KHRONOS_profiles");
}
PFN_vkCreateDebugReportCallbackEXT fvkCreateDebugReportCallbackEXT = nullptr;
PFN_vkDestroyDebugReportCallbackEXT fvkDestroyDebugReportCallbackEXT = nullptr;
void Renderer::_InitDebug()
{
// function pointer??
fvkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(_Instance, "vkCreateDebugReportCallbackEXT");
fvkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(_Instance, "vkDestroyDebugReportCallbackEXT");
if (nullptr == fvkCreateDebugReportCallbackEXT || nullptr == fvkDestroyDebugReportCallbackEXT) {
assert(0 && "Vulkan can't take debug function pointer");
std::cout << "Vulkan can't take debug function pointer" << std::endl;
std::exit(-1);
}
//std::cout << "Vulkan failed to set up a debug message check" << std::endl;
ErrorCheck(fvkCreateDebugReportCallbackEXT(_Instance, &debug_callback_create_info, nullptr, &_debug_report));
//fvkCreateDebugReportCallbackEXT(_Instance, nullptr, nullptr, nullptr);
}
void Renderer::_DeInitDebug()
{
fvkDestroyDebugReportCallbackEXT(_Instance, _debug_report, nullptr);
_debug_report = VK_NULL_HANDLE;
}
Render.h
#pragma once
#include <vulkan/vulkan.h>
#include "Shared.h"
#include <vector>
#include <iostream>
#include <cstdlib>
#include <assert.h>
class Renderer
{
public:
Renderer();
~Renderer();
//private:
void _InitInstance();
void _DeInitInstance();
void _InitDevice();
void _DeInitDevice();
void _SetupDebug();
void _InitDebug();
void _DeInitDebug();
VkInstance _Instance = VK_NULL_HANDLE;
VkPhysicalDevice _gpu = VK_NULL_HANDLE;
VkDevice _device = VK_NULL_HANDLE;
VkPhysicalDeviceProperties _gpu_properties = {};
VkQueue _queue = VK_NULL_HANDLE;
uint32_t _graphics_family_index = 0;
std::vector<const char*> _instance_layers;
std::vector<const char*> _instance_extensions;
std::vector<const char*> _device_layers;
std::vector<const char*> _device_extensions;
VkDebugReportCallbackEXT _debug_report = VK_NULL_HANDLE;
VkDebugReportCallbackCreateInfoEXT debug_callback_create_info{};
};