Refactor project

Crealned up some TODOs, FIXMEs etc. Added better error handling. Looks
better, feels better.
This commit is contained in:
Piotr Krygier committed 2023-10-10 10:46:12 +02:00
1 parent bd4dd74881
commit 42dc4d6fcd
29 files changed
+750 -645

No files matched your search

+21 -2
View File
@@ -3,9 +3,28 @@
#include <stdint.h> #include <stdint.h>
void rse_graphics_init(void); #include "utilities/rse_commons.h"
uint8_t rse_graphics_run(void);
/**
* @brief Initializes graphics backend. This has to be called before any new mesh, texture or any other object is
* added
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success
*/
rse_err_t rse_graphics_init(void);
/**
* @brief Runs graphics engine. This has to be called after all objects are added to the scene
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success
*/
rse_err_t rse_graphics_run(void);
/**
* @brief Custom function for testing engine. Remove it whe releasing
*
*/
void rse_graphics_test_function(void); void rse_graphics_test_function(void);
#endif /* RSE_GRAPHICS_H */ #endif /* RSE_GRAPHICS_H */
+26 -5
View File
@@ -14,14 +14,16 @@
#include "utilities/localization.h" #include "utilities/localization.h"
#define vulkan_error_messages vulkan_error_messages_nolocale[SELECTED_LANGUAGE] #define vulkan_messages vulkan_messages_nolocale[SELECTED_LANGUAGE]
enum vulkan_errors_t { enum vulkan_messages_t {
VULKAN_DEBUG_MESSENGER_SETUP_FAILED,
VULKAN_LAYER_NOT_SUPPORTED, VULKAN_LAYER_NOT_SUPPORTED,
VULKAN_EXTENSION_NOT_SUPPORTED, VULKAN_EXTENSION_NOT_SUPPORTED,
VULKAN_INTANCE_INIT_FAILED, VULKAN_INTANCE_INIT_FAILED,
VULKAN_NO_PHYSICAL_DEVICES, VULKAN_NO_PHYSICAL_DEVICES,
VULKAN_NO_SUITABLE_PHYSICAL_DEVICES, VULKAN_NO_SUITABLE_PHYSICAL_DEVICES,
VULKAN_BINDLESS_DESIGN_NOT_SUPPORTED,
VULKAN_QUEUE_NOT_SUPPORTED, VULKAN_QUEUE_NOT_SUPPORTED,
VULKAN_FAILED_TO_CREATE_DEVICE, VULKAN_FAILED_TO_CREATE_DEVICE,
VULKAN_ALLOCATOR_CREATION_FAILED, VULKAN_ALLOCATOR_CREATION_FAILED,
@@ -31,6 +33,7 @@ enum vulkan_errors_t {
VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED, VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED,
VULKAN_SURFACE_CREATION_FAILED, VULKAN_SURFACE_CREATION_FAILED,
VULKAN_SWAPCHAIN_CREATION_FAILED, VULKAN_SWAPCHAIN_CREATION_FAILED,
VULKAN_ACQUIRE_SWAPCHAIN_FAILED,
VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED, VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED,
VULKAN_SHADER_UNABLE_TO_OPEN, VULKAN_SHADER_UNABLE_TO_OPEN,
VULKAN_SHADER_UNABLE_TO_CREATE_SHADER, VULKAN_SHADER_UNABLE_TO_CREATE_SHADER,
@@ -47,11 +50,17 @@ enum vulkan_errors_t {
VULKAN_MESH_NO_FREE, VULKAN_MESH_NO_FREE,
VULKAN_MESH_INSTANCE_NO_FREE, VULKAN_MESH_INSTANCE_NO_FREE,
VULAKN_DRAW_FAILED, VULAKN_DRAW_FAILED,
LAST_MESSAGE VULKAN_FORMAT_NOT_FOUND,
VULKAN_IMAGE_NOT_CREATED,
VULKAN_IMAGE_VIEW_NOT_CREATED,
VULKAN_MAX_TEXTURE_COUNT_REACHED,
VULKAN_LAST_MESSAGE
}; };
static const char vulkan_error_messages_nolocale[LAST_LANGUAGE][LAST_MESSAGE][MAX_MESSAGE_LENGHT] = { static const char vulkan_messages_nolocale[LAST_LANGUAGE][VULKAN_LAST_MESSAGE][MAX_MESSAGE_LENGHT] = {
{/* EN_US */ {/* EN_US */
/* VULKAN_DEBUG_MESSENGER_SETUP_FAILED*/
"Failed to setup debug messenger\n",
/* VULKAN_LAYER_NOT_SUPPORTED */ /* VULKAN_LAYER_NOT_SUPPORTED */
"Selected layer is not supported: %s\n", "Selected layer is not supported: %s\n",
/* VULKAN_EXTENSION_NOT_SUPPORTED */ /* VULKAN_EXTENSION_NOT_SUPPORTED */
@@ -62,6 +71,8 @@ static const char vulkan_error_messages_nolocale[LAST_LANGUAGE][LAST_MESSAGE][MA
"No physical graphical physical devices found in system\n", "No physical graphical physical devices found in system\n",
/* VULKAN_NO_SUITABLE_PHYSICAL_DEVICES */ /* VULKAN_NO_SUITABLE_PHYSICAL_DEVICES */
"No suitable physical device found\n", "No suitable physical device found\n",
/* VULKAN_BINDLESS_DESIGN_NOT_SUPPORTED */
"Required features for bindless design not supported\n",
/* VULKAN_QUEUE_NOT_SUPPORTED */ /* VULKAN_QUEUE_NOT_SUPPORTED */
"Selected physical device does not support required queue capabilities\n", "Selected physical device does not support required queue capabilities\n",
/* VULKAN_FAILED_TO_CREATE_DEVICE */ /* VULKAN_FAILED_TO_CREATE_DEVICE */
@@ -80,6 +91,8 @@ static const char vulkan_error_messages_nolocale[LAST_LANGUAGE][LAST_MESSAGE][MA
"Failed to create window surface\n", "Failed to create window surface\n",
/* VULKAN_SWAPCHAIN_CREATION_FAILED */ /* VULKAN_SWAPCHAIN_CREATION_FAILED */
"Failed to create swapchain\n", "Failed to create swapchain\n",
/* VULKAN_ACQUIRE_SWAPCHAIN_FAILED */
"Failed to acquire swapchain image\n",
/* VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED */ /* VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED */
"Failed to create swapchain image view\n", "Failed to create swapchain image view\n",
/* VULKAN_SHADER_UNABLE_TO_OPEN */ /* VULKAN_SHADER_UNABLE_TO_OPEN */
@@ -111,7 +124,15 @@ static const char vulkan_error_messages_nolocale[LAST_LANGUAGE][LAST_MESSAGE][MA
/* VULKAN_MESH_INSTANCE_NO_FREE */ /* VULKAN_MESH_INSTANCE_NO_FREE */
"Could not allocate new mesh instance\n", "Could not allocate new mesh instance\n",
/* VULAKN_DRAW_FAILED */ /* VULAKN_DRAW_FAILED */
"Failed to submit draw command buffer!", "Failed to submit draw command buffer!\n",
/* VULKAN_ERROR_FORMAT_NOT_FOUND */
"Failed to find correct format\n",
/* VULKAN_IMAGE_NOT_CREATED */
"Failed to create image\n",
/* VULKAN_IMAGE_VIEW_NOT_CREATED */
"Failed to create image view\n",
/* VULKAN_MAX_TEXTURE_COUNT_REACHED */
"Failed to find free texture image handle\n",
} }
}; };
+3 -3
View File
@@ -16,15 +16,15 @@
#define window_error_messages window_error_messages_nolocale[SELECTED_LANGUAGE] #define window_error_messages window_error_messages_nolocale[SELECTED_LANGUAGE]
enum Errors enum window_messages_t
{ {
WINDOW_GLFW_INIT_FAILED, WINDOW_GLFW_INIT_FAILED,
WINDOW_VULKAN_NOT_SUPPORTED, WINDOW_VULKAN_NOT_SUPPORTED,
WINDOW_NOT_CREATED, WINDOW_NOT_CREATED,
LAST_MESSAGE WINDOW_LAST_MESSAGE
}; };
static const char window_error_messages_nolocale[LAST_LANGUAGE][LAST_MESSAGE][MAX_MESSAGE_LENGHT] = { static const char window_error_messages_nolocale[LAST_LANGUAGE][WINDOW_LAST_MESSAGE][MAX_MESSAGE_LENGHT] = {
{/* EN_US */ {/* EN_US */
/* WINDOW_GLFW_INIT_FAILED */ /* WINDOW_GLFW_INIT_FAILED */
"GLFW init failed!\n", "GLFW init failed!\n",
+8 -6
View File
@@ -1,6 +1,8 @@
#include "mesh_controller.h" #include "mesh_controller.h"
#include "vulkan_buffers.h" #include "vulkan_buffers.h"
#include "vulkan_errors.h"
#include "utilities/rse_errors_common.h"
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "utilities/logger.h" #include "utilities/logger.h"
@@ -53,13 +55,12 @@ uint16_t create_mesh(struct rse_vertex_t* vertices,
} }
if(iter >= MAX_MESH_NUMBER) { if(iter >= MAX_MESH_NUMBER) {
LOGE(vulkan_error_messages[VULKAN_MESH_NO_FREE]); LOGE(vulkan_messages[VULKAN_MESH_NO_FREE]);
/* TODO: Add error handling */ /* TODO: Add error handling */
return MAX_MESH_NUMBER; return MAX_MESH_NUMBER;
} }
g_meshes[iter].is_mesh_id_taken = MESH_ID_TAKEN; g_meshes[iter].is_mesh_id_taken = MESH_ID_TAKEN;
g_meshes[iter].unique_id = iter; g_meshes[iter].unique_id = iter;
g_meshes[iter].vertex_data.count = vertices_count; g_meshes[iter].vertex_data.count = vertices_count;
g_meshes[iter].index_data.count = indices_count; g_meshes[iter].index_data.count = indices_count;
@@ -71,7 +72,7 @@ uint16_t create_mesh(struct rse_vertex_t* vertices,
return iter; return iter;
} }
void create_mesh_instance(uint16_t mesh_id, rse_err_t create_mesh_instance(uint16_t mesh_id,
struct rse_instance_data_t instance_data) struct rse_instance_data_t instance_data)
{ {
size_t iter = 0U; size_t iter = 0U;
@@ -83,9 +84,8 @@ void create_mesh_instance(uint16_t mesh_id,
} }
if(iter >= MAX_INSTANCE_NUMBER) { if(iter >= MAX_INSTANCE_NUMBER) {
LOGE(vulkan_error_messages[VULKAN_MESH_NO_FREE]); LOGE(vulkan_messages[VULKAN_MESH_NO_FREE]);
/* TODO: Add error handling */ return VULKAN_ERROR_MAX_INSTANCE_COUNT_REACHED;
return;
} }
g_meshes[mesh_id].instance_data[iter].instance_taken = MESH_ID_TAKEN; g_meshes[mesh_id].instance_data[iter].instance_taken = MESH_ID_TAKEN;
@@ -95,6 +95,8 @@ void create_mesh_instance(uint16_t mesh_id,
} }
update_mesh_instances(mesh_id, &instance_data); update_mesh_instances(mesh_id, &instance_data);
return RSE_ERROR_NO_ERROR;
} }
size_t get_vertices_count(uint16_t mesh_id) size_t get_vertices_count(uint16_t mesh_id)
+8 -5
View File
@@ -13,6 +13,7 @@
#define RSE_MESH_CONTROLLER_H #define RSE_MESH_CONTROLLER_H
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "utilities/rse_commons.h"
/** /**
* @brief Create a new mesh for provided vertices and indices. * @brief Create a new mesh for provided vertices and indices.
@@ -33,7 +34,7 @@ uint16_t create_mesh(struct rse_vertex_t* vertices,
* @param mesh_id Mesh id * @param mesh_id Mesh id
* @param instance_data Transformation info * @param instance_data Transformation info
*/ */
void create_mesh_instance(uint16_t mesh_id, rse_err_t create_mesh_instance(uint16_t mesh_id,
struct rse_instance_data_t instance_data); struct rse_instance_data_t instance_data);
/** /**
@@ -60,10 +61,12 @@ size_t get_indices_count(uint16_t mesh_id);
*/ */
size_t get_instances_count(uint16_t mesh_id); size_t get_instances_count(uint16_t mesh_id);
/**
* @brief Get vertex offset in vertex buffer for selected mesh
*
* @param mesh_id Mesh identifies
* @return size_t Offset
*/
size_t get_vertex_offset(uint16_t mesh_id); size_t get_vertex_offset(uint16_t mesh_id);
VkDrawIndexedIndirectCommand get_indices_data_buffer(uint16_t mesh_id);
#endif /* RSE_MESH_CONTROLLER_H */ #endif /* RSE_MESH_CONTROLLER_H */
+20 -12
View File
@@ -5,13 +5,17 @@
#include "mesh_controller.h" #include "mesh_controller.h"
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "rse_vulkan_image.h" #include "rse_vulkan_image.h"
#include "utilities/logger.h"
#include "utilities/rse_commons.h"
#include "utilities/rse_errors_common.h"
#include "rse_math.h" #include "rse_math.h"
extern struct rse_vulkan_state_t g_vulkan_state; extern struct rse_vulkan_state_t g_vulkan_state;
void rse_graphics_init(void) rse_err_t rse_graphics_init(void)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
g_vulkan_state.graphics_queue = VK_NULL_HANDLE; g_vulkan_state.graphics_queue = VK_NULL_HANDLE;
g_vulkan_state.physical_device = VK_NULL_HANDLE; g_vulkan_state.physical_device = VK_NULL_HANDLE;
g_vulkan_state.current_frame = 0U; g_vulkan_state.current_frame = 0U;
@@ -21,17 +25,22 @@ void rse_graphics_init(void)
g_vulkan_state.pipeline_layout = VK_NULL_HANDLE; g_vulkan_state.pipeline_layout = VK_NULL_HANDLE;
g_vulkan_state.swapchain = VK_NULL_HANDLE; g_vulkan_state.swapchain = VK_NULL_HANDLE;
window_init(); STATUS_CHECK(window_init());
STATUS_CHECK(preinit_vulkan());
if (0 != preinit_vulkan()) return status;
return;
} }
void rse_graphics_test_function(void) void rse_graphics_test_function(void)
{ {
int8_t tex_id_2 = 0; rse_err_t status = RSE_ERROR_NO_ERROR;
uint8_t tex_id_2 = 0;
tex_id_2 = rse_load_texture("../../test_image.png"); status = rse_load_texture("../../test_image.png", &tex_id_2);
if (status != RSE_ERROR_NO_ERROR) {
LOGE("Failed to do something. Check error messages");
return;
}
// FIXME: Temporary array of vertices, for testing purposes // FIXME: Temporary array of vertices, for testing purposes
struct rse_vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, struct rse_vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
@@ -71,17 +80,16 @@ void rse_graphics_test_function(void)
}); });
} }
uint8_t rse_graphics_run(void) rse_err_t rse_graphics_run(void)
{ {
if (0 != init_vulkan()) { rse_err_t status = RSE_ERROR_NO_ERROR;
return -1; STATUS_CHECK(init_vulkan());
}
window_loop(); STATUS_CHECK(window_loop());
deinit_vulkan(); deinit_vulkan();
window_terminate(); window_terminate();
return 0; return status;
} }
-21
View File
@@ -29,27 +29,6 @@ static float scalar_cross_vec3(const struct vec3_t* vec1, const struct vec3_t* v
+(vec1->z * vec2->z); +(vec1->z * vec2->z);
} }
// static struct mat4_t mat4_times_vector3_t(const struct mat4_t* mat, const struct vec3_t* vec)
// {
// /* We can't do that, mathematically speaking, but we can just assume that the 4th
// * element of vector is just 1. */
// struct mat4_t result = rse_math_uniform_mat4();
// result.x_1 = mat->x_1 * vec->x;
// result.x_2 = mat->x_2 * vec->y;
// result.x_3 = mat->x_3 * vec->z;
// result.y_1 = mat->y_1 * vec->x;
// result.y_2 = mat->y_2 * vec->y;
// result.y_3 = mat->y_3 * vec->z;
// result.z_1 = mat->z_1 * vec->x;
// result.z_2 = mat->z_2 * vec->y;
// result.z_3 = mat->z_3 * vec->z;
// return result;
// }
float rse_math_deg_to_radians(float degrees) float rse_math_deg_to_radians(float degrees)
{ {
return degrees * (PI/180.0f); return degrees * (PI/180.0f);
-7
View File
@@ -12,10 +12,6 @@
#ifndef RSE_MATH_H #ifndef RSE_MATH_H
#define RSE_MATH_H #define RSE_MATH_H
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* @brief Simple representation of vector * @brief Simple representation of vector
* *
@@ -122,8 +118,5 @@ struct mat4_t rse_math_perspective(float fovy_rad, float aspect_ratio, float z_n
* @return struct mat4_t resulting matrix * @return struct mat4_t resulting matrix
*/ */
struct mat4_t rse_math_rotate(struct mat4_t matrix, float radians, struct vec3_t rotation_vector); struct mat4_t rse_math_rotate(struct mat4_t matrix, float radians, struct vec3_t rotation_vector);
#ifdef __cplusplus
}
#endif
#endif /* RSE_MATH_H */ #endif /* RSE_MATH_H */
+13 -12
View File
@@ -3,39 +3,40 @@
#include "vulkan_errors.h" #include "vulkan_errors.h"
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "utilities/rse_errors_common.h"
VkCommandPool g_command_pool = VK_NULL_HANDLE; VkCommandPool g_command_pool = VK_NULL_HANDLE;
/** /**
* @brief Create Command Pools * @brief Create Command Pools
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED * VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED
*/ */
static uint8_t create_command_pools() static rse_err_t create_command_pools()
{ {
VkCommandPoolCreateInfo create_info; VkCommandPoolCreateInfo create_info;
create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
create_info.pNext = NULL; create_info.pNext = NULL;
create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; create_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
create_info.queueFamilyIndex = g_vulkan_state.queue_family_indices[0]; /* TODO: Change when more families are needed */ create_info.queueFamilyIndex = g_vulkan_state.queue_family_indices[0];
if (VK_SUCCESS != vkCreateCommandPool(g_vulkan_state.device, &create_info, NULL, &g_command_pool)) { if (VK_SUCCESS != vkCreateCommandPool(g_vulkan_state.device, &create_info, NULL, &g_command_pool)) {
LOGF(vulkan_error_messages[VULKAN_COMMAND_POOL_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_COMMAND_POOL_CREATION_FAILED]);
return VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED; return VULKAN_ERROR_COMMAND_POOL_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Allocate Command Buffers * @brief Allocate Command Buffers
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED * VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED
*/ */
static uint8_t allocate_command_buffers() static rse_err_t allocate_command_buffers()
{ {
VkCommandBufferAllocateInfo allocate_info; VkCommandBufferAllocateInfo allocate_info;
@@ -43,16 +44,16 @@ static uint8_t allocate_command_buffers()
allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocate_info.pNext = NULL; allocate_info.pNext = NULL;
allocate_info.commandPool = g_command_pool; allocate_info.commandPool = g_command_pool;
allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; /* TODO: When needed, add secondary command buffer */ allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocate_info.commandBufferCount = SWAP_BUFFER_COUNT; allocate_info.commandBufferCount = SWAP_BUFFER_COUNT;
if (VK_SUCCESS != vkAllocateCommandBuffers(g_vulkan_state.device, if (VK_SUCCESS != vkAllocateCommandBuffers(g_vulkan_state.device,
&allocate_info, &allocate_info,
g_vulkan_state.command_buffers)) { g_vulkan_state.command_buffers)) {
LOGF(vulkan_error_messages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED]); LOGF(vulkan_messages[VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED]);
return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED; return VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
VkCommandBuffer rse_begin_single_time_command() VkCommandBuffer rse_begin_single_time_command()
@@ -100,9 +101,9 @@ void rse_end_single_time_comands(VkCommandBuffer command_buffer)
vkFreeCommandBuffers(g_vulkan_state.device, g_command_pool, 1, &command_buffer); vkFreeCommandBuffers(g_vulkan_state.device, g_command_pool, 1, &command_buffer);
} }
uint8_t init_commands() rse_err_t init_commands()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_command_pools()); STATUS_CHECK(create_command_pools());
STATUS_CHECK(allocate_command_buffers()); STATUS_CHECK(allocate_command_buffers());
+23 -1
View File
@@ -14,11 +14,33 @@
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include "utilities/rse_commons.h"
uint8_t init_commands(); /**
* @brief Initialize vulkan commands pools and sets
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success
*/
rse_err_t init_commands();
/**
* @brief Destroy vulkan commands sets and pools
*
*/
void destroy_commands(); void destroy_commands();
/**
* @brief Helper function, creates command buffer for recording a command. Useful for copying buffer na images.
*
* @return VkCommandBuffer Created command buffer, ready to be filled with commands.
*/
VkCommandBuffer rse_begin_single_time_command(); VkCommandBuffer rse_begin_single_time_command();
/**
* @brief Close command buffer and execute recorded command.
*
* @param command_buffer Command buffer for execution
*/
void rse_end_single_time_comands(VkCommandBuffer command_buffer); void rse_end_single_time_comands(VkCommandBuffer command_buffer);
#endif /* RSE_VULKAN_COMMANDS_H */ #endif /* RSE_VULKAN_COMMANDS_H */
+63 -56
View File
@@ -2,6 +2,7 @@
#include "utilities/file_utils.h" #include "utilities/file_utils.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "utilities/rse_errors_common.h"
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "vulkan_errors.h" #include "vulkan_errors.h"
#include "rse_vulkan_commands.h" #include "rse_vulkan_commands.h"
@@ -42,7 +43,7 @@ struct rse_vulkan_image_t g_depth_image;
VkSampler g_sampler; VkSampler g_sampler;
static uint8_t create_sampler() static rse_err_t create_sampler()
{ {
VkSamplerCreateInfo create_info = {0}; VkSamplerCreateInfo create_info = {0};
@@ -73,17 +74,14 @@ static uint8_t create_sampler()
return 1; return 1;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
// static uint8_t has_stencil_component(VkFormat format) { static rse_err_t find_supported_format(const VkFormat* candidates,
// return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
// }
static VkFormat find_supported_format(const VkFormat* candidates,
size_t candidates_count, size_t candidates_count,
VkImageTiling tiling, VkImageTiling tiling,
VkFormatFeatureFlags features) VkFormatFeatureFlags features,
VkFormat* found_format)
{ {
size_t i = 0U; size_t i = 0U;
@@ -92,20 +90,21 @@ static VkFormat find_supported_format(const VkFormat* candidates,
vkGetPhysicalDeviceFormatProperties(g_vulkan_state.physical_device, candidates[i], &props); vkGetPhysicalDeviceFormatProperties(g_vulkan_state.physical_device, candidates[i], &props);
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
return candidates[i]; *found_format = candidates[i];
return RSE_ERROR_NO_ERROR;
} else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
return candidates[i]; *found_format = candidates[i];
return RSE_ERROR_NO_ERROR;
} }
} }
LOGE("Failed to find correct format"); LOGE(vulkan_messages[VULKAN_FORMAT_NOT_FOUND]);
//FIXME: Add error handling return VULKAN_ERROR_FORMAT_NOT_FOUND;
return 0;
} }
static uint8_t create_depth_resources() static rse_err_t create_depth_resources()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
VkFormat depth_format = {0}; VkFormat depth_format = {0};
VkExtent3D image_extent = {0}; VkExtent3D image_extent = {0};
VkImageCreateInfo image_info = {0}; VkImageCreateInfo image_info = {0};
@@ -114,7 +113,7 @@ static uint8_t create_depth_resources()
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities; VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
depth_format = find_depth_format(); STATUS_CHECK(find_depth_format(&depth_format));
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vulkan_state.physical_device, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vulkan_state.physical_device,
g_vulkan_state.surface, g_vulkan_state.surface,
&physical_device_surface_capabilities); &physical_device_surface_capabilities);
@@ -156,8 +155,8 @@ static uint8_t create_depth_resources()
&g_depth_image.image, &g_depth_image.image,
&g_depth_image.allocation, &g_depth_image.allocation,
&g_depth_image.allocation_info)) { &g_depth_image.allocation_info)) {
LOGF("Failed to create image"); LOGF(vulkan_messages[VULKAN_IMAGE_NOT_CREATED]);
return -1; return VULKAN_ERROR_IMAGE_NOT_CREATED;
} }
image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
@@ -180,19 +179,20 @@ static uint8_t create_depth_resources()
&image_view_create_info, &image_view_create_info,
NULL, NULL,
&g_depth_image.image_view)) { &g_depth_image.image_view)) {
LOGF(vulkan_error_messages[VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED]);
return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED; return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED;
} }
return status; return RSE_ERROR_NO_ERROR;
} }
static VkDeviceSize format_to_pixel_size(VkFormat format) static rse_err_t format_to_pixel_size(VkFormat format,
VkDeviceSize* format_size)
{ {
switch (format) switch (format)
{ {
case VK_FORMAT_R8G8B8A8_SRGB: case VK_FORMAT_R8G8B8A8_SRGB:
return 4; *format_size = 4;
break; break;
default: default:
@@ -200,12 +200,17 @@ static VkDeviceSize format_to_pixel_size(VkFormat format)
break; break;
} }
return 0; return RSE_ERROR_NO_ERROR;
} }
static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat format, unsigned char* pixels) static rse_err_t create_vulkan_image(uint32_t width,
uint32_t height,
VkFormat format,
unsigned char* pixels,
uint8_t* texture_id)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
struct rse_vulkan_buffer_t staging_buffer = {0}; struct rse_vulkan_buffer_t staging_buffer = {0};
VkDeviceSize staging_buffer_size = 0U; VkDeviceSize staging_buffer_size = 0U;
VkImageCreateInfo image_info = {0}; VkImageCreateInfo image_info = {0};
@@ -217,23 +222,26 @@ static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat form
VkExtent3D image_extent = {0}; VkExtent3D image_extent = {0};
VkImageViewCreateInfo image_view_create_info = {0}; VkImageViewCreateInfo image_view_create_info = {0};
struct rse_vulkan_image_t* free_texture_image = NULL; struct rse_vulkan_image_t* free_texture_image = NULL;
size_t i = 0U; *texture_id = 0U;
while(free_texture_image == NULL || i > RSE_MAX_IMAGE_COUNT) { while(free_texture_image == NULL || *texture_id > RSE_MAX_IMAGE_COUNT) {
if(g_texture_images[i].id_taken == IMAGE_FREE) { if(g_texture_images[*texture_id].id_taken == IMAGE_FREE) {
free_texture_image = &g_texture_images[i]; free_texture_image = &g_texture_images[*texture_id];
} else { } else {
++i; *texture_id += 1;
} }
} }
/* Check if we found free image handle */ /* Check if we found free image handle */
if (free_texture_image == NULL) { if (free_texture_image == NULL) {
LOGE("Failed to find free texture image handle"); LOGE(vulkan_messages[VULKAN_MAX_TEXTURE_COUNT_REACHED]);
return -1; *texture_id = -1;
return VULKAN_ERROR_MAX_TEXTURE_COUNT_REACHED;
} }
staging_buffer_size = width * height * format_to_pixel_size(format); STATUS_CHECK(format_to_pixel_size(format, &staging_buffer_size));
staging_buffer_size = staging_buffer_size * width * height;
image_extent.width = width; image_extent.width = width;
image_extent.height = height; image_extent.height = height;
@@ -270,8 +278,8 @@ static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat form
&free_texture_image->image, &free_texture_image->image,
&free_texture_image->allocation, &free_texture_image->allocation,
&free_texture_image->allocation_info)) { &free_texture_image->allocation_info)) {
LOGF("Failed to create image"); LOGF(vulkan_messages[VULKAN_IMAGE_NOT_CREATED]);
return -1; return VULKAN_ERROR_IMAGE_NOT_CREATED;
} }
/* Put image into correct layout to copy pixels from buffer to image memory */ /* Put image into correct layout to copy pixels from buffer to image memory */
@@ -306,15 +314,12 @@ static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat form
rse_end_single_time_comands(command_buffer); rse_end_single_time_comands(command_buffer);
/* Copy pixel data to GPU memory */ /* Copy pixel data to GPU memory */
if (VK_SUCCESS != create_buffer(staging_buffer_size, STATUS_CHECK(create_buffer(staging_buffer_size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_HOST, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
VMA_ALLOCATION_CREATE_MAPPED_BIT VMA_ALLOCATION_CREATE_MAPPED_BIT
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
&staging_buffer)) { &staging_buffer));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return -1;
}
memcpy(staging_buffer.allocation_info.pMappedData, pixels, staging_buffer_size); memcpy(staging_buffer.allocation_info.pMappedData, pixels, staging_buffer_size);
@@ -376,17 +381,17 @@ static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat form
&image_view_create_info, &image_view_create_info,
NULL, NULL,
&free_texture_image->image_view)) { &free_texture_image->image_view)) {
LOGF("Failed to create image view"); LOGF(vulkan_messages[VULKAN_IMAGE_VIEW_NOT_CREATED]);
return -1; return VULKAN_ERROR_IMAGE_VIEW_NOT_CREATED;
} }
free_texture_image->id_taken = IMAGE_TAKEN; free_texture_image->id_taken = IMAGE_TAKEN;
return i; return RSE_ERROR_NO_ERROR;
} }
uint8_t init_vulkan_images() rse_err_t init_vulkan_images()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_sampler()); STATUS_CHECK(create_sampler());
STATUS_CHECK(create_depth_resources()); STATUS_CHECK(create_depth_resources());
@@ -394,16 +399,14 @@ uint8_t init_vulkan_images()
return status; return status;
} }
int8_t rse_load_texture(const char* file_path) rse_err_t rse_load_texture(const char* file_path, uint8_t* texture_id)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
int width = 0; int width = 0;
int height = 0; int height = 0;
int channels = 0; int channels = 0;
stbi_uc* pixel_buffer = NULL; stbi_uc* pixel_buffer = NULL;
int8_t ret;
pixel_buffer = stbi_load(file_path, &width, &height, &channels, STBI_rgb_alpha); pixel_buffer = stbi_load(file_path, &width, &height, &channels, STBI_rgb_alpha);
if (pixel_buffer == NULL) { if (pixel_buffer == NULL) {
@@ -412,14 +415,14 @@ int8_t rse_load_texture(const char* file_path)
} }
/* Create actual Vulkan Image */ /* Create actual Vulkan Image */
ret = create_vulkan_image(width, status = create_vulkan_image(width,
height, height,
VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R8G8B8A8_SRGB,
pixel_buffer); pixel_buffer, texture_id);
stbi_image_free(pixel_buffer); stbi_image_free(pixel_buffer);
return ret; return status;
} }
@@ -440,7 +443,7 @@ void rse_destroy_textures()
vmaDestroyImage(g_vulkan_state.allocator, g_depth_image.image, g_depth_image.allocation); vmaDestroyImage(g_vulkan_state.allocator, g_depth_image.image, g_depth_image.allocation);
} }
int8_t image_exists(uint8_t image_id) { uint8_t image_exists(uint8_t image_id) {
return g_texture_images[image_id].id_taken == IMAGE_TAKEN; return g_texture_images[image_id].id_taken == IMAGE_TAKEN;
} }
@@ -474,16 +477,20 @@ size_t get_textures_count()
return count; return count;
} }
VkFormat find_depth_format() rse_err_t find_depth_format(VkFormat* found_format)
{ {
#define formats_count 3 #define formats_count 3
rse_err_t status;
VkFormat formats[formats_count] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}; VkFormat formats[formats_count] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
return find_supported_format( STATUS_CHECK(find_supported_format(
formats, formats,
formats_count, formats_count,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TILING_OPTIMAL,
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT,
); found_format
));
return status;
#undef formats_count #undef formats_count
} }
+10 -8
View File
@@ -14,6 +14,7 @@
#define RSE_TEXTURE_H #define RSE_TEXTURE_H
#include "utilities/file_utils.h" #include "utilities/file_utils.h"
#include "utilities/rse_commons.h"
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include <stdint.h> #include <stdint.h>
@@ -27,17 +28,18 @@
/** /**
* @brief Initialize vulkan with image views and stuff * @brief Initialize vulkan with image views and stuff
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
uint8_t init_vulkan_images(void); rse_err_t init_vulkan_images(void);
/** /**
* @brief Loads image from file, for later to be uysed as a texture * @brief Loads image from file, for later to be uysed as a texture
* *
* @param path Path to texture file * @param file_path Path to texture file
* @return int8_t -1 on error. Texture ID on success * @param texture_id Texture ID will be set up here
* @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
int8_t rse_load_texture(const char* path); rse_err_t rse_load_texture(const char* file_path, uint8_t* texture_id);
/** /**
* @brief Destroy all loaded textures. Usefull for closing application or just clearing. * @brief Destroy all loaded textures. Usefull for closing application or just clearing.
@@ -64,9 +66,9 @@ VkSampler rse_get_texture_sampler();
* @brief Checks if image exists for provided image ID. * @brief Checks if image exists for provided image ID.
* *
* @param image_id Image ID * @param image_id Image ID
* @return int8_t 1 on success, 0 on failure * @return uint8_t 1 on success, 0 on failure
*/ */
int8_t image_exists(uint8_t image_id); uint8_t image_exists(uint8_t image_id);
/** /**
* @brief Returns number of loaded texture * @brief Returns number of loaded texture
@@ -75,7 +77,7 @@ int8_t image_exists(uint8_t image_id);
*/ */
size_t get_textures_count(); size_t get_textures_count();
VkFormat find_depth_format(); rse_err_t find_depth_format(VkFormat* found_format);
VkImageView rse_get_depth_image_view(); VkImageView rse_get_depth_image_view();
+24
View File
@@ -0,0 +1,24 @@
/**
* @file window_errors.h
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief
* @version 0.1
* @date 2023-10-06
*
* @copyright Copyright (c) 2023
*
*/
#ifndef RSE_WINDOW_ERRORS_H
#define RSE_WINDOW_ERRORS_H
#define RSE_WINDOW_MODULE_ID 0x0200U
/* Error codes */
enum rse_window_error_t {
WINDOW_ERROR_GLFW_INIT_FAILED = RSE_WINDOW_MODULE_ID,
WINDOW_ERROR_VULKAN_NOT_LOADED,
WINDOW_ERROR_WINDOW_NOT_CREATED
};
#endif /* RSE_WINDOW_ERRORS_H */
+4 -1
View File
@@ -1,7 +1,10 @@
#version 450 #version 450
/* Each time texture count is changed this value also need to change. I have to fix it somehow. */ /* Each time texture count is changed this value also need to change. I have to fix it somehow. */
layout(binding = 1) uniform sampler2D texSampler[1];
#extension GL_EXT_nonuniform_qualifier : enable
layout(set = 1, binding = 1) uniform sampler2D texSampler[];
layout(location = 0) in vec3 fragColor; layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord; layout(location = 1) in vec2 fragTexCoord;
+149 -152
View File
@@ -11,23 +11,26 @@
#include "vulkan_base.h" #include "vulkan_base.h"
#include "vulkan_errors.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#pragma GCC diagnostic push /* We are building with -Werror flag on, but there are some warning in VMA implementation. Thus diagnostic push */
#pragma GCC diagnostic ignored "-Wunused-function" // #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable" // #pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wpedantic" // #pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wignored-qualifiers" // #pragma GCC diagnostic ignored "-Wpedantic"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers" // #pragma GCC diagnostic ignored "-Wignored-qualifiers"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" // #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wswitch" // #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wparentheses" // #pragma GCC diagnostic ignored "-Wswitch"
// #pragma GCC diagnostic ignored "-Wparentheses"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#pragma GCC diagnostic pop // #pragma GCC diagnostic pop
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "utilities/locale_common.h"
#include "utilities/rse_errors_common.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "vulkan_errors.h"
#include "window.h" #include "window.h"
#include "vulkan_commons.h" #include "vulkan_commons.h"
@@ -73,60 +76,7 @@ VkSemaphore g_render_finished_semaphores[SWAP_BUFFER_COUNT] = {};
VkFence g_in_flight_fences[SWAP_BUFFER_COUNT] = {}; VkFence g_in_flight_fences[SWAP_BUFFER_COUNT] = {};
#ifndef NDEBUG #ifndef NDEBUG
static void setup_debug_messenger();
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageTypeFlagsEXT message_type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
void* user_data);
static VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator,
VkDebugUtilsMessengerEXT* debug_messenger);
static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger,
const VkAllocationCallbacks* allocator);
#endif
static void set_enabled_extension();
static uint8_t create_instance();
static uint8_t create_surface();
static uint8_t pick_physical_device();
static uint8_t create_device();
static uint8_t create_memory_allocator();
static uint8_t create_sync_objects();
#ifndef NDEBUG
/**
* @brief Setup debugging system for Vulkan API
*
*/
void setup_debug_messenger()
{
VkDebugUtilsMessengerCreateInfoEXT create_info;
create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
create_info.pNext = NULL;
create_info.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;
create_info.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;
create_info.pfnUserCallback = debug_callback;
create_info.pUserData = NULL; // Optional
create_info.flags = 0U;
if (CreateDebugUtilsMessengerEXT(g_vulkan_instance, &create_info, NULL, &g_debug_messenger) != VK_SUCCESS) {
fprintf(stderr, "failed to set up debug messenger!");
}
}
/** /**
* @brief Calback for debug messenger * @brief Calback for debug messenger
@@ -137,15 +87,29 @@ void setup_debug_messenger()
* @param user_data Data provided by the user * @param user_data Data provided by the user
* @return VkBool32 Should always return VK_FALSE. The VK_TRUE value is reserved for use in layer development * @return VkBool32 Should always return VK_FALSE. The VK_TRUE value is reserved for use in layer development
*/ */
VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageTypeFlagsEXT message_type, VkDebugUtilsMessageTypeFlagsEXT message_type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data)
{ {
enum log_level_t log_level = LOGLEVEL_TRACE;
(void)message_severity; (void)message_severity;
(void)message_type; (void)message_type;
(void)user_data; (void)user_data;
LOGD(callback_data->pMessage); /* There is no guarantee, that the error message will have single severity flag set, so we can't use switch()
* here. We have to check flags and set severity to most important one */
if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
log_level = LOGLEVEL_ERROR;
} else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
log_level = LOGLEVEL_WARNING;
} else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
log_level = LOGLEVEL_INFO;
} else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
log_level = LOGLEVEL_TRACE;
}
LOGGER(log_level, callback_data->pMessage);
return VK_FALSE; return VK_FALSE;
} }
@@ -159,7 +123,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBit
* @param debug_messenger Debug messanger handle * @param debug_messenger Debug messanger handle
* @return VkResult VK_SUCCESS on success * @return VkResult VK_SUCCESS on success
*/ */
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info, static VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info,
const VkAllocationCallbacks* allocator, const VkAllocationCallbacks* allocator,
VkDebugUtilsMessengerEXT* debug_messenger) VkDebugUtilsMessengerEXT* debug_messenger)
{ {
@@ -175,6 +139,34 @@ VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMes
return VK_SUCCESS; return VK_SUCCESS;
} }
/**
* @brief Setup debugging system for Vulkan API
*
*/
static rse_err_t setup_debug_messenger()
{
VkDebugUtilsMessengerCreateInfoEXT create_info = {0};
create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
create_info.pNext = NULL;
create_info.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;
create_info.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;
create_info.pfnUserCallback = debug_callback;
create_info.pUserData = NULL; // Optional
create_info.flags = 0U;
if (CreateDebugUtilsMessengerEXT(g_vulkan_instance, &create_info, NULL, &g_debug_messenger) != VK_SUCCESS) {
LOGF(vulkan_messages[VULKAN_DEBUG_MESSENGER_SETUP_FAILED]);
return VULKAN_ERROR_DEBUG_MESSENGER_CREATION_FAILED;
}
return RSE_ERROR_NO_ERROR;
}
/** /**
* @brief Proxy for vkDestroyDebugUtilsMessengerEXT * @brief Proxy for vkDestroyDebugUtilsMessengerEXT
* *
@@ -182,7 +174,7 @@ VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMes
* @param debug_messenger Debug messanger handle * @param debug_messenger Debug messanger handle
* @param allocator Memory allocator * @param allocator Memory allocator
*/ */
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger, static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger,
const VkAllocationCallbacks* allocator) const VkAllocationCallbacks* allocator)
{ {
PFN_vkDestroyDebugUtilsMessengerEXT func = PFN_vkDestroyDebugUtilsMessengerEXT func =
@@ -192,13 +184,13 @@ void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT
} }
} }
#endif #endif /* DEBUG */
/** /**
* @brief Enable instance extensions, based on system and requirements * @brief Enable instance extensions, based on system and requirements
* *
*/ */
void set_enabled_extension() static void set_enabled_extension()
{ {
g_enabled_instance_extensions_names[0] = "VK_KHR_surface"; g_enabled_instance_extensions_names[0] = "VK_KHR_surface";
g_enabled_instance_extensions_names[1] = "VK_KHR_device_group_creation"; g_enabled_instance_extensions_names[1] = "VK_KHR_device_group_creation";
@@ -210,49 +202,54 @@ void set_enabled_extension()
g_enabled_instance_extensions_names[2] = "VK_KHR_xcb_surface"; g_enabled_instance_extensions_names[2] = "VK_KHR_xcb_surface";
} }
#elif defined(_WIN32) || defined(WIN32) #elif defined(_WIN32) || defined(WIN32)
g_enabled_instance_extensions_names.push_back("VK_KHR_win32_surface"); g_enabled_instance_extensions_names[2] = "VK_KHR_win32_surface";
#endif #endif
/* Add custom extensions here and make VK_EXT_debug_utils last */
/* ----------------------------------------------------------- */
#ifndef NDEBUG #ifndef NDEBUG
g_enabled_instance_extensions_names[3] = "VK_EXT_debug_utils"; g_enabled_instance_extensions_names[3] = "VK_EXT_debug_utils";
#endif #endif
}; };
/** /**
* @brief Create the Vulkan Instance object * @brief Create the Vulkan Instance object
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_INSTANCE_INIT_FAILED * VULKAN_ERROR_INSTANCE_INIT_FAILED
*/ */
uint8_t create_instance() static rse_err_t create_instance()
{ {
size_t i; size_t i = 0U;
size_t j; size_t j = 0U;
uint8_t supported = 0; uint8_t supported = 0U;
uint32_t extensionCount = 0; uint32_t extensionCount = 0U;
uint32_t layersCount = 0; uint32_t layersCount = 0U;
VkApplicationInfo application_info = {}; VkApplicationInfo application_info = {0};
VkInstanceCreateInfo create_info = {}; VkInstanceCreateInfo create_info = {0};
VkLayerProperties* layer_properties; VkLayerProperties* layer_properties;
VkExtensionProperties* extensions_properties; VkExtensionProperties* extensions_properties;
vkEnumerateInstanceLayerProperties(&layersCount, NULL); vkEnumerateInstanceLayerProperties(&layersCount, NULL);
layer_properties = malloc(sizeof(VkLayerProperties) * layersCount); rse_malloc(layer_properties, sizeof(VkLayerProperties) * layersCount);
vkEnumerateInstanceLayerProperties(&layersCount, layer_properties); vkEnumerateInstanceLayerProperties(&layersCount, layer_properties);
vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL); vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
extensions_properties = malloc(sizeof(VkExtensionProperties) * extensionCount); rse_malloc(extensions_properties, sizeof(VkExtensionProperties) * extensionCount);
vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensions_properties); vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensions_properties);
#ifndef NDEBUG #ifndef NDEBUG
LOGD("Supported Layers"); LOGD("Supported Layers: \n");
for (i = 0; i < layersCount; i++) { for (i = 0; i < layersCount; i++) {
LOGD("%s", layer_properties[i].layerName); LOGD("\t-%s\n", layer_properties[i].layerName);
} }
LOGD("Supported Extensions"); LOGD("Supported Extensions: \n");
for (size_t i = 0; i < extensionCount; i++) { for (size_t i = 0; i < extensionCount; i++) {
LOGD("%s", extensions_properties[i].extensionName); LOGD("\t-%s\n", extensions_properties[i].extensionName);
} }
#endif #endif
@@ -264,14 +261,13 @@ uint8_t create_instance()
break; break;
} }
} }
if(supported == 0) {
LOGF(vulkan_messages[VULKAN_LAYER_NOT_SUPPORTED], layer_properties[j].layerName);
return VULKAN_ERROR_LAYER_NOT_SUPPORTED;
}
supported = 0;
} }
if(supported == 0) {
LOGF(vulkan_error_messages[VULKAN_LAYER_NOT_SUPPORTED], layer_properties[j].layerName);
return VULKAN_ERROR_LAYER_NOT_SUPPORTED;
}
supported = 0;
/* Check if selected extensions are supported*/ /* Check if selected extensions are supported*/
for (i = 0; i < ENABLED_EXTENSIONS_COUT; ++i) { for (i = 0; i < ENABLED_EXTENSIONS_COUT; ++i) {
for(j = 0; j < extensionCount; ++j) { for(j = 0; j < extensionCount; ++j) {
@@ -280,10 +276,11 @@ uint8_t create_instance()
break; break;
} }
} }
} if(supported == 0) {
if(supported == 0) { LOGF(vulkan_messages[VULKAN_EXTENSION_NOT_SUPPORTED], extensions_properties[j].extensionName);
LOGF(vulkan_error_messages[VULKAN_EXTENSION_NOT_SUPPORTED], extensions_properties[j].extensionName); return VULKAN_ERROR_EXTENSION_NOT_SUPPORTED;
return VULKAN_ERROR_EXTENSION_NOT_SUPPORTED; }
supported = 0;
} }
application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -309,36 +306,35 @@ uint8_t create_instance()
VkResult result = vkCreateInstance(&create_info, NULL, &g_vulkan_instance); VkResult result = vkCreateInstance(&create_info, NULL, &g_vulkan_instance);
if (VK_SUCCESS != result) { if (VK_SUCCESS != result) {
LOGF(vulkan_error_messages[VULKAN_INTANCE_INIT_FAILED]); LOGF(vulkan_messages[VULKAN_INTANCE_INIT_FAILED]);
return VULKAN_ERROR_INSTANCE_INIT_FAILED; return VULKAN_ERROR_INSTANCE_INIT_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Surface, connection between Vulkan and actual window * @brief Create a Surface, connection between Vulkan and actual window
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
*/ */
uint8_t create_surface() static rse_err_t create_surface()
{ {
if (VK_SUCCESS != glfwCreateWindowSurface(g_vulkan_instance, get_window_handle(), NULL, &g_vulkan_state.surface)) { if (VK_SUCCESS != glfwCreateWindowSurface(g_vulkan_instance, get_window_handle(), NULL, &g_vulkan_state.surface)) {
LOGF(vulkan_error_messages[VULKAN_SURFACE_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_SURFACE_CREATION_FAILED]);
return VULKAN_ERROR_SURFACE_CREATION_FAILED; return VULKAN_ERROR_SURFACE_CREATION_FAILED;
} }
return RSE_ERROR_NO_ERROR;
return VULKAN_ERROR_NO_ERROR;
} }
/** /**
* @brief Choose physical device. Used later for vkDevice * @brief Choose physical device. Used later for vkDevice
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND * VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND
* VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND * VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND
*/ */
uint8_t pick_physical_device() static rse_err_t pick_physical_device()
{ {
uint32_t physical_device_count = 0U; uint32_t physical_device_count = 0U;
VkPhysicalDevice* physical_devices = NULL; VkPhysicalDevice* physical_devices = NULL;
@@ -349,11 +345,12 @@ uint8_t pick_physical_device()
vkEnumeratePhysicalDevices(g_vulkan_instance, &physical_device_count, NULL); vkEnumeratePhysicalDevices(g_vulkan_instance, &physical_device_count, NULL);
if (0 == physical_device_count) { if (0 == physical_device_count) {
LOGF(vulkan_error_messages[VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND]); LOGF(vulkan_messages[VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND]);
return VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND; return VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND;
} }
physical_devices = malloc(sizeof(VkPhysicalDevice) * physical_device_count); rse_malloc(physical_devices, sizeof(VkPhysicalDevice) * physical_device_count);
vkEnumeratePhysicalDevices(g_vulkan_instance, &physical_device_count, physical_devices); vkEnumeratePhysicalDevices(g_vulkan_instance, &physical_device_count, physical_devices);
/* Check for suitability */ /* Check for suitability */
@@ -373,35 +370,36 @@ uint8_t pick_physical_device()
if (VK_NULL_HANDLE == g_vulkan_state.physical_device) { if (VK_NULL_HANDLE == g_vulkan_state.physical_device) {
/* No suitable device found */ /* No suitable device found */
LOGF(vulkan_error_messages[VULKAN_NO_SUITABLE_PHYSICAL_DEVICES]); LOGF(vulkan_messages[VULKAN_NO_SUITABLE_PHYSICAL_DEVICES]);
return VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND; return VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create vkDevice object * @brief Create vkDevice object
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_QUEUE_NOT_SUPPORTED * VULKAN_ERROR_QUEUE_NOT_SUPPORTED
* VULKAN_ERROR_DEVICE_CREATION_FAILED * VULKAN_ERROR_DEVICE_CREATION_FAILED
*/ */
uint8_t create_device() static rse_err_t create_device()
{ {
size_t device_queues_count = 0; size_t device_queues_count = 0;
uint32_t queue_families_property_count = 0U; uint32_t queue_families_property_count = 0U;
ssize_t graphics_family_idx = -1; ssize_t graphics_family_idx = -1;
ssize_t presentation_familiy_idx = -1; ssize_t presentation_familiy_idx = -1;
VkQueueFamilyProperties* queue_family_properties = NULL; VkQueueFamilyProperties* queue_family_properties = NULL;
VkDeviceCreateInfo device_create_info = {}; VkDeviceCreateInfo device_create_info = {0};
VkDeviceQueueCreateInfo device_queue_createinfos[2] = {}; /* TODO: Change when we want more queues */ VkDeviceQueueCreateInfo device_queue_createinfos[2] = {0};
float* graphics_familiy_queue_priorities = NULL; float* graphics_familiy_queue_priorities = NULL;
float* presentation_familiy_queue_priorities = NULL; float* presentation_familiy_queue_priorities = NULL;
VkPhysicalDeviceFeatures2 physical_features2 = {0}; VkPhysicalDeviceFeatures2 physical_features2 = {0};
VkPhysicalDeviceDescriptorIndexingFeatures indexing_features = {0}; VkPhysicalDeviceDescriptorIndexingFeatures indexing_features = {0};
VkBool32 bindless_supported = VK_FALSE; VkBool32 bindless_supported = VK_FALSE;
/* Enable descriptori indexing for bindless textures */
indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
physical_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; physical_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
@@ -411,13 +409,13 @@ uint8_t create_device()
bindless_supported = indexing_features.descriptorBindingPartiallyBound && indexing_features.runtimeDescriptorArray; bindless_supported = indexing_features.descriptorBindingPartiallyBound && indexing_features.runtimeDescriptorArray;
if (bindless_supported == VK_FALSE) { if (bindless_supported == VK_FALSE) {
LOGE("This engine requires bindless support"); LOGF(vulkan_messages[VULKAN_BINDLESS_DESIGN_NOT_SUPPORTED]);
return 1; return VULKAN_ERROR_MISSING_FEATURES_FOR_BINDLESS_DESIGN;
} }
/* Get information about supported queue families */ /* Get information about supported queue families */
vkGetPhysicalDeviceQueueFamilyProperties(g_vulkan_state.physical_device, &queue_families_property_count, NULL); vkGetPhysicalDeviceQueueFamilyProperties(g_vulkan_state.physical_device, &queue_families_property_count, NULL);
queue_family_properties = malloc(sizeof(VkQueueFamilyProperties) * queue_families_property_count); rse_malloc(queue_family_properties, sizeof(VkQueueFamilyProperties) * queue_families_property_count);
vkGetPhysicalDeviceQueueFamilyProperties(g_vulkan_state.physical_device, &queue_families_property_count, vkGetPhysicalDeviceQueueFamilyProperties(g_vulkan_state.physical_device, &queue_families_property_count,
queue_family_properties); queue_family_properties);
@@ -442,11 +440,9 @@ uint8_t create_device()
if (presentSupport) { if (presentSupport) {
presentation_familiy_idx = familyIdx; presentation_familiy_idx = familyIdx;
/* If this is the same queue family as in graphics family, don't increase queue count */ /* If this is the same queue family as in graphics family, don't increase queue count */
//TODO: This is still ugly, but fixes an error. Change later.
if (presentation_familiy_idx != graphics_family_idx) { if (presentation_familiy_idx != graphics_family_idx) {
device_queues_count++; device_queues_count++;
} }
LOGI("Setting present family idx to %d", familyIdx);
} }
if (graphics_family_idx > 0 && presentation_familiy_idx > 0) { if (graphics_family_idx > 0 && presentation_familiy_idx > 0) {
@@ -457,21 +453,22 @@ uint8_t create_device()
/* This is not magic number ;P. We want to support exact number of required queues flags */ /* This is not magic number ;P. We want to support exact number of required queues flags */
if (0 > graphics_family_idx) { if (0 > graphics_family_idx) {
LOGF(vulkan_error_messages[VULKAN_QUEUE_NOT_SUPPORTED]); LOGF(vulkan_messages[VULKAN_QUEUE_NOT_SUPPORTED]);
return VULKAN_ERROR_QUEUE_NOT_SUPPORTED; return VULKAN_ERROR_QUEUE_NOT_SUPPORTED;
} }
g_vulkan_state.queue_family_indices[0] = graphics_family_idx; /* TODO: Change when more families are needed */ g_vulkan_state.queue_family_indices[0] = graphics_family_idx;
rse_malloc(graphics_familiy_queue_priorities, sizeof(float) * queue_family_properties[graphics_family_idx].queueCount);
graphics_familiy_queue_priorities = malloc(sizeof(float) * queue_family_properties[graphics_family_idx].queueCount);
for (size_t i = 0; i < queue_family_properties[graphics_family_idx].queueCount; i++) { for (size_t i = 0; i < queue_family_properties[graphics_family_idx].queueCount; i++) {
graphics_familiy_queue_priorities[i] = 1.0f; /* TODO: When queues have different tasks, change this if needed */ graphics_familiy_queue_priorities[i] = 1.0f;
} }
presentation_familiy_queue_priorities = malloc(sizeof(float) * queue_family_properties[presentation_familiy_idx].queueCount); rse_malloc(presentation_familiy_queue_priorities, sizeof(float) * queue_family_properties[presentation_familiy_idx].queueCount);
for (size_t i = 0; i < queue_family_properties[presentation_familiy_idx].queueCount; i++) { for (size_t i = 0; i < queue_family_properties[presentation_familiy_idx].queueCount; i++) {
presentation_familiy_queue_priorities[i] = presentation_familiy_queue_priorities[i] =
1.0f; /* TODO: When queues have different tasks, change this if needed */ 1.0f;
} }
device_queue_createinfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; device_queue_createinfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
@@ -497,27 +494,26 @@ uint8_t create_device()
device_create_info.ppEnabledLayerNames = NULL; device_create_info.ppEnabledLayerNames = NULL;
device_create_info.enabledExtensionCount = ENABLED_DEVICE_EXTENSIONS_COUT; device_create_info.enabledExtensionCount = ENABLED_DEVICE_EXTENSIONS_COUT;
device_create_info.ppEnabledExtensionNames = g_enabled_device_extensions_names; device_create_info.ppEnabledExtensionNames = g_enabled_device_extensions_names;
device_create_info.pEnabledFeatures = NULL; /* TODO: Enable features, when needed */ device_create_info.pEnabledFeatures = NULL;
if (VK_SUCCESS != vkCreateDevice(g_vulkan_state.physical_device, &device_create_info, NULL, &g_vulkan_state.device)) { if (VK_SUCCESS != vkCreateDevice(g_vulkan_state.physical_device, &device_create_info, NULL, &g_vulkan_state.device)) {
LOGF(vulkan_error_messages[VULKAN_FAILED_TO_CREATE_DEVICE]); LOGF(vulkan_messages[VULKAN_FAILED_TO_CREATE_DEVICE]);
return VULKAN_ERROR_DEVICE_CREATION_FAILED; return VULKAN_ERROR_DEVICE_CREATION_FAILED;
} }
vkGetDeviceQueue(g_vulkan_state.device, graphics_family_idx, 0, &g_vulkan_state.graphics_queue); vkGetDeviceQueue(g_vulkan_state.device, graphics_family_idx, 0, &g_vulkan_state.graphics_queue);
vkGetDeviceQueue(g_vulkan_state.device, presentation_familiy_idx, 0, &g_present_queue); vkGetDeviceQueue(g_vulkan_state.device, presentation_familiy_idx, 0, &g_present_queue);
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Memory Allocator object * @brief Create a Memory Allocator object
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_ALLOCATOR_CREATION_FAILED * VULKAN_ERROR_ALLOCATOR_CREATION_FAILED
*/ */
uint8_t create_memory_allocator() static rse_err_t create_memory_allocator()
{ {
VmaVulkanFunctions vulkan_functions = {0}; VmaVulkanFunctions vulkan_functions = {0};
vulkan_functions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr; vulkan_functions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
@@ -531,21 +527,21 @@ uint8_t create_memory_allocator()
allocator_create_info.pVulkanFunctions = &vulkan_functions; allocator_create_info.pVulkanFunctions = &vulkan_functions;
if (VK_SUCCESS != vmaCreateAllocator(&allocator_create_info, &g_vulkan_state.allocator)) { if (VK_SUCCESS != vmaCreateAllocator(&allocator_create_info, &g_vulkan_state.allocator)) {
LOGF(vulkan_error_messages[VULKAN_ERROR_ALLOCATOR_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_ERROR_ALLOCATOR_CREATION_FAILED]);
return VULKAN_ERROR_ALLOCATOR_CREATION_FAILED; return VULKAN_ERROR_ALLOCATOR_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Sync Objects * @brief Create a Sync Objects
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_SYNCOBJCTS_CREATION_FAILED * VULKAN_ERROR_SYNCOBJCTS_CREATION_FAILED
*/ */
uint8_t create_sync_objects() static rse_err_t create_sync_objects()
{ {
VkSemaphoreCreateInfo semaphore_info = {}; VkSemaphoreCreateInfo semaphore_info = {};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
@@ -558,23 +554,23 @@ uint8_t create_sync_objects()
if (VK_SUCCESS != vkCreateSemaphore(g_vulkan_state.device, &semaphore_info, NULL, &g_image_available_semaphores[i]) || if (VK_SUCCESS != vkCreateSemaphore(g_vulkan_state.device, &semaphore_info, NULL, &g_image_available_semaphores[i]) ||
VK_SUCCESS != vkCreateSemaphore(g_vulkan_state.device, &semaphore_info, NULL, &g_render_finished_semaphores[i]) || VK_SUCCESS != vkCreateSemaphore(g_vulkan_state.device, &semaphore_info, NULL, &g_render_finished_semaphores[i]) ||
VK_SUCCESS != vkCreateFence(g_vulkan_state.device, &fenceInfo, NULL, &g_in_flight_fences[i])) { VK_SUCCESS != vkCreateFence(g_vulkan_state.device, &fenceInfo, NULL, &g_in_flight_fences[i])) {
LOGF(vulkan_error_messages[VULKAN_SYNCOBJCTS_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_SYNCOBJCTS_CREATION_FAILED]);
return VULKAN_ERROR_SYNCOBJCTS_CREATION_FAILED; return VULKAN_ERROR_SYNCOBJCTS_CREATION_FAILED;
} }
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
uint8_t preinit_vulkan() rse_err_t preinit_vulkan()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
set_enabled_extension(); set_enabled_extension();
STATUS_CHECK(create_instance()); STATUS_CHECK(create_instance());
#ifndef NDEBUG #ifndef NDEBUG
setup_debug_messenger(); STATUS_CHECK(setup_debug_messenger());
#endif #endif
STATUS_CHECK(create_surface()); STATUS_CHECK(create_surface());
STATUS_CHECK(pick_physical_device()); STATUS_CHECK(pick_physical_device());
@@ -587,27 +583,28 @@ uint8_t preinit_vulkan()
return status; return status;
} }
uint8_t init_vulkan() rse_err_t init_vulkan()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_pipeline()); STATUS_CHECK(create_pipeline());
STATUS_CHECK(create_descriptors()); STATUS_CHECK(create_descriptors());
STATUS_CHECK(create_sync_objects()); STATUS_CHECK(create_sync_objects());
rse_init_time(); rse_init_time();
return status; return status;
} }
void draw_frame() rse_err_t draw_frame()
{ {
uint32_t image_index = 0U; uint32_t image_index = 0U;
VkResult result = VK_FALSE; VkResult result = VK_FALSE;
VkSubmitInfo submit_info = {}; VkSubmitInfo submit_info = {0};
VkSemaphore wait_semaphores[1]; //TODO: Increase when needed VkSemaphore wait_semaphores[1];
VkPipelineStageFlags wait_stages[1]; VkPipelineStageFlags wait_stages[1];
VkSemaphore signal_semaphores[1]; VkSemaphore signal_semaphores[1];
VkPresentInfoKHR present_info = {}; VkPresentInfoKHR present_info = {0};
VkSwapchainKHR swap_chains[1]; VkSwapchainKHR swap_chains[1];
vkWaitForFences(g_vulkan_state.device, 1, &g_in_flight_fences[g_vulkan_state.current_frame], VK_TRUE, UINT64_MAX); vkWaitForFences(g_vulkan_state.device, 1, &g_in_flight_fences[g_vulkan_state.current_frame], VK_TRUE, UINT64_MAX);
@@ -619,10 +616,10 @@ void draw_frame()
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) { if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
recreate_swapchain(); recreate_swapchain();
return; return RSE_ERROR_NO_ERROR;
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
// throw std::runtime_error("failed to acquire swap chain image!"); LOGF(vulkan_messages[VULKAN_ACQUIRE_SWAPCHAIN_FAILED]);
return; return VULKAN_ERROR_ACQUIRE_SWAPCHAIN_FAILED;
} }
update_uniform_buffers(); update_uniform_buffers();
@@ -633,7 +630,6 @@ void draw_frame()
record_command_buffer(image_index); record_command_buffer(image_index);
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
wait_semaphores[0] = g_image_available_semaphores[g_vulkan_state.current_frame]; wait_semaphores[0] = g_image_available_semaphores[g_vulkan_state.current_frame];
@@ -650,11 +646,10 @@ void draw_frame()
submit_info.pSignalSemaphores = signal_semaphores; submit_info.pSignalSemaphores = signal_semaphores;
if (vkQueueSubmit(g_vulkan_state.graphics_queue, 1, &submit_info, g_in_flight_fences[g_vulkan_state.current_frame]) != VK_SUCCESS) { if (vkQueueSubmit(g_vulkan_state.graphics_queue, 1, &submit_info, g_in_flight_fences[g_vulkan_state.current_frame]) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULAKN_DRAW_FAILED]); LOGF(vulkan_messages[VULAKN_DRAW_FAILED]);
return; return VULKAN_ERROR_DRAW_FAILED;
} }
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.waitSemaphoreCount = 1; present_info.waitSemaphoreCount = 1;
@@ -669,6 +664,8 @@ void draw_frame()
vkQueuePresentKHR(g_present_queue, &present_info); vkQueuePresentKHR(g_present_queue, &present_info);
g_vulkan_state.current_frame = (g_vulkan_state.current_frame + 1) % SWAP_BUFFER_COUNT; g_vulkan_state.current_frame = (g_vulkan_state.current_frame + 1) % SWAP_BUFFER_COUNT;
return RSE_ERROR_NO_ERROR;
} }
void deinit_vulkan() void deinit_vulkan()
+8 -10
View File
@@ -17,35 +17,33 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "utilities/rse_commons.h"
/** /**
* @brief Initialize Vulkan backend for buffers and stuff * @brief Initialize Vulkan backend for buffers and stuff
* *
* @param state * @return rse_err_t 0 on success. Status code on failure
* @return uint8_t 0 on success. Status code on failure
*/ */
uint8_t preinit_vulkan(); rse_err_t preinit_vulkan();
/** /**
* @brief Initialize Vulkan backend with descriptors * @brief Initialize Vulkan backend with descriptors
* *
* @param state * @return rse_err_t 0 on success. Status code on failure
* @return uint8_t 0 on success. Status code on failure
*/ */
uint8_t init_vulkan(); rse_err_t init_vulkan();
/** /**
* @brief Deinitialize Vulkan backend * @brief Deinitialize Vulkan backend
* *
* @param state * */
*/
void deinit_vulkan(); void deinit_vulkan();
/** /**
* @brief Draw frame on the screen. * @brief Draw frame on the screen.
* *
* @param state * @return rse_err_t
*/ */
void draw_frame(); rse_err_t draw_frame();
#endif /* RSE_GRAPHICS_VULKANBASE_HPP */ #endif /* RSE_GRAPHICS_VULKANBASE_HPP */
+46 -58
View File
@@ -3,6 +3,7 @@
#include "vulkan_errors.h" #include "vulkan_errors.h"
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "utilities/rse_errors_common.h"
#include "mesh_controller.h" #include "mesh_controller.h"
#include "rse_math.h" #include "rse_math.h"
#include "rse_vulkan_commands.h" #include "rse_vulkan_commands.h"
@@ -48,57 +49,54 @@ static void copy_buffer(VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceS
/** /**
* @brief Create a buffer holding all vertex data * @brief Create a buffer holding all vertex data
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_BUFFER_CREATION_FAILED * VULKAN_ERROR_BUFFER_CREATION_FAILED
* VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED * VULKAN_ERROR_VERTEX_BUFFER_MAPPING_FAILED
*/ */
static uint8_t create_vertex_buffer() static rse_err_t create_vertex_buffer()
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
VkDeviceSize buffer_size; VkDeviceSize buffer_size;
buffer_size = MAX_VERTEX_BUFFER_SIZE; buffer_size = MAX_VERTEX_BUFFER_SIZE;
/* Create Vertex Buffer*/ /* Create Vertex Buffer*/
if (VK_SUCCESS != create_buffer(buffer_size, STATUS_CHECK(create_buffer(buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
0, /* Will not be mapped with vmaMapMemory */ 0, /* Will not be mapped with vmaMapMemory */
&g_vertex_buffer)) { &g_vertex_buffer));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
}
g_vertex_buffer.allocated_size = 0; g_vertex_buffer.allocated_size = 0;
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create an index buffer, connected with vertex buffer * @brief Create an index buffer, connected with vertex buffer
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_BUFFER_CREATION_FAILED * VULKAN_ERROR_BUFFER_CREATION_FAILED
*/ */
static uint8_t create_index_buffer() static rse_err_t create_index_buffer()
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
VkDeviceSize buffer_size; VkDeviceSize buffer_size;
buffer_size = MAX_VERTEX_BUFFER_SIZE; buffer_size = MAX_VERTEX_BUFFER_SIZE;
/* Create Index Buffer*/ /* Create Index Buffer*/
if (VK_SUCCESS != create_buffer(buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, STATUS_CHECK(create_buffer(buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
0, /* Will not be mapped with vmaMapMemory */ 0, /* Will not be mapped with vmaMapMemory */
&g_index_buffer)) { &g_index_buffer));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
}
g_index_buffer.allocated_size = 0; g_index_buffer.allocated_size = 0;
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
static uint8_t create_instance_buffers() static rse_err_t create_instance_buffers()
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
size_t iter = 0U; size_t iter = 0U;
VkDeviceSize buffer_size; VkDeviceSize buffer_size;
@@ -106,51 +104,45 @@ static uint8_t create_instance_buffers()
for (iter = 0; iter < MAX_MESH_NUMBER; ++iter) { for (iter = 0; iter < MAX_MESH_NUMBER; ++iter) {
/* Create Instance Buffer */ /* Create Instance Buffer */
if (VK_SUCCESS != create_buffer(buffer_size, STATUS_CHECK(create_buffer(buffer_size,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */ VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
&g_instance_buffers[iter])) { &g_instance_buffers[iter]));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
}
g_instance_buffers[iter].allocated_size = 0; g_instance_buffers[iter].allocated_size = 0;
} }
if (VK_SUCCESS != create_buffer(sizeof(VkDrawIndexedIndirectCommand) * MAX_MESH_NUMBER, STATUS_CHECK(create_buffer(sizeof(VkDrawIndexedIndirectCommand) * MAX_MESH_NUMBER,
VK_BUFFER_USAGE_TRANSFER_DST_BIT VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_HOST, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
&g_draw_indirect_command_buffer)) { &g_draw_indirect_command_buffer));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]); return RSE_ERROR_NO_ERROR;
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Uniform Buffers * @brief Create a Uniform Buffers
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success.
*/ */
static uint8_t create_uniform_buffer() static rse_err_t create_uniform_buffer()
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
VkDeviceSize buffer_size = sizeof(struct rse_uniform_buffer_object_t); VkDeviceSize buffer_size = sizeof(struct rse_uniform_buffer_object_t);
for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) { for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) {
create_buffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST, STATUS_CHECK(create_buffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
&g_vulkan_state.uniform_buffers[i]); &g_vulkan_state.uniform_buffers[i]));
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
uint8_t create_buffer(const VkDeviceSize size, rse_err_t create_buffer(const VkDeviceSize size,
VkBufferUsageFlags buffer_usage, VkBufferUsageFlags buffer_usage,
VmaMemoryUsage memory_usage, VmaMemoryUsage memory_usage,
const VmaAllocationCreateFlags allocation_flags, const VmaAllocationCreateFlags allocation_flags,
@@ -183,11 +175,11 @@ uint8_t create_buffer(const VkDeviceSize size,
&buffer->buffer, &buffer->buffer,
&buffer->allocation, &buffer->allocation,
&buffer->allocation_info)) { &buffer->allocation_info)) {
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED; return VULKAN_ERROR_BUFFER_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
void destroy_buffer(struct rse_vulkan_buffer_t* buffer) void destroy_buffer(struct rse_vulkan_buffer_t* buffer)
@@ -224,12 +216,13 @@ void update_uniform_buffers()
memcpy(g_vulkan_state.uniform_buffers[g_vulkan_state.current_frame].allocation_info.pMappedData, &ubo, sizeof(ubo)); memcpy(g_vulkan_state.uniform_buffers[g_vulkan_state.current_frame].allocation_info.pMappedData, &ubo, sizeof(ubo));
} }
uint8_t rse_add_vertices(uint16_t mesh_id, rse_err_t rse_add_vertices(uint16_t mesh_id,
const struct rse_vertex_t* vertices, const struct rse_vertex_t* vertices,
const uint16_t* indices, const uint16_t* indices,
struct rse_buffer_data_t* vertex_data, struct rse_buffer_data_t* vertex_data,
struct rse_buffer_data_t* index_data) struct rse_buffer_data_t* index_data)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
VkDrawIndexedIndirectCommand draw_indirect_command; VkDrawIndexedIndirectCommand draw_indirect_command;
struct rse_vulkan_buffer_t staging_buffer; struct rse_vulkan_buffer_t staging_buffer;
size_t vertices_size = sizeof(vertices[0]) * vertex_data->count; size_t vertices_size = sizeof(vertices[0]) * vertex_data->count;
@@ -238,15 +231,12 @@ uint8_t rse_add_vertices(uint16_t mesh_id,
struct rse_vulkan_buffer_t* index_buffer = &g_index_buffer; struct rse_vulkan_buffer_t* index_buffer = &g_index_buffer;
/* Creating staging buffer*/ /* Creating staging buffer*/
if (VK_SUCCESS != create_buffer(MAX_VERTEX_BUFFER_SIZE, STATUS_CHECK(create_buffer(MAX_VERTEX_BUFFER_SIZE,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_HOST, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
VMA_ALLOCATION_CREATE_MAPPED_BIT VMA_ALLOCATION_CREATE_MAPPED_BIT
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
&staging_buffer)) { &staging_buffer));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
}
/* Fill staging buffer with vertex data */ /* Fill staging buffer with vertex data */
memset(staging_buffer.allocation_info.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE); memset(staging_buffer.allocation_info.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE);
@@ -280,26 +270,24 @@ uint8_t rse_add_vertices(uint16_t mesh_id,
memcpy(g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); memcpy(g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand));
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* instance_data) rse_err_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* instance_data)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
VkDrawIndexedIndirectCommand draw_indirect_command; VkDrawIndexedIndirectCommand draw_indirect_command;
struct rse_vulkan_buffer_t staging_buffer; struct rse_vulkan_buffer_t staging_buffer;
struct rse_vulkan_buffer_t* instance_buffer = &g_instance_buffers[mesh_id]; struct rse_vulkan_buffer_t* instance_buffer = &g_instance_buffers[mesh_id];
size_t instance_size = sizeof(struct rse_instance_data_t); size_t instance_size = sizeof(struct rse_instance_data_t);
/* Creating staging buffer*/ /* Creating staging buffer*/
if (VK_SUCCESS != create_buffer(MAX_VERTEX_BUFFER_SIZE, STATUS_CHECK(create_buffer(MAX_VERTEX_BUFFER_SIZE,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_HOST, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
VMA_ALLOCATION_CREATE_MAPPED_BIT VMA_ALLOCATION_CREATE_MAPPED_BIT
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
&staging_buffer)) { &staging_buffer));
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
}
/* Copy transformation information about instance */ /* Copy transformation information about instance */
memcpy(staging_buffer.allocation_info.pMappedData, instance_data, instance_size); memcpy(staging_buffer.allocation_info.pMappedData, instance_data, instance_size);
@@ -316,7 +304,7 @@ uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* inst
draw_indirect_command.instanceCount++; draw_indirect_command.instanceCount++;
memcpy(g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); memcpy(g_draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand));
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
@@ -324,10 +312,10 @@ uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* inst
* *
* @param command_buffer Command buffer, that will hold commands * @param command_buffer Command buffer, that will hold commands
* @param image_index Image index * @param image_index Image index
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED * VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED
*/ */
uint8_t record_command_buffer(uint32_t image_index) rse_err_t record_command_buffer(uint32_t image_index)
{ {
VkCommandBuffer command_buffer = g_vulkan_state.command_buffers[g_vulkan_state.current_frame]; VkCommandBuffer command_buffer = g_vulkan_state.command_buffers[g_vulkan_state.current_frame];
VkDescriptorSet descriptor_sets[] = {g_vulkan_state.descriptor_sets[g_vulkan_state.current_frame], VkDescriptorSet descriptor_sets[] = {g_vulkan_state.descriptor_sets[g_vulkan_state.current_frame],
@@ -352,7 +340,7 @@ uint8_t record_command_buffer(uint32_t image_index)
begin_info.pInheritanceInfo = NULL; begin_info.pInheritanceInfo = NULL;
if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) { if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_RECORD_COMMAND_BEGIN_FAILED]); LOGF(vulkan_messages[VULKAN_RECORD_COMMAND_BEGIN_FAILED]);
return VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED; return VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED;
} }
@@ -401,16 +389,16 @@ uint8_t record_command_buffer(uint32_t image_index)
vkCmdEndRenderPass(command_buffer); vkCmdEndRenderPass(command_buffer);
if (VK_SUCCESS != vkEndCommandBuffer(command_buffer)) { if (VK_SUCCESS != vkEndCommandBuffer(command_buffer)) {
LOGF(vulkan_error_messages[VULKAN_RECORD_COMMAND_BUFFER_FAILED]); LOGF(vulkan_messages[VULKAN_RECORD_COMMAND_BUFFER_FAILED]);
return VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED; return VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
uint8_t create_buffers() rse_err_t create_buffers()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_vertex_buffer()); STATUS_CHECK(create_vertex_buffer());
STATUS_CHECK(create_index_buffer()); STATUS_CHECK(create_index_buffer());
+12 -10
View File
@@ -2,6 +2,8 @@
#define RSE_VULKAN_BUFFERS_H #define RSE_VULKAN_BUFFERS_H
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "utilities/rse_commons.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include <stdint.h> #include <stdint.h>
@@ -21,9 +23,9 @@ struct rse_buffer_data_t
/** /**
* @brief Create buffers needed by vulkan pipeline * @brief Create buffers needed by vulkan pipeline
* *
* @return uint8_t * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
uint8_t create_buffers(); rse_err_t create_buffers();
/** /**
* @brief Update uniform buffers * @brief Update uniform buffers
@@ -38,9 +40,9 @@ void update_uniform_buffers();
* @param indices Indices to add * @param indices Indices to add
* @param vertex_data Mutable vertex data. Count will be read and buffer offset will be set * @param vertex_data Mutable vertex data. Count will be read and buffer offset will be set
* @param index_data Mutable index data. Count will be read and buffer offset will be set * @param index_data Mutable index data. Count will be read and buffer offset will be set
* @return uint8_t * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
uint8_t rse_add_vertices(uint16_t mesh_id, rse_err_t rse_add_vertices(uint16_t mesh_id,
const struct rse_vertex_t* vertices, const struct rse_vertex_t* vertices,
const uint16_t* indices, const uint16_t* indices,
struct rse_buffer_data_t* vertex_data, struct rse_buffer_data_t* vertex_data,
@@ -51,18 +53,18 @@ uint8_t rse_add_vertices(uint16_t mesh_id,
* *
* @param mesh_id Mesh ID * @param mesh_id Mesh ID
* @param instance_data Instance data * @param instance_data Instance data
* @return uint8_t VULKAN_ERROR_NO_ERROR on success * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* instance_data); rse_err_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* instance_data);
/** /**
* @brief Record commands for given image index * @brief Record commands for given image index
* *
* @param vulkan_state * @param vulkan_state
* @param imageIndex * @param imageIndex
* @return uint8_t VULKAN_ERROR_NO_ERROR on success * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
uint8_t record_command_buffer(uint32_t imageIndex); rse_err_t record_command_buffer(uint32_t imageIndex);
/** /**
* @brief Reset command buffer for current frame. * @brief Reset command buffer for current frame.
@@ -87,10 +89,10 @@ void destroy_buffers();
* @param memory_usage memory usage flags (mostly VMA_MEMORY_USAGE_AUTO) * @param memory_usage memory usage flags (mostly VMA_MEMORY_USAGE_AUTO)
* @param allocation_flags VMA allocation flags * @param allocation_flags VMA allocation flags
* @param buffer Buffer, that will be allocated * @param buffer Buffer, that will be allocated
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED * VULKAN_ERROR_COMMAND_BUFFER_ALLOCATION_FAILED
*/ */
uint8_t create_buffer(const VkDeviceSize size, rse_err_t create_buffer(const VkDeviceSize size,
VkBufferUsageFlags buffer_usage, VkBufferUsageFlags buffer_usage,
VmaMemoryUsage memory_usage, VmaMemoryUsage memory_usage,
const VmaAllocationCreateFlags allocation_flags, const VmaAllocationCreateFlags allocation_flags,
+13 -15
View File
@@ -2,6 +2,7 @@
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "utilities/rse_errors_common.h"
#include "vulkan_errors.h" #include "vulkan_errors.h"
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "rse_vulkan_image.h" #include "rse_vulkan_image.h"
@@ -12,16 +13,13 @@
VkDescriptorPool gDescriptorPool; VkDescriptorPool gDescriptorPool;
VkDescriptorPool gDescriptorPool_bindless; VkDescriptorPool gDescriptorPool_bindless;
static uint8_t create_descriptor_pool();
static uint8_t create_descriptor_sets();
/** /**
* @brief Create a Descriptor Pool * @brief Create a Descriptor Pool
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED * VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED
*/ */
uint8_t create_descriptor_pool() static rse_err_t create_descriptor_pool()
{ {
VkDescriptorPoolSize pool_sizes[2] = {}; VkDescriptorPoolSize pool_sizes[2] = {};
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
@@ -38,7 +36,7 @@ uint8_t create_descriptor_pool()
pool_info.maxSets = (uint32_t)(SWAP_BUFFER_COUNT); pool_info.maxSets = (uint32_t)(SWAP_BUFFER_COUNT);
if (vkCreateDescriptorPool(g_vulkan_state.device, &pool_info, NULL, &gDescriptorPool) != VK_SUCCESS) { if (vkCreateDescriptorPool(g_vulkan_state.device, &pool_info, NULL, &gDescriptorPool) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_POOL_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_DESCRIPTOR_POOL_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED; return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
} }
@@ -47,19 +45,19 @@ uint8_t create_descriptor_pool()
pool_info.pPoolSizes = &pool_sizes[1]; pool_info.pPoolSizes = &pool_sizes[1];
if (vkCreateDescriptorPool(g_vulkan_state.device, &pool_info, NULL, &gDescriptorPool_bindless) != VK_SUCCESS) { if (vkCreateDescriptorPool(g_vulkan_state.device, &pool_info, NULL, &gDescriptorPool_bindless) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_POOL_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_DESCRIPTOR_POOL_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED; return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Descriptor Sets * @brief Create a Descriptor Sets
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED */ * VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED */
uint8_t create_descriptor_sets() static rse_err_t create_descriptor_sets()
{ {
uint32_t max_binding = MAX_BINDLESS_RESOURCES - 1; uint32_t max_binding = MAX_BINDLESS_RESOURCES - 1;
VkDescriptorSetLayout layouts[SWAP_BUFFER_COUNT] = { VkDescriptorSetLayout layouts[SWAP_BUFFER_COUNT] = {
@@ -90,12 +88,12 @@ uint8_t create_descriptor_sets()
allocInfo_bindless.descriptorSetCount = 1; allocInfo_bindless.descriptorSetCount = 1;
if (vkAllocateDescriptorSets(g_vulkan_state.device, &allocInfo, g_vulkan_state.descriptor_sets) != VK_SUCCESS) { if (vkAllocateDescriptorSets(g_vulkan_state.device, &allocInfo, g_vulkan_state.descriptor_sets) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED]); LOGF(vulkan_messages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED; return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
} }
if (vkAllocateDescriptorSets(g_vulkan_state.device, &allocInfo_bindless, &g_vulkan_state.descriptor_sets_bindless) != VK_SUCCESS) { if (vkAllocateDescriptorSets(g_vulkan_state.device, &allocInfo_bindless, &g_vulkan_state.descriptor_sets_bindless) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED]); LOGF(vulkan_messages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED; return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
} }
@@ -138,12 +136,12 @@ uint8_t create_descriptor_sets()
vkUpdateDescriptorSets(g_vulkan_state.device, 2, descriptor_writes, 0, NULL); vkUpdateDescriptorSets(g_vulkan_state.device, 2, descriptor_writes, 0, NULL);
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
uint8_t create_descriptors() rse_err_t create_descriptors()
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_descriptor_pool()); STATUS_CHECK(create_descriptor_pool());
STATUS_CHECK(create_descriptor_sets()); STATUS_CHECK(create_descriptor_sets());
+4 -3
View File
@@ -2,6 +2,8 @@
#define RSE_VULKAN_DESCRIPTORS_H #define RSE_VULKAN_DESCRIPTORS_H
#include <stdint.h> #include <stdint.h>
#include "utilities/rse_commons.h"
#define MAX_BINDLESS_RESOURCES 16536 #define MAX_BINDLESS_RESOURCES 16536
@@ -9,14 +11,13 @@
* @brief Create descriptors * @brief Create descriptors
* *
* @param vulkan_state * @param vulkan_state
* @return uint8_t * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
uint8_t create_descriptors(); rse_err_t create_descriptors();
/** /**
* @brief Destroy all descriptors * @brief Destroy all descriptors
* *
* @param vulkan_state
*/ */
void destroy_descriptors(); void destroy_descriptors();
+11 -8
View File
@@ -1,21 +1,17 @@
#ifndef VULKAN_ERRORS_H #ifndef VULKAN_ERRORS_H
#define VULKAN_ERRORS_H #define VULKAN_ERRORS_H
/* Macro for checking status of function execution in initVulkan. Created to avoid writing boilerplate code */ #define RSE_VULKAN_MODULE_ID 0x0300U
#define STATUS_CHECK(FUNC) \
status = FUNC; \
if (VULKAN_ERROR_NO_ERROR != status) { \
return status; \
}
enum VULKAN_ERROR enum rse_vulkan_error_t
{ {
VULKAN_ERROR_NO_ERROR = 0x0U, VULKAN_ERROR_DEBUG_MESSENGER_CREATION_FAILED = RSE_VULKAN_MODULE_ID,
VULKAN_ERROR_LAYER_NOT_SUPPORTED, VULKAN_ERROR_LAYER_NOT_SUPPORTED,
VULKAN_ERROR_EXTENSION_NOT_SUPPORTED, VULKAN_ERROR_EXTENSION_NOT_SUPPORTED,
VULKAN_ERROR_INSTANCE_INIT_FAILED, VULKAN_ERROR_INSTANCE_INIT_FAILED,
VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND, VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND,
VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND, VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND,
VULKAN_ERROR_MISSING_FEATURES_FOR_BINDLESS_DESIGN,
VULKAN_ERROR_QUEUE_NOT_SUPPORTED, VULKAN_ERROR_QUEUE_NOT_SUPPORTED,
VULKAN_ERROR_DEVICE_CREATION_FAILED, VULKAN_ERROR_DEVICE_CREATION_FAILED,
VULKAN_ERROR_ALLOCATOR_CREATION_FAILED, VULKAN_ERROR_ALLOCATOR_CREATION_FAILED,
@@ -31,6 +27,7 @@ enum VULKAN_ERROR
VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED, VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED,
VULKAN_ERROR_RENDERPASS_CREATION_FAILED, VULKAN_ERROR_RENDERPASS_CREATION_FAILED,
VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED, VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED,
VULKAN_ERROR_FORMAT_NOT_FOUND,
VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED, VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED,
VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED, VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED,
VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED, VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED,
@@ -38,6 +35,12 @@ enum VULKAN_ERROR
VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED, VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED,
VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED, VULKAN_ERROR_RECORD_COMMAND_BUFFER_FAILED,
VULKAN_ERROR_SYNCOBJCTS_CREATION_FAILED, VULKAN_ERROR_SYNCOBJCTS_CREATION_FAILED,
VULKAN_ERROR_ACQUIRE_SWAPCHAIN_FAILED,
VULKAN_ERROR_MAX_INSTANCE_COUNT_REACHED,
VULKAN_ERROR_IMAGE_NOT_CREATED,
VULKAN_ERROR_IMAGE_VIEW_NOT_CREATED,
VULKAN_ERROR_MAX_TEXTURE_COUNT_REACHED,
VULKAN_ERROR_DRAW_FAILED,
}; };
#endif #endif
+198 -221
View File
@@ -3,6 +3,7 @@
#include "locale_vulkan.h" #include "locale_vulkan.h"
#include "utilities/file_utils.h" #include "utilities/file_utils.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "utilities/rse_errors_common.h"
#include "vulkan_errors.h" #include "vulkan_errors.h"
#include "mesh_controller.h" #include "mesh_controller.h"
#include "rse_vulkan_image.h" #include "rse_vulkan_image.h"
@@ -31,35 +32,10 @@ VkShaderModule g_shader_modules[SHADER_MODULES_COUNT];
const char* g_shader_paths[] = { const char* g_shader_paths[] = {
/* TODO: When changing to release and install, move those files*/
"../graphics/shaders/shader.vert.num", "../graphics/shaders/shader.vert.num",
"../graphics/shaders/shader.frag.num", "../graphics/shaders/shader.frag.num",
}; };
VkShaderModule create_shader_module(const char* binary_data, size_t data_size);
static uint8_t create_swapchain();
static uint8_t create_swapchain_image_views();
static uint8_t create_render_pass();
static uint8_t create_descriptor_set_layout();
static uint8_t create_pipeline_layout();
static uint8_t create_graphics_pipeline();
static uint8_t create_framebuffers();
static uint8_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages);
static void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state);
static void free_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state);
static void fill_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info);
static void free_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info);
static void fill_input_assembly_info(VkPipelineInputAssemblyStateCreateInfo* input_assembly);
static void fill_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state);
static void free_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state);
static void fill_rasterization_info(VkPipelineRasterizationStateCreateInfo* rasterizer);
static void fill_multisampling_state_info(VkPipelineMultisampleStateCreateInfo* multisampling);
static void fill_color_blend_state_info(VkPipelineColorBlendStateCreateInfo* color_blending);
static void free_color_blend_info(VkPipelineColorBlendStateCreateInfo* color_blending);
static VkVertexInputBindingDescription get_binding_description() static VkVertexInputBindingDescription get_binding_description()
{ {
VkVertexInputBindingDescription binding_description; VkVertexInputBindingDescription binding_description;
@@ -98,11 +74,10 @@ static VkVertexInputAttributeDescription* get_attribute_descriptions()
* @brief Creates shader module * @brief Creates shader module
* *
* @param binary_data Shader compiled code * @param binary_data Shader compiled code
* @return std::optional<VkShaderModule> Handle to compiled shader module or nullopt * @return rse_err_t RSE_ERROR_NO_ERROR on success
*/ */
VkShaderModule create_shader_module(const char* binary_data, size_t data_size) static rse_err_t create_shader_module(const char* binary_data, size_t data_size, VkShaderModule* shader_module)
{ {
VkShaderModule shader_module;
VkShaderModuleCreateInfo create_info = {}; VkShaderModuleCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
@@ -111,22 +86,21 @@ VkShaderModule create_shader_module(const char* binary_data, size_t data_size)
create_info.codeSize = data_size; create_info.codeSize = data_size;
create_info.pCode = (const uint32_t*)(binary_data); create_info.pCode = (const uint32_t*)(binary_data);
if (VK_SUCCESS != vkCreateShaderModule(g_vulkan_state.device, &create_info, NULL, &shader_module)) { if (VK_SUCCESS != vkCreateShaderModule(g_vulkan_state.device, &create_info, NULL, shader_module)) {
LOGF(vulkan_error_messages[VULKAN_SHADER_UNABLE_TO_CREATE_SHADER]); LOGF(vulkan_messages[VULKAN_SHADER_UNABLE_TO_CREATE_SHADER]);
// TODO: Add error handling return VULKAN_ERROR_SHADER_CREATION_FAILED;
return shader_module;
} }
return shader_module; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Swapchain * @brief Create a Swapchain
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED * VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED
*/ */
uint8_t create_swapchain() static rse_err_t create_swapchain()
{ {
VkSwapchainCreateInfoKHR create_info; VkSwapchainCreateInfoKHR create_info;
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities; VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
@@ -150,22 +124,22 @@ uint8_t create_swapchain()
create_info.flags = 0U; create_info.flags = 0U;
create_info.surface = g_vulkan_state.surface; create_info.surface = g_vulkan_state.surface;
create_info.minImageCount = SWAP_BUFFER_COUNT + 1; create_info.minImageCount = SWAP_BUFFER_COUNT + 1;
create_info.imageFormat = IMAGE_FORMAT; /* TODO: Check for supported formats */ create_info.imageFormat = IMAGE_FORMAT;
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; /* TODO: Check for supported color space */ create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
create_info.imageExtent = g_vulkan_state.swapchain_extent; create_info.imageExtent = g_vulkan_state.swapchain_extent;
create_info.imageArrayLayers = 1U; /* For non-stereoscopic-3D applications, this value is 1. */ create_info.imageArrayLayers = 1U; /* For non-stereoscopic-3D applications, this value is 1. */
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; /* TODO: Probably change later? Dunno */ create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* Using only one queue family, so this is ok */ create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; /* Using only one queue family, so this is ok */
create_info.queueFamilyIndexCount = 1U; create_info.queueFamilyIndexCount = 1U;
create_info.pQueueFamilyIndices = g_vulkan_state.queue_family_indices; create_info.pQueueFamilyIndices = g_vulkan_state.queue_family_indices;
create_info.preTransform = physical_device_surface_capabilities.currentTransform; create_info.preTransform = physical_device_surface_capabilities.currentTransform;
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR; /* TODO: Choose present mode from VkPresentModeKHR */ create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
create_info.clipped = VK_TRUE; create_info.clipped = VK_TRUE;
create_info.oldSwapchain = VK_NULL_HANDLE; create_info.oldSwapchain = VK_NULL_HANDLE;
if (VK_SUCCESS != vkCreateSwapchainKHR(g_vulkan_state.device, &create_info, NULL, &g_vulkan_state.swapchain)) { if (VK_SUCCESS != vkCreateSwapchainKHR(g_vulkan_state.device, &create_info, NULL, &g_vulkan_state.swapchain)) {
LOGF(vulkan_error_messages[VULKAN_SWAPCHAIN_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_SWAPCHAIN_CREATION_FAILED]);
return VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED; return VULKAN_ERROR_SWAPCHAIN_CREATION_FAILED;
} }
@@ -174,15 +148,15 @@ uint8_t create_swapchain()
g_swapchain_images = (VkImage*)malloc(sizeof(VkImage) * g_swapchain_images_count); g_swapchain_images = (VkImage*)malloc(sizeof(VkImage) * g_swapchain_images_count);
vkGetSwapchainImagesKHR(g_vulkan_state.device, g_vulkan_state.swapchain, &g_swapchain_images_count, g_swapchain_images); vkGetSwapchainImagesKHR(g_vulkan_state.device, g_vulkan_state.swapchain, &g_swapchain_images_count, g_swapchain_images);
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Swapchain Image Views * @brief Create a Swapchain Image Views
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
*/ */
uint8_t create_swapchain_image_views() static rse_err_t create_swapchain_image_views()
{ {
g_vulkan_state.swapchain_image_views = malloc(sizeof(VkImageView) * g_swapchain_images_count); g_vulkan_state.swapchain_image_views = malloc(sizeof(VkImageView) * g_swapchain_images_count);
for (size_t i = 0; i < g_swapchain_images_count; i++) { for (size_t i = 0; i < g_swapchain_images_count; i++) {
@@ -205,22 +179,23 @@ uint8_t create_swapchain_image_views()
create_info.subresourceRange.layerCount = 1U; create_info.subresourceRange.layerCount = 1U;
if (VK_SUCCESS != vkCreateImageView(g_vulkan_state.device, &create_info, NULL, &g_vulkan_state.swapchain_image_views[i])) { if (VK_SUCCESS != vkCreateImageView(g_vulkan_state.device, &create_info, NULL, &g_vulkan_state.swapchain_image_views[i])) {
LOGF(vulkan_error_messages[VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED]);
return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED; return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED;
} }
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Render Pass * @brief Create a Render Pass
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_RENDERPASS_CREATION_FAILED * VULKAN_ERROR_RENDERPASS_CREATION_FAILED
*/ */
uint8_t create_render_pass() static rse_err_t create_render_pass()
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
VkAttachmentDescription attachments[2] = {}; VkAttachmentDescription attachments[2] = {};
VkAttachmentDescription color_attachment = {}; VkAttachmentDescription color_attachment = {};
VkAttachmentReference color_attachment_ref = {}; VkAttachmentReference color_attachment_ref = {};
@@ -230,7 +205,8 @@ uint8_t create_render_pass()
VkAttachmentReference depth_attachment_ref = {}; VkAttachmentReference depth_attachment_ref = {};
VkSubpassDependency dependency = {}; VkSubpassDependency dependency = {};
depth_attachment.format = find_depth_format(); STATUS_CHECK(find_depth_format(&depth_attachment.format));
depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
@@ -280,19 +256,19 @@ uint8_t create_render_pass()
renderpass_info.pDependencies = &dependency; renderpass_info.pDependencies = &dependency;
if (VK_SUCCESS != vkCreateRenderPass(g_vulkan_state.device, &renderpass_info, NULL, &g_vulkan_state.render_pass)) { if (VK_SUCCESS != vkCreateRenderPass(g_vulkan_state.device, &renderpass_info, NULL, &g_vulkan_state.render_pass)) {
LOGF(vulkan_error_messages[VULKAN_RENDERPASS_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_RENDERPASS_CREATION_FAILED]);
return VULKAN_ERROR_RENDERPASS_CREATION_FAILED; return VULKAN_ERROR_RENDERPASS_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Descriptor Set Layout * @brief Create a Descriptor Set Layout
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success.
*/ */
uint8_t create_descriptor_set_layout() static rse_err_t create_descriptor_set_layout()
{ {
VkDescriptorSetLayoutCreateInfo layout_info = {}; VkDescriptorSetLayoutCreateInfo layout_info = {};
VkDescriptorSetLayoutCreateInfo layout_info_bindless = {}; VkDescriptorSetLayoutCreateInfo layout_info_bindless = {};
@@ -328,7 +304,7 @@ uint8_t create_descriptor_set_layout()
layout_info.pBindings = &bindings[0]; layout_info.pBindings = &bindings[0];
if (vkCreateDescriptorSetLayout(g_vulkan_state.device, &layout_info, NULL, &g_vulkan_state.descriptor_set_layout) != VK_SUCCESS) { if (vkCreateDescriptorSetLayout(g_vulkan_state.device, &layout_info, NULL, &g_vulkan_state.descriptor_set_layout) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED; return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
} }
@@ -338,19 +314,19 @@ uint8_t create_descriptor_set_layout()
layout_info_bindless.pBindings = &bindings[1]; layout_info_bindless.pBindings = &bindings[1];
if (vkCreateDescriptorSetLayout(g_vulkan_state.device, &layout_info_bindless, NULL, &g_vulkan_state.descriptor_set_layout_bindless) != VK_SUCCESS) { if (vkCreateDescriptorSetLayout(g_vulkan_state.device, &layout_info_bindless, NULL, &g_vulkan_state.descriptor_set_layout_bindless) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED; return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
* @brief Create a Pipeline Layout * @brief Create a Pipeline Layout
* *
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED * VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED
*/ */
uint8_t create_pipeline_layout() static rse_err_t create_pipeline_layout()
{ {
VkDescriptorSetLayout set_layouts[2] = {g_vulkan_state.descriptor_set_layout, g_vulkan_state.descriptor_set_layout_bindless}; VkDescriptorSetLayout set_layouts[2] = {g_vulkan_state.descriptor_set_layout, g_vulkan_state.descriptor_set_layout_bindless};
VkPipelineLayoutCreateInfo create_info = {}; VkPipelineLayoutCreateInfo create_info = {};
@@ -363,161 +339,24 @@ uint8_t create_pipeline_layout()
create_info.pPushConstantRanges = NULL; create_info.pPushConstantRanges = NULL;
if (VK_SUCCESS != vkCreatePipelineLayout(g_vulkan_state.device, &create_info, NULL, &g_vulkan_state.pipeline_layout)) { if (VK_SUCCESS != vkCreatePipelineLayout(g_vulkan_state.device, &create_info, NULL, &g_vulkan_state.pipeline_layout)) {
LOGF(vulkan_error_messages[VULKAN_PIPELAYOUT_CREATION_FAILED]); LOGF(vulkan_messages[VULKAN_PIPELAYOUT_CREATION_FAILED]);
return VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED; return VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED;
} }
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
}
/**
* @brief Create Graphics Pipeline
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED
*/
uint8_t create_graphics_pipeline()
{
uint8_t status = VULKAN_ERROR_NO_ERROR;
VkPipelineShaderStageCreateInfo shader_stages[SHADER_MODULES_COUNT];
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
VkPipelineViewportStateCreateInfo viewport_state = {};
VkPipelineRasterizationStateCreateInfo rasterizer = {};
VkPipelineMultisampleStateCreateInfo multisampling = {};
VkPipelineColorBlendStateCreateInfo color_blending = {};
VkPipelineDynamicStateCreateInfo dynamic_state = {};
VkPipelineDepthStencilStateCreateInfo depth_stencil = {};
STATUS_CHECK(fill_shader_stages(shader_stages));
fill_vertex_input_info(&vertex_input_info);
fill_input_assembly_info(&input_assembly);
fill_viewport_state_info(&viewport_state);
fill_rasterization_info(&rasterizer);
fill_multisampling_state_info(&multisampling);
fill_color_blend_state_info(&color_blending);
fill_dynamic_pipeline_state_info(&dynamic_state);
//TODO: Move to another function
depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depth_stencil.depthTestEnable = VK_TRUE;
depth_stencil.depthWriteEnable = VK_TRUE;
depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS;
depth_stencil.depthBoundsTestEnable = VK_FALSE;
depth_stencil.minDepthBounds = 0.0f; // Optional
depth_stencil.maxDepthBounds = 1.0f; // Optional
depth_stencil.stencilTestEnable = VK_FALSE;
// depth_stencil.front = {0}; // Optional
// depth_stencil.back = {0}; // Optional
VkGraphicsPipelineCreateInfo pipeline_info = {};
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.pNext = NULL;
pipeline_info.flags = 0U;
pipeline_info.stageCount = SHADER_MODULES_COUNT;
pipeline_info.pStages = shader_stages;
pipeline_info.pVertexInputState = &vertex_input_info;
pipeline_info.pInputAssemblyState = &input_assembly;
pipeline_info.pTessellationState = NULL;
pipeline_info.pViewportState = &viewport_state;
pipeline_info.pRasterizationState = &rasterizer;
pipeline_info.pMultisampleState = &multisampling;
pipeline_info.pDepthStencilState = &depth_stencil;
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDynamicState = &dynamic_state;
pipeline_info.layout = g_vulkan_state.pipeline_layout;
pipeline_info.renderPass = g_vulkan_state.render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_info.basePipelineIndex = -1;
if (VK_SUCCESS !=
vkCreateGraphicsPipelines(g_vulkan_state.device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &g_vulkan_state.graphics_pipeline)) {
LOGF(vulkan_error_messages[VULKAN_GRAPHICSPIPELINE_CREATION_FAILED]);
status = VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED;
}
free_dynamic_pipeline_state_info(&dynamic_state);
free_color_blend_info(&color_blending);
free_viewport_state_info(&viewport_state);
free_vertex_input_info(&vertex_input_info);
return status;
}
/**
* @brief Create Frambuffers
*
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors:
*/
uint8_t create_framebuffers()
{
g_vulkan_state.swapchain_framebuffers = malloc(sizeof(VkFramebuffer) * g_swapchain_images_count);
for (size_t i = 0; i < g_swapchain_images_count; i++) {
VkImageView attachments[] = {g_vulkan_state.swapchain_image_views[i], rse_get_depth_image_view()};
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = g_vulkan_state.render_pass;
framebufferInfo.attachmentCount = 2;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = g_vulkan_state.swapchain_extent.width;
framebufferInfo.height = g_vulkan_state.swapchain_extent.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(g_vulkan_state.device, &framebufferInfo, NULL, &g_vulkan_state.swapchain_framebuffers[i]) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_FRAMEBUFFERS_CREATION_FAILED]);
return VULKAN_ERROR_FRAMEBUFFERS_CREATION_FAILED;
}
}
return VULKAN_ERROR_NO_ERROR;
}
/**
* @brief Recreate swapchain
*
*/
void recreate_swapchain()
{
cleanup_swapchain();
create_swapchain();
create_swapchain_image_views();
create_framebuffers();
}
/**
* @brief Cleanup swapchain
*
*/
void cleanup_swapchain()
{
size_t i;
vkDeviceWaitIdle(g_vulkan_state.device);
for (i = 0; i < g_swapchain_images_count; i++) {
vkDestroyFramebuffer(g_vulkan_state.device, g_vulkan_state.swapchain_framebuffers[i], NULL);
}
for (i = 0; i < g_swapchain_images_count; i++) {
vkDestroyImageView(g_vulkan_state.device, g_vulkan_state.swapchain_image_views[i], NULL);
}
vkDestroySwapchainKHR(g_vulkan_state.device, g_vulkan_state.swapchain, NULL);
} }
/** /**
* @brief Creates shader stages from hardcoded shader paths. Changes input * @brief Creates shader stages from hardcoded shader paths. Changes input
* *
* @param shader_stages Empty vector, that will be filled with data * @param shader_stages Empty vector, that will be filled with data
* @return uint8_t VULKAN_ERROR_NO_ERROR on success. Possible errors: * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_SHADER_FILE_OPEN_FAILED * VULKAN_ERROR_SHADER_FILE_OPEN_FAILED
* VULKAN_ERROR_SHADER_CREATION_FAILED * VULKAN_ERROR_SHADER_CREATION_FAILED
*/ */
static uint8_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages) static rse_err_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages)
{ {
rse_err_t status = RSE_ERROR_NO_ERROR;
char* buffer; char* buffer;
long buffer_size; long buffer_size;
VkShaderModule vertex_shader_module; VkShaderModule vertex_shader_module;
@@ -529,18 +368,16 @@ static uint8_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages
buffer = malloc(buffer_size); buffer = malloc(buffer_size);
rse_read_file(g_shader_paths[VERTEX], &buffer_size, buffer); rse_read_file(g_shader_paths[VERTEX], &buffer_size, buffer);
vertex_shader_module = create_shader_module(buffer, buffer_size); STATUS_CHECK(create_shader_module(buffer, buffer_size, &vertex_shader_module));
free(buffer); free(buffer);
rse_read_file(g_shader_paths[FRAGMENTS], &buffer_size, NULL); rse_read_file(g_shader_paths[FRAGMENTS], &buffer_size, NULL);
buffer = malloc(buffer_size); buffer = malloc(buffer_size);
rse_read_file(g_shader_paths[FRAGMENTS], &buffer_size, buffer); rse_read_file(g_shader_paths[FRAGMENTS], &buffer_size, buffer);
fragments_shader_module = create_shader_module(buffer, buffer_size); STATUS_CHECK(create_shader_module(buffer, buffer_size, &fragments_shader_module));
free(buffer); free(buffer);
//TODO: Shader creation might have failed. Add error handling
/* Vertex Shader Pipeline Stage */ /* Vertex Shader Pipeline Stage */
vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vert_shader_stage_info.pNext = NULL; vert_shader_stage_info.pNext = NULL;
@@ -565,7 +402,7 @@ static uint8_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages
memcpy(&g_shader_modules[0], &vertex_shader_module, sizeof(VkShaderModule)); memcpy(&g_shader_modules[0], &vertex_shader_module, sizeof(VkShaderModule));
memcpy(&g_shader_modules[1], &fragments_shader_module, sizeof(VkShaderModule)); memcpy(&g_shader_modules[1], &fragments_shader_module, sizeof(VkShaderModule));
return VULKAN_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
/** /**
@@ -573,7 +410,7 @@ static uint8_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages
* *
* @param dynamic_state structure to be filled * @param dynamic_state structure to be filled
*/ */
void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state) static void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state)
{ {
VkDynamicState* dynamic_states; VkDynamicState* dynamic_states;
/* /*
@@ -601,7 +438,7 @@ void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_
* *
* @param dynamic_state structure to be freed * @param dynamic_state structure to be freed
*/ */
void free_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state) static void free_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state)
{ {
free((VkDynamicState*)dynamic_state->pDynamicStates); free((VkDynamicState*)dynamic_state->pDynamicStates);
} }
@@ -611,7 +448,7 @@ void free_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_
* *
* @param vertex_input_info structure to be filled * @param vertex_input_info structure to be filled
*/ */
void fill_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info) static void fill_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info)
{ {
const size_t binding_descriptions_count = 2; const size_t binding_descriptions_count = 2;
const size_t attribute_descriptions_count = 7; const size_t attribute_descriptions_count = 7;
@@ -627,7 +464,7 @@ void fill_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_i
binding_descriptions[0] = vertex_binding_description; binding_descriptions[0] = vertex_binding_description;
binding_descriptions[1].binding = 1; binding_descriptions[1].binding = 1;
binding_descriptions[1].stride = sizeof(struct rse_instance_data_t); //TODO: change binding_descriptions[1].stride = sizeof(struct rse_instance_data_t);
binding_descriptions[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; binding_descriptions[1].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
memcpy(attribute_descriptions, vertex_attribute_descriptions, sizeof(VkVertexInputAttributeDescription) * 3); memcpy(attribute_descriptions, vertex_attribute_descriptions, sizeof(VkVertexInputAttributeDescription) * 3);
@@ -668,7 +505,7 @@ void fill_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_i
* *
* @param vertex_input_info structure to be freed * @param vertex_input_info structure to be freed
*/ */
void free_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info) static void free_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_info)
{ {
free((VkVertexInputBindingDescription*)vertex_input_info->pVertexBindingDescriptions); free((VkVertexInputBindingDescription*)vertex_input_info->pVertexBindingDescriptions);
free((VkVertexInputAttributeDescription*)vertex_input_info->pVertexAttributeDescriptions); free((VkVertexInputAttributeDescription*)vertex_input_info->pVertexAttributeDescriptions);
@@ -679,14 +516,13 @@ void free_vertex_input_info(VkPipelineVertexInputStateCreateInfo* vertex_input_i
* *
* @param input_assembly structure to be filled * @param input_assembly structure to be filled
*/ */
void fill_input_assembly_info(VkPipelineInputAssemblyStateCreateInfo* input_assembly) static void fill_input_assembly_info(VkPipelineInputAssemblyStateCreateInfo* input_assembly)
{ {
input_assembly->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; input_assembly->sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
input_assembly->pNext = NULL; input_assembly->pNext = NULL;
input_assembly->flags = 0U; input_assembly->flags = 0U;
input_assembly->topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // TODO: Change to _STRIP input_assembly->topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
input_assembly->primitiveRestartEnable = VK_FALSE; /* If I want to break lines during _STRIP, input_assembly->primitiveRestartEnable = VK_FALSE;
* I must set this to VK_TRUE */
} }
/** /**
@@ -694,7 +530,7 @@ void fill_input_assembly_info(VkPipelineInputAssemblyStateCreateInfo* input_asse
* *
* @param viewport_state structure to be filled * @param viewport_state structure to be filled
*/ */
void fill_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state) static void fill_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state)
{ {
VkViewport* viewport = malloc(sizeof(VkViewport)); VkViewport* viewport = malloc(sizeof(VkViewport));
VkRect2D* scissor = malloc(sizeof(VkRect2D)); VkRect2D* scissor = malloc(sizeof(VkRect2D));
@@ -723,7 +559,7 @@ void fill_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state)
* *
* @param viewport_state structure to be freed * @param viewport_state structure to be freed
*/ */
void free_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state) static void free_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state)
{ {
free((VkViewport*)viewport_state->pViewports); free((VkViewport*)viewport_state->pViewports);
free((VkRect2D*)viewport_state->pScissors); free((VkRect2D*)viewport_state->pScissors);
@@ -734,7 +570,7 @@ void free_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state)
* *
* @param rasterizer * @param rasterizer
*/ */
void fill_rasterization_info(VkPipelineRasterizationStateCreateInfo* rasterizer) static void fill_rasterization_info(VkPipelineRasterizationStateCreateInfo* rasterizer)
{ {
rasterizer->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rasterizer->sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rasterizer->pNext = NULL; rasterizer->pNext = NULL;
@@ -756,7 +592,7 @@ void fill_rasterization_info(VkPipelineRasterizationStateCreateInfo* rasterizer)
* *
* @param multisampling structure to be filled * @param multisampling structure to be filled
*/ */
void fill_multisampling_state_info(VkPipelineMultisampleStateCreateInfo* multisampling) static void fill_multisampling_state_info(VkPipelineMultisampleStateCreateInfo* multisampling)
{ {
multisampling->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; multisampling->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisampling->pNext = NULL; multisampling->pNext = NULL;
@@ -774,7 +610,7 @@ void fill_multisampling_state_info(VkPipelineMultisampleStateCreateInfo* multisa
* *
* @param color_blending structure to be filled * @param color_blending structure to be filled
*/ */
void fill_color_blend_state_info(VkPipelineColorBlendStateCreateInfo* color_blending) static void fill_color_blend_state_info(VkPipelineColorBlendStateCreateInfo* color_blending)
{ {
VkPipelineColorBlendAttachmentState* color_blend_attachment = malloc(sizeof(VkPipelineColorBlendAttachmentState)); VkPipelineColorBlendAttachmentState* color_blend_attachment = malloc(sizeof(VkPipelineColorBlendAttachmentState));
@@ -806,14 +642,155 @@ void fill_color_blend_state_info(VkPipelineColorBlendStateCreateInfo* color_blen
* *
* @param color_blending Structure to be freed * @param color_blending Structure to be freed
*/ */
void free_color_blend_info(VkPipelineColorBlendStateCreateInfo* color_blending) static void free_color_blend_info(VkPipelineColorBlendStateCreateInfo* color_blending)
{ {
free((VkPipelineColorBlendAttachmentState*)color_blending->pAttachments); free((VkPipelineColorBlendAttachmentState*)color_blending->pAttachments);
} }
uint8_t create_pipeline() static void fill_depth_stencil_info(VkPipelineDepthStencilStateCreateInfo* depth_stencil)
{ {
uint8_t status = VULKAN_ERROR_NO_ERROR; depth_stencil->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depth_stencil->depthTestEnable = VK_TRUE;
depth_stencil->depthWriteEnable = VK_TRUE;
depth_stencil->depthCompareOp = VK_COMPARE_OP_LESS;
depth_stencil->depthBoundsTestEnable = VK_FALSE;
depth_stencil->minDepthBounds = 0.0f; // Optional
depth_stencil->maxDepthBounds = 1.0f; // Optional
depth_stencil->stencilTestEnable = VK_FALSE;
// depth_stencil.front = {0}; // Optional
// depth_stencil.back = {0}; // Optional
}
/**
* @brief Create Graphics Pipeline
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED
*/
static rse_err_t create_graphics_pipeline()
{
rse_err_t status = RSE_ERROR_NO_ERROR;
VkPipelineShaderStageCreateInfo shader_stages[SHADER_MODULES_COUNT];
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
VkPipelineInputAssemblyStateCreateInfo input_assembly = {};
VkPipelineViewportStateCreateInfo viewport_state = {};
VkPipelineRasterizationStateCreateInfo rasterizer = {};
VkPipelineMultisampleStateCreateInfo multisampling = {};
VkPipelineColorBlendStateCreateInfo color_blending = {};
VkPipelineDynamicStateCreateInfo dynamic_state = {};
VkPipelineDepthStencilStateCreateInfo depth_stencil = {};
STATUS_CHECK(fill_shader_stages(shader_stages));
fill_vertex_input_info(&vertex_input_info);
fill_input_assembly_info(&input_assembly);
fill_viewport_state_info(&viewport_state);
fill_rasterization_info(&rasterizer);
fill_multisampling_state_info(&multisampling);
fill_color_blend_state_info(&color_blending);
fill_dynamic_pipeline_state_info(&dynamic_state);
fill_depth_stencil_info(&depth_stencil);
VkGraphicsPipelineCreateInfo pipeline_info = {};
pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipeline_info.pNext = NULL;
pipeline_info.flags = 0U;
pipeline_info.stageCount = SHADER_MODULES_COUNT;
pipeline_info.pStages = shader_stages;
pipeline_info.pVertexInputState = &vertex_input_info;
pipeline_info.pInputAssemblyState = &input_assembly;
pipeline_info.pTessellationState = NULL;
pipeline_info.pViewportState = &viewport_state;
pipeline_info.pRasterizationState = &rasterizer;
pipeline_info.pMultisampleState = &multisampling;
pipeline_info.pDepthStencilState = &depth_stencil;
pipeline_info.pColorBlendState = &color_blending;
pipeline_info.pDynamicState = &dynamic_state;
pipeline_info.layout = g_vulkan_state.pipeline_layout;
pipeline_info.renderPass = g_vulkan_state.render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
pipeline_info.basePipelineIndex = -1;
if (VK_SUCCESS !=
vkCreateGraphicsPipelines(g_vulkan_state.device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &g_vulkan_state.graphics_pipeline)) {
LOGF(vulkan_messages[VULKAN_GRAPHICSPIPELINE_CREATION_FAILED]);
status = VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED;
}
free_dynamic_pipeline_state_info(&dynamic_state);
free_color_blend_info(&color_blending);
free_viewport_state_info(&viewport_state);
free_vertex_input_info(&vertex_input_info);
return status;
}
/**
* @brief Create Frambuffers
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
*/
static rse_err_t create_framebuffers()
{
g_vulkan_state.swapchain_framebuffers = malloc(sizeof(VkFramebuffer) * g_swapchain_images_count);
for (size_t i = 0; i < g_swapchain_images_count; i++) {
VkImageView attachments[] = {g_vulkan_state.swapchain_image_views[i], rse_get_depth_image_view()};
VkFramebufferCreateInfo framebufferInfo = {};
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
framebufferInfo.renderPass = g_vulkan_state.render_pass;
framebufferInfo.attachmentCount = 2;
framebufferInfo.pAttachments = attachments;
framebufferInfo.width = g_vulkan_state.swapchain_extent.width;
framebufferInfo.height = g_vulkan_state.swapchain_extent.height;
framebufferInfo.layers = 1;
if (vkCreateFramebuffer(g_vulkan_state.device, &framebufferInfo, NULL, &g_vulkan_state.swapchain_framebuffers[i]) != VK_SUCCESS) {
LOGF(vulkan_messages[VULKAN_FRAMEBUFFERS_CREATION_FAILED]);
return VULKAN_ERROR_FRAMEBUFFERS_CREATION_FAILED;
}
}
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Recreate swapchain
*
*/
void recreate_swapchain()
{
cleanup_swapchain();
create_swapchain();
create_swapchain_image_views();
create_framebuffers();
}
/**
* @brief Cleanup swapchain
*
*/
void cleanup_swapchain()
{
size_t i;
vkDeviceWaitIdle(g_vulkan_state.device);
for (i = 0; i < g_swapchain_images_count; i++) {
vkDestroyFramebuffer(g_vulkan_state.device, g_vulkan_state.swapchain_framebuffers[i], NULL);
}
for (i = 0; i < g_swapchain_images_count; i++) {
vkDestroyImageView(g_vulkan_state.device, g_vulkan_state.swapchain_image_views[i], NULL);
}
vkDestroySwapchainKHR(g_vulkan_state.device, g_vulkan_state.swapchain, NULL);
}
rse_err_t create_pipeline()
{
rse_err_t status = RSE_ERROR_NO_ERROR;
STATUS_CHECK(create_swapchain()); STATUS_CHECK(create_swapchain());
STATUS_CHECK(create_swapchain_image_views()); STATUS_CHECK(create_swapchain_image_views());
+3 -6
View File
@@ -2,35 +2,32 @@
#define RSE_VULKAN_PIPELINE_H #define RSE_VULKAN_PIPELINE_H
#include "vulkan_commons.h" #include "vulkan_commons.h"
#include "utilities/rse_commons.h"
#include <stdint.h> #include <stdint.h>
/** /**
* @brief Create a graphics pipeline * @brief Create a graphics pipeline
* *
* @param vulkan_state * @return rse_err_t RSE_ERROR_NO_ERROR on success
* @return uint8_t
*/ */
uint8_t create_pipeline(void); rse_err_t create_pipeline(void);
/** /**
* @brief Cleanup swapchain * @brief Cleanup swapchain
* *
* @param vulkan_state
*/ */
void cleanup_swapchain(void); void cleanup_swapchain(void);
/** /**
* @brief Recreates swapchain * @brief Recreates swapchain
* *
* @param vulkan_state
*/ */
void recreate_swapchain(void); void recreate_swapchain(void);
/** /**
* @brief Destroy all vulkan pipeline objects * @brief Destroy all vulkan pipeline objects
* *
* @param vulkan_state
*/ */
void destroy_pipeline(void); void destroy_pipeline(void);
+5 -12
View File
@@ -13,16 +13,9 @@
#include "locale_window.h" #include "locale_window.h"
#include "utilities/logger.h" #include "utilities/logger.h"
#include "utilities/rse_errors_common.h"
#include "vulkan_base.h" #include "vulkan_base.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 *g_window_handle = NULL; GLFWwindow *g_window_handle = NULL;
/** /**
@@ -58,7 +51,7 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
} }
uint16_t window_init() rse_err_t window_init()
{ {
/* Initiliaze GLFW AP */ /* Initiliaze GLFW AP */
if (GLFW_TRUE != glfwInit()) if (GLFW_TRUE != glfwInit())
@@ -89,17 +82,17 @@ uint16_t window_init()
glfwSetKeyCallback(g_window_handle, key_callback); glfwSetKeyCallback(g_window_handle, key_callback);
return WINDOW_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
uint16_t window_loop() rse_err_t window_loop()
{ {
while (!glfwWindowShouldClose(g_window_handle)) { while (!glfwWindowShouldClose(g_window_handle)) {
glfwPollEvents(); glfwPollEvents();
draw_frame(); draw_frame();
} }
return WINDOW_ERROR_NO_ERROR; return RSE_ERROR_NO_ERROR;
} }
void window_terminate() void window_terminate()
+7 -4
View File
@@ -17,23 +17,26 @@
/* Vulkan header MUST be included before glfw */ /* Vulkan header MUST be included before glfw */
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "rse_window_errors.h"
#include "utilities/rse_commons.h"
/** /**
* @brief Initialize window * @brief Initialize window
* *
* @return uint16_t WINDOW_SUCCESS on success. Possible errors: * @return rse_err_t WINDOW_SUCCESS on success. Possible errors:
* WINDOW_VULKAN_NOT_LOADED * WINDOW_VULKAN_NOT_LOADED
* WINDOW_WINDOW_NOT_CREATED * WINDOW_WINDOW_NOT_CREATED
* *
*/ */
uint16_t window_init(); rse_err_t window_init();
/** /**
* @brief Main window loop * @brief Main window loop
* *
* @param vulkan_state * @param vulkan_state
* @return uint16_t WINDOW_SUCCESS or error code * @return rse_err_t WINDOW_SUCCESS or error code
*/ */
uint16_t window_loop(); rse_err_t window_loop();
/** /**
* @brief Closes window and terminates GLFW * @brief Closes window and terminates GLFW
+5 -5
View File
@@ -14,14 +14,14 @@
#include "localization.h" #include "localization.h"
#define vulkan_error_messages vulkan_error_messages_nolocale[SELECTED_LANGUAGE] #define common_messages common_messages_nolocale[SELECTED_LANGUAGE]
enum vulkan_errors_t { enum common_errors_t {
COMMON_MEMORY_ALLOCATION_FAILED, COMMON_ERROR_MEMORY_ALLOCATION_FAILED,
LAST_MESSAGE COMMON_ERROR_LAST_MESSAGE
}; };
static const char vulkan_error_messages_nolocale[LAST_LANGUAGE][LAST_MESSAGE][MAX_MESSAGE_LENGHT] = { static const char common_messages_nolocale[LAST_LANGUAGE][COMMON_ERROR_LAST_MESSAGE][MAX_MESSAGE_LENGHT] = {
{/* EN_US */ {/* EN_US */
/* COMMON_MEMORY_ALLOCATION_FAILED */ /* COMMON_MEMORY_ALLOCATION_FAILED */
"Unable to allocate memory" "Unable to allocate memory"
+2 -2
View File
@@ -34,7 +34,7 @@
* @brief Log level. Is not an enum class, because level is being compared to enable prints * @brief Log level. Is not an enum class, because level is being compared to enable prints
* *
*/ */
typedef enum enum log_level_t
{ {
LOGLEVEL_TRACE, LOGLEVEL_TRACE,
LOGLEVEL_DEBUG, LOGLEVEL_DEBUG,
@@ -42,7 +42,7 @@ typedef enum
LOGLEVEL_WARNING, LOGLEVEL_WARNING,
LOGLEVEL_ERROR, LOGLEVEL_ERROR,
LOGLEVEL_FATAL LOGLEVEL_FATAL
} LogLevel; };
void _log_log(unsigned int level, const char* file, int line, const char* fmt, ...); void _log_log(unsigned int level, const char* file, int line, const char* fmt, ...);
+34
View File
@@ -0,0 +1,34 @@
/**
* @file rse_commons.h
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief Common functionality for all modules
* @version 0.1
* @date 2023-10-05
*
* @copyright Copyright (c) 2023
*
*/
#ifndef RSE_COMMONS_H
#define RSE_COMMONS_H
#include <stdint.h>
/**
* @brief Macro for allocating memory and checking it on the same line
*
*/
#define rse_malloc(ptr, size) \
ptr = malloc(size); \
if (ptr == NULL) { \
LOGF(common_messages[COMMON_ERROR_MEMORY_ALLOCATION_FAILED]); \
return RSE_COMMON_ERROR_MALLLOC_FAILED; \
}
/**
* @brief Error type for RSE
*
*/
typedef uint32_t rse_err_t;
#endif /* RSE_COMMONS_H */
+30
View File
@@ -0,0 +1,30 @@
/**
* @file rse_errors_common.h
* @author Piotr Krygier (everyonecancode@gmail.com)
* @brief Common error messages, that can appear in any module
* @version 0.1
* @date 2023-10-05
*
* @copyright Copyright (c) 2023
*
*/
#ifndef RSE_ERRORS_COMMON_H
/* Macro for checking status of function execution in initVulkan. Created to avoid writing boilerplate code */
#define STATUS_CHECK(FUNC) \
status = FUNC; \
if (RSE_ERROR_NO_ERROR != status) { \
return status; \
}
#define RSE_COMMON_MODULE_ID 0x0100U
enum rse_common_error_t
{
RSE_ERROR_NO_ERROR = RSE_COMMON_MODULE_ID,
RSE_COMMON_ERROR_MALLLOC_FAILED,
};
#define RSE_ERRORS_COMMON_H
#endif /* RSE_ERRORS_COMMON_H */