Move back to C++

This commit is contained in:
Piotr Krygier committed 2022-07-05 16:03:31 -04:00
1 parent 4755371ffa
commit ce0c399810
13 files changed
+44 -83

No files matched your search

+605
View File
@@ -0,0 +1,605 @@
/**
* @file vulkanBase.cpp
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief Base configuration for Vulkan API
* @version 0.1
* @date 2022-05-13
*
* @copyright Copyright (c) 2022
*
*/
/* TODO: Replace with more dynamic include */
#define VK_USE_PLATFORM_XCB_KHR
#include "vulkanBase.hpp"
#include <vulkan/vulkan.h>
#include <vk_mem_alloc.h>
#include <GLFW/glfw3.h>
#include "localeVulkan.hpp"
#include "log.hpp"
#include "window.hpp"
#include <vector>
#include <string>
enum VULKAN_ERROR
{
VULKAN_ERROR_NO_ERROR = 0x0U,
VULKAN_ERROR_INSTANCE_INIT_FAILED,
VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND,
VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND,
VULKAN_ERROR_QUEUE_NOT_SUPPORTED,
VULKAN_ERROR_DEVICE_CREATION_FAILED,
VULKAN_ERROR_ALLOCATOR_CREATION_FAILED,
VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED,
VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED,
VULKAN_ERROR_SURFACE_CREATION_FAILED,
VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED,
VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED,
};
/* Macro for checking status of function execution in initVulkan. Created to avoid writing boilerplate code */
#define STATUS_CHECK(FUNC) \
status = FUNC; \
if (VULKAN_ERROR_NO_ERROR != status) { \
return status; \
}
#define APPLICATION_NAME "RedScarfEngine PoC"
#define ENGINE_NAME "RedScarf Engine"
#define SWAP_BUFFER_COUNT 2U
/* Define Validation Layers for debug build */
#ifndef NDEBUG
std::vector<std::string> gEnabledInstanceLayersNames = {"VK_LAYER_KHRONOS_validation"};
#else
std::vector<std::string> gEnabledInstanceLayersNames = {};
#endif
#define ENABLED_DEVICE_EXTENSIONS_COUNT 1U
/* Extensions required by GLFW. TODO: Check for extensions required on other platforms */
std::vector<std::string> gEnabledInstanceExtensionsNames = {
"VK_KHR_surface",
"VK_KHR_xcb_surface",
"VK_KHR_device_group_creation",
#ifndef NDEBUG
"VK_EXT_debug_utils",
#endif
};
std::vector<std::string> gEnabledDeviceExtensionsNames[ENABLED_DEVICE_EXTENSIONS_COUNT] = {
"VK_KHR_swapchain",
};
uint32_t gQueueFamilyIndices[1] = {0U}; /* TODO: Change when more families are needed */
uint32_t gSwapchainImagesCount = 0U;
VkInstance gVulkanInstance = VK_NULL_HANDLE;
VkSurfaceKHR gSurface = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT gDebugMessenger = VK_NULL_HANDLE;
VkPhysicalDevice gPhysicalDevice = VK_NULL_HANDLE;
VkDevice gDevice = VK_NULL_HANDLE;
VmaAllocator gAllocator = VK_NULL_HANDLE;
VkCommandPool gCommandPool = VK_NULL_HANDLE;
VkCommandBuffer* gpCommandBuffers = NULL; /* This one is an array. Allocated during runtime */
VkSwapchainKHR gSwapchain = VK_NULL_HANDLE;
VkImage* gpSwapChainImages = NULL;
VkImageView* gpSwapChainImageViews = NULL;
/**
* @brief Create the Vulkan Instance object
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_INSTANCE_INIT_FAILED
*/
static int createInstance();
/**
* @brief Create a Surface, connection between Vulkan and actual window
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
*/
static int createSurface();
/**
* @brief Choose physical device. Used later for vkDevice
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND
* VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND
*/
static int pickPhysicalDevice();
/**
* @brief Create vkDevice object
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_QUEUE_NOT_SUPPORTED
* VULKAN_ERROR_DEVICE_CREATION_FAILED
*/
static int createDevice();
#ifndef NDEBUG
/**
* @brief Setup debugging system for Vulkan API
*
*/
static void setupDebugMessenger();
/**
* @brief Create a Memory Allocator object
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_ALLOCATOR_CREATION_FAILED
*/
static int createMemoryAllocator();
/**
* @brief Create Command Pools
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED
*/
static int createCommandPools();
/**
* @brief Allocate Command Buffers
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED
*/
static int allocateCommandBuffers();
/**
* @brief Create a Swapchain
*
* @return int VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED
*/
static int createSwapchain();
/**
* @brief Create a Swapchain Image Views
*
* @return int int VULKAN_ERROR_NO_ERROR on success. Possible errors:
*/
static int createSwapchainImageViews();
/**
* @brief Calback for debug messenger
*
* @param messageSeverity Message severity
* @param messageType Type of a message
* @param pCallbackData Contains all the callback related data in the VkDebugUtilsMessengerCallbackDataEXT structure
* @param pUserData Data provided by the user
* @return VkBool32 Should always return VK_FALSE. The VK_TRUE value is reserved for use in layer development
*/
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData)
{
(void)messageSeverity;
(void)messageType;
(void)pUserData;
fprintf(stderr, "validation layer: %s\n", pCallbackData->pMessage);
return VK_FALSE;
}
/**
* @brief Proxy for vkCreateDebugUtilsMessengerEXT
*
* @param instance Vulkan instance object
* @param pCreateInfo VkDebugUtilsMessengerCreateInfoEXT structure
* @param pAllocator Memory allocator
* @param pDebugMessenger Debug messanger handle
* @return VkResult VK_SUCCESS on success
*/
static VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDebugUtilsMessengerEXT* pDebugMessenger)
{
PFN_vkCreateDebugUtilsMessengerEXT func = NULL;
func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
if (func != NULL) {
return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
} else {
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
return VK_SUCCESS;
}
/**
* @brief Proxy for vkDestroyDebugUtilsMessengerEXT
*
* @param instance Vulkan instance object
* @param debugMessenger Debug messanger handle
* @param pAllocator Memory allocator
*/
static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger,
const VkAllocationCallbacks* pAllocator)
{
PFN_vkDestroyDebugUtilsMessengerEXT func =
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
if (func != NULL) {
func(instance, debugMessenger, pAllocator);
}
}
static void setupDebugMessenger()
{
VkDebugUtilsMessengerCreateInfoEXT createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
createInfo.pfnUserCallback = debugCallback;
createInfo.pUserData = NULL; // Optional
createInfo.flags = 0U;
if (CreateDebugUtilsMessengerEXT(gVulkanInstance, &createInfo, NULL, &gDebugMessenger) != VK_SUCCESS) {
fprintf(stderr, "failed to set up debug messenger!");
}
}
#endif
static int createInstance()
{
uint32_t extensionCount = 0;
uint32_t layersCount = 0;
VkApplicationInfo applicationInfo;
VkInstanceCreateInfo createInfo;
std::vector<VkLayerProperties> layerProperties;
std::vector<VkExtensionProperties> extensionsProperties;
/* TODO: Remove or use later layer and extension properties */
vkEnumerateInstanceLayerProperties(&layersCount, NULL);
layerProperties.resize(layersCount);
vkEnumerateInstanceLayerProperties(&layersCount, layerProperties);
vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
extensionsProperties = malloc(sizeof(VkExtensionProperties) * extensionCount);
vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensionsProperties);
printf("Supported Layers: \n");
for (size_t i = 0; i < layersCount; i++) {
printf("%s\n", layerProperties[i].layerName);
}
printf("Supported Extensions: \n");
for (size_t i = 0; i < extensionCount; i++) {
printf("%s\n", extensionsProperties[i].extensionName);
}
applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
applicationInfo.pNext = NULL;
applicationInfo.pApplicationName = APPLICATION_NAME;
applicationInfo.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
applicationInfo.pEngineName = ENGINE_NAME;
applicationInfo.engineVersion = VK_MAKE_VERSION(0, 1, 0);
applicationInfo.apiVersion = VK_API_VERSION_1_2; /* TODO: Wait for package update to 1.3 */
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pNext = NULL;
createInfo.flags = 0U;
createInfo.pApplicationInfo = &applicationInfo;
createInfo.enabledLayerCount = gEnabledInstanceLayersNames.size();
#ifndef NDEBUG
createInfo.ppEnabledLayerNames = gEnabledInstanceLayersNames;
#else
createInfo.ppEnabledLayerNames = NULL;
#endif
createInfo.enabledExtensionCount = gEnabledInstanceExtensionsNames.size();
createInfo.ppEnabledExtensionNames = gEnabledInstanceExtensionsNames;
VkResult result = vkCreateInstance(&createInfo, NULL, &gVulkanInstance);
if (VK_SUCCESS != result) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_INTANCE_INIT_FAILED]));
return VULKAN_ERROR_INSTANCE_INIT_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static int createSurface()
{
if (VK_SUCCESS != glfwCreateWindowSurface(gVulkanInstance, getWindowHandle(), NULL, &gSurface)) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_SURFACE_CREATION_FAILED]));
return VULKAN_ERROR_SURFACE_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static int pickPhysicalDevice()
{
uint32_t physicalDeviceCount = 0U;
VkPhysicalDevice* pPhysicalDevices = NULL;
/* Get number of existing physical devices */
vkEnumeratePhysicalDevices(gVulkanInstance, &physicalDeviceCount, NULL);
if (0 == physicalDeviceCount) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND]));
return VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND;
}
pPhysicalDevices = malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
vkEnumeratePhysicalDevices(gVulkanInstance, &physicalDeviceCount, pPhysicalDevices);
/* Check for suitability */
for (size_t physicalDeviceIdx = 0U; physicalDeviceIdx < physicalDeviceCount; ++physicalDeviceIdx) {
/* TODO: Check for support */
VkPhysicalDeviceProperties deviceProperties;
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceProperties(pPhysicalDevices[physicalDeviceIdx], &deviceProperties);
vkGetPhysicalDeviceFeatures(pPhysicalDevices[physicalDeviceIdx], &deviceFeatures);
/* Expect discrete graphics device type */
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
gPhysicalDevice = pPhysicalDevices[physicalDeviceIdx];
}
}
free(pPhysicalDevices);
if (VK_NULL_HANDLE == gPhysicalDevice) {
/* No suitable device found */
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_NO_SUITABLE_PHYSICAL_DEVICES]));
return VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND;
}
return VULKAN_ERROR_NO_ERROR;
}
static int createDevice()
{
uint32_t queueFamiliesPropertyCount = 0U;
ssize_t supportingQueueFamilityIdx = -1;
VkQueueFamilyProperties* pQueueFamilyProperties = NULL;
VkDeviceCreateInfo deviceCreateInfo = {0};
VkDeviceQueueCreateInfo deviceQueueCreateInfos[1] = {0}; /* TODO: Change when we want more queues */
float* pQueuePriorities = NULL;
/* Get information about supported queue families */
vkGetPhysicalDeviceQueueFamilyProperties(gPhysicalDevice, &queueFamiliesPropertyCount, NULL);
pQueueFamilyProperties = malloc(sizeof(VkQueueFamilyProperties) * queueFamiliesPropertyCount);
vkGetPhysicalDeviceQueueFamilyProperties(gPhysicalDevice, &queueFamiliesPropertyCount, pQueueFamilyProperties);
/* Get queue families that support graphics operations AND have most
* queues. */
{
size_t numberOfQueues = 0;
for (size_t familyIdx = 0; familyIdx < queueFamiliesPropertyCount; ++familyIdx) {
if (pQueueFamilyProperties[familyIdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
if (pQueueFamilyProperties[familyIdx].queueCount > numberOfQueues) {
supportingQueueFamilityIdx = familyIdx;
numberOfQueues = pQueueFamilyProperties[familyIdx].queueCount;
}
}
}
}
/* This is not magic number ;P. We want to support exact number of required queues flags */
if (0 > supportingQueueFamilityIdx) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_QUEUE_NOT_SUPPORTED]));
return VULKAN_ERROR_QUEUE_NOT_SUPPORTED;
}
gQueueFamilyIndices[0] = supportingQueueFamilityIdx; /* TODO: Change when more families are needed */
pQueuePriorities = malloc(pQueueFamilyProperties[supportingQueueFamilityIdx].queueCount * sizeof(float));
for (size_t i = 0; i < pQueueFamilyProperties[supportingQueueFamilityIdx].queueCount; i++) {
pQueuePriorities[i] = 1.0f; /* TODO: When queues have different tasks, change this if needed */
}
deviceQueueCreateInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
deviceQueueCreateInfos[0].pNext = NULL;
deviceQueueCreateInfos[0].flags = 0;
deviceQueueCreateInfos[0].queueFamilyIndex = supportingQueueFamilityIdx;
deviceQueueCreateInfos[0].queueCount = pQueueFamilyProperties[supportingQueueFamilityIdx].queueCount;
deviceQueueCreateInfos[0].pQueuePriorities = pQueuePriorities;
free(pQueueFamilyProperties); /* Not needed anymore */
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.pNext = NULL;
deviceCreateInfo.flags = 0U;
deviceCreateInfo.queueCreateInfoCount = 1u; /* For now one is enough. TODO: Change when needed. */
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfos;
deviceCreateInfo.enabledLayerCount = 0;
deviceCreateInfo.ppEnabledLayerNames = NULL;
deviceCreateInfo.enabledExtensionCount = ENABLED_DEVICE_EXTENSIONS_COUNT;
deviceCreateInfo.ppEnabledExtensionNames = gEnabledDeviceExtensionsNames;
deviceCreateInfo.pEnabledFeatures = NULL; /* TODO: Enable features, when needed */
if (VK_SUCCESS != vkCreateDevice(gPhysicalDevice, &deviceCreateInfo, NULL, &gDevice)) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_FAILED_TO_CREATE_DEVICE]));
free(pQueuePriorities);
return VULKAN_ERROR_DEVICE_CREATION_FAILED;
}
free(pQueuePriorities);
return VULKAN_ERROR_NO_ERROR;
}
static int createMemoryAllocator()
{
VmaVulkanFunctions vulkanFunctions = {0};
vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
VmaAllocatorCreateInfo allocatorCreateInfo = {0};
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
allocatorCreateInfo.physicalDevice = gPhysicalDevice;
allocatorCreateInfo.device = gDevice;
allocatorCreateInfo.instance = gVulkanInstance;
allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
if (VK_SUCCESS != vmaCreateAllocator(&allocatorCreateInfo, &gAllocator)) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_ERROR_ALLOCATOR_CREATION_FAILED]));
return VULKAN_ERROR_ALLOCATOR_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static int createCommandPools()
{
VkCommandPoolCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
createInfo.pNext = NULL;
createInfo.flags = 0U;
createInfo.queueFamilyIndex = gQueueFamilyIndices[0]; /* TODO: Change when more families are needed */
if (VK_SUCCESS != vkCreateCommandPool(gDevice, &createInfo, NULL, &gCommandPool)) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_COMMAND_POOL_CREATION_FAILED]));
return VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static int allocateCommandBuffers()
{
VkCommandBufferAllocateInfo allocateInfo;
/* Allocate memory for command buffers */
gpCommandBuffers = malloc(sizeof(VkCommandBuffer) * SWAP_BUFFER_COUNT);
allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocateInfo.pNext = NULL;
allocateInfo.commandPool = gCommandPool;
allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; /* TODO: When needed, add secondary command buffer */
allocateInfo.commandBufferCount = SWAP_BUFFER_COUNT;
if (VK_SUCCESS != vkAllocateCommandBuffers(gDevice, &allocateInfo, gpCommandBuffers)) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED]));
return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
static int createSwapchain()
{
VkSwapchainCreateInfoKHR createInfo;
VkSurfaceCapabilitiesKHR physicalDeviceSurfaceCapabilities;
VkBool32 surfaceSupported;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gPhysicalDevice, gSurface, &physicalDeviceSurfaceCapabilities);
/* Check if device supports surface for presentation */
vkGetPhysicalDeviceSurfaceSupportKHR(gPhysicalDevice, gQueueFamilyIndices[0], gSurface, &surfaceSupported);
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.pNext = NULL;
createInfo.flags = 0U;
createInfo.surface = gSurface;
createInfo.minImageCount = SWAP_BUFFER_COUNT;
createInfo.imageFormat = VK_FORMAT_B8G8R8A8_SRGB; /* TODO: Check for supported formats */
createInfo.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; /* TODO: Check for supported color space */
createInfo.imageExtent = physicalDeviceSurfaceCapabilities.currentExtent;
createInfo.imageArrayLayers = 1U; /* For non-stereoscopic-3D applications, this value is 1. */
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; /* TODO: Probably change later? Dunno */
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* Using only one queue family, so this is ok */
createInfo.queueFamilyIndexCount = 1U;
createInfo.pQueueFamilyIndices = gQueueFamilyIndices;
createInfo.preTransform = physicalDeviceSurfaceCapabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; /* TODO: Choose present mode from VkPresentModeKHR */
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (VK_SUCCESS != vkCreateSwapchainKHR(gDevice, &createInfo, NULL, &gSwapchain)) {
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_SWAPCHAIN_CREATION_FAILED]));
return VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED;
}
/* Obtain swapchain images */
vkGetSwapchainImagesKHR(gDevice, gSwapchain, &gSwapchainImagesCount, NULL);
gpSwapChainImages = malloc(sizeof(VkImage) * gSwapchainImagesCount);
vkGetSwapchainImagesKHR(gDevice, gSwapchain, &gSwapchainImagesCount, gpSwapChainImages);
return VULKAN_ERROR_NO_ERROR;
}
static int createSwapchainImageViews()
{
gpSwapChainImageViews = malloc(sizeof(VkImageView) * gSwapchainImagesCount);
for (size_t i = 0; i < gSwapchainImagesCount; i++) {
VkImageViewCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.pNext = NULL;
createInfo.flags = 0U;
createInfo.image = gpSwapChainImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; /* 2D Texture */
createInfo.format = VK_FORMAT_B8G8R8A8_SRGB;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0U;
createInfo.subresourceRange.levelCount = 1U;
createInfo.subresourceRange.baseArrayLayer = 0U;
createInfo.subresourceRange.layerCount = 1U;
if(VK_SUCCESS != vkCreateImageView(gDevice, &createInfo, NULL, &gpSwapChainImageViews[i]))
{
LOG(FATAL, "%s", LOCALIZE(vulkanErrorMesssages[VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED]));
return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED;
}
}
return VULKAN_ERROR_NO_ERROR;
}
int initVulkan()
{
int status = VULKAN_ERROR_NO_ERROR;
STATUS_CHECK(createInstance());
#ifndef NDEBUG
setupDebugMessenger();
#endif
STATUS_CHECK(createSurface());
STATUS_CHECK(pickPhysicalDevice());
STATUS_CHECK(createDevice());
STATUS_CHECK(createMemoryAllocator());
STATUS_CHECK(createCommandPools());
STATUS_CHECK(allocateCommandBuffers());
STATUS_CHECK(createSwapchain());
STATUS_CHECK(createSwapchainImageViews());
return status;
}
void deinitVulkan()
{
for (size_t i = 0; i < gSwapchainImagesCount; i++) {
vkDestroyImageView(gDevice ,gpSwapChainImageViews[i], NULL);
}
vkDestroySwapchainKHR(gDevice, gSwapchain, NULL);
vkDestroyCommandPool(gDevice, gCommandPool, NULL);
vmaDestroyAllocator(gAllocator);
vkDestroyDevice(gDevice, NULL);
#ifndef NDEBUG
DestroyDebugUtilsMessengerEXT(gVulkanInstance, gDebugMessenger, NULL);
#endif
vkDestroySurfaceKHR(gVulkanInstance, gSurface, NULL);
vkDestroyInstance(gVulkanInstance, NULL);
}