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

-18
View File
@@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 3.10)
project(GraphicsEngine)
add_library(${PROJECT_NAME} SHARED
src/window.c
src/vmaInit.cpp
src/vulkanBase.c)
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/locales
${CMAKE_SOURCE_DIR}/third_party/vma/include
${CMAKE_SOURCE_DIR}/Utilities/include)
target_link_libraries(${PROJECT_NAME}
vulkan
glfw)
-18
View File
@@ -1,18 +0,0 @@
/**
* @file vulkanBase.h
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief Vulkan wrapper functions used by other parts of Graphics component
* @version 0.1
* @date 2022-05-13
*
* @copyright Copyright (c) 2022
*
*/
#ifndef VULKAN_BASE_H
#define VULKAN_BASE_H
int initVulkan();
void deinitVulkan();
#endif /* VULKAN_BASE_H */
-45
View File
@@ -1,45 +0,0 @@
/**
* @file window.h
* @author Piotr Krygier (everyonencancode@gmail.com)
* @brief Window control system
* @version 0.1
* @date 2022-02-15
*
* @copyright Copyright (c) 2022
*
*/
#ifndef WINDOW_HANDLER_H
#define WINDOW_HANDLER_H
/* Vulkan header MUST be included before glfw */
#include <vulkan/vulkan.h>
#include <GLFW/glfw3.h>
/**
* @brief Initialize window
*
* @return uint16_t WINDOW_SUCCESS on success. Possible errors:
* WINDOW_VULKAN_NOT_LOADED
* WINDOW_WINDOW_NOT_CREATED
*
*/
uint16_t windowInit();
/**
* @brief Main window loop
*
* @return uint16_t WINDOW_SUCCESS or error code
*/
uint16_t windowLoop();
/**
* @brief Closes window and terminates GLFW
*
*/
void windowTerminate();
GLFWwindow* getWindowHandle();
#endif /* WINDOW_HANDLER_H */
-104
View File
@@ -1,104 +0,0 @@
/**
* @file localeVulkan.h
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief Error messages for Vulkan initializers
* @version 0.1
* @date 2022-05-13
*
* @copyright Copyright (c) 2022
*
*/
#ifndef LOCALE_VULKAN_H
#define LOCALE_VULKAN_H
#include "localization.h"
enum Errors
{
VULKAN_INTANCE_INIT_FAILED,
VULKAN_NO_PHYSICAL_DEVICES,
VULKAN_NO_SUITABLE_PHYSICAL_DEVICES,
VULKAN_QUEUE_NOT_SUPPORTED,
VULKAN_FAILED_TO_CREATE_DEVICE,
VULKAN_ALLOCATOR_CREATION_FAILED,
VULKAN_COMMAND_POOL_CREATION_FAILED,
VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED,
VULKAN_SURFACE_CREATION_FAILED,
VULKAN_SWAPCHAIN_CREATION_FAILED,
VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED,
LAST_MESSAGE
};
const struct MessageString_t vulkanErrorMesssages[LAST_MESSAGE] =
{
{
38,
{/* VULKAN_INTANCE_INIT_FAILED */
"Vulkan instance initialization failed"
}
},
{
55,
{/* VULKAN_NO_PHYSICAL_DEVICES */
"No physical graphical physical devices found in system"
}
},
{
35,
{/* VULKAN_NO_SUITABLE_PHYSICAL_DEVICES */
"No suitable physical device found"
}
},
{
70,
{/* VULKAN_QUEUE_NOT_SUPPORTED */
"Selected physical device does not support required queue capabilities"
}
},
{
23,
{/* VULKAN_FAILED_TO_CREATE_DEVICE */
"Failed to create logical device"
}
},
{
41,
{/* VULKAN_ALLOCATOR_CREATION_FAILED */
"Failed to create Vulkan Memory Allocator"
}
},
{
30,
{/* VULKAN_COMMAND_POOL_CREATION_FAILED */
"Failed to create command pool"
}
},
{
35,
{/* VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED */
"Failed to allocate command buffers"
}
},
{
32,
{/* VULKAN_SURFACE_CREATION_FAILED */
"Failed to create window surface"
}
},
{
27,
{/* VULKAN_SWAPCHAIN_CREATION_FAILED */
"Failed to create swapchain"
}
},
{
38,
{/* VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED */
"Failed to create swapchain image view"
}
},
};
#endif
-41
View File
@@ -1,41 +0,0 @@
/**
* @file localeWindow.hxx
* @author Piotr Krygier (everyonencancode@gmail.com)
* @brief Error messages
* @version 0.1
* @date 2022-02-15
*
* @copyright Copyright (c) 2022
*
*/
#include "localization.h"
enum Errors
{
WINDOW_GLFW_INIT_FAILED,
WINDOW_VULKAN_NOT_SUPPORTED,
WINDOW_NOT_CREATED,
LAST_MESSAGE
};
const struct MessageString_t windowErrorMesssages[LAST_MESSAGE] =
{
{
17,
{/* WINDOW_GLFW_INIT_FAILED */
"GLFW init failed!"
}
},
{
22,
{/* WINDOW_VULKAN_NOT_SUPPORTED */
"Unable to load Vulkan"
}
},
{
31,
{/*WINDOW_NOT_CREATED*/
"Window context creation failed"
}}
};
-26
View File
@@ -1,26 +0,0 @@
/**
* @file vmaInit.cpp
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief VMA is written in C, but has C++ compatible interface. It still needs to compiled as C++ though, hence the
* file
* @version 0.1
* @date 2022-05-23
*
* @copyright Copyright (c) 2022
*
*/
#pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wunused"
# pragma GCC diagnostic warning "-Wpedantic"
# pragma GCC diagnostic warning "-Wignored-qualifiers"
# pragma GCC diagnostic warning "-Wmissing-field-initializers"
# pragma GCC diagnostic warning "-Wimplicit-fallthrough"
# pragma GCC diagnostic warning "-Wswitch"
# pragma GCC diagnostic warning "-Wparentheses"
#define VMA_IMPLEMENTATION
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#define VMA_STATS_STRING_ENABLED 0
#include <vk_mem_alloc.h>
#pragma GCC diagnostic pop
-610
View File
@@ -1,610 +0,0 @@
/**
* @file vulkanBase.c
* @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.h"
#include <stdbool.h>
#include <string.h>
#include <vulkan/vulkan.h>
#include <vk_mem_alloc.h>
#include <GLFW/glfw3.h>
#include "localeVulkan.h"
#include "log.h"
#include "window.h"
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
#define ENABLED_INSTANCE_LAYERS_COUNT 1U
#else
#define ENABLED_INSTANCE_LAYERS_COUNT 0U
#endif
#define ENABLED_INSTANCE_EXTENSIONS_COUNT 4U
#define ENABLED_DEVICE_EXTENSIONS_COUNT 1U
#ifndef NDEBUG
const char* gEnabledInstanceLayersNames[ENABLED_INSTANCE_LAYERS_COUNT] = {"VK_LAYER_KHRONOS_validation"};
#endif
/* Extensions required by GLFW. TODO: Check for extensions required on other platforms */
const char* gEnabledInstanceExtensionsNames[ENABLED_INSTANCE_EXTENSIONS_COUNT] = {
"VK_KHR_surface",
"VK_KHR_xcb_surface",
"VK_KHR_device_group_creation",
#ifndef NDEBUG
"VK_EXT_debug_utils",
#endif
};
const char* 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;
VkLayerProperties* layerProperties = NULL;
VkExtensionProperties* extensionsProperties = NULL;
/* TODO: Remove or use later layer and extension properties */
vkEnumerateInstanceLayerProperties(&layersCount, NULL);
layerProperties = malloc(sizeof(VkLayerProperties) * 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 = ENABLED_INSTANCE_LAYERS_COUNT;
#ifndef NDEBUG
createInfo.ppEnabledLayerNames = gEnabledInstanceLayersNames;
#else
createInfo.ppEnabledLayerNames = NULL;
#endif
createInfo.enabledExtensionCount = ENABLED_INSTANCE_EXTENSIONS_COUNT;
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);
}
-111
View File
@@ -1,111 +0,0 @@
/**
* @file window.cxx
* @author Piotr Krygier (everyonencancode@gmail.com)
* @brief
* @version 0.1
* @date 2022-02-15
*
* @copyright Copyright (c) 2022
*
*/
#include "window.h"
#include "localeWindow.h"
#include "log.h"
/* Error codes */
typedef enum {
WINDOW_ERROR_NO_ERROR = 0U,
WINDOW_ERROR_GLFW_INIT_FAILED,
WINDOW_ERROR_VULKAN_NOT_LOADED,
WINDOW_ERROR_WINDOW_NOT_CREATED
} WINDOW_ERROR;
GLFWwindow *gpWindowHandle = NULL;
/**
* @brief GLFW erro callback
*
* @param error Error code
* @param description Error description
*/
static void errrorCallback(int error, const char* description)
{
(void)error;
LOG(ERROR, "Error: %s", description);
}
/**
* @brief Pressed key callback
*
* @param window Window in which contex the key has been pressed
* @param key The keyboard key that was pressed or released
* @param scancode The system-specific scancode of the key.
* @param action GLFW_PRESS, GLFW_RELEASE or GLFW_REPEAT
* @param mods Bit field describing which modifier keys were held down
*/
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
(void)scancode;
(void)action;
(void)mods;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
uint16_t windowInit()
{
/* Initiliaze GLFW AP */
if (GLFW_TRUE != glfwInit())
{
LOG(FATAL, "%s", LOCALIZE(windowErrorMesssages[WINDOW_GLFW_INIT_FAILED]));
return WINDOW_ERROR_GLFW_INIT_FAILED;
}
/* Check for Vulkan support */
if (GLFW_FALSE == glfwVulkanSupported()) {
LOG(FATAL, "%s", LOCALIZE(windowErrorMesssages[WINDOW_VULKAN_NOT_SUPPORTED]));
return WINDOW_ERROR_VULKAN_NOT_LOADED;
}
/* Set error callback */
glfwSetErrorCallback(errrorCallback);
/* Create window */
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
gpWindowHandle = glfwCreateWindow(640, 480, "RedScarfEngine", NULL, NULL);
if (NULL == gpWindowHandle) {
LOG(FATAL, "%s", LOCALIZE(windowErrorMesssages[WINDOW_NOT_CREATED]));
return WINDOW_ERROR_WINDOW_NOT_CREATED;
}
glfwSetKeyCallback(gpWindowHandle, keyCallback);
return WINDOW_ERROR_NO_ERROR;
}
uint16_t windowLoop()
{
while (!glfwWindowShouldClose(gpWindowHandle)) {
glfwPollEvents();
}
return WINDOW_ERROR_NO_ERROR;
}
void windowTerminate()
{
glfwDestroyWindow(gpWindowHandle);
glfwTerminate();
}
GLFWwindow* getWindowHandle()
{
return gpWindowHandle;
}