Refactor project
Crealned up some TODOs, FIXMEs etc. Added better error handling. Looks better, feels better.
This commit is contained in:
1 parent
bd4dd74881
commit
42dc4d6fcd
29 files changed
+750
-645
No files matched your search
+21
-2
@@ -3,9 +3,28 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void rse_graphics_init(void);
|
||||
uint8_t rse_graphics_run(void);
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
#endif /* RSE_GRAPHICS_H */
|
||||
@@ -14,14 +14,16 @@
|
||||
|
||||
#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_EXTENSION_NOT_SUPPORTED,
|
||||
VULKAN_INTANCE_INIT_FAILED,
|
||||
VULKAN_NO_PHYSICAL_DEVICES,
|
||||
VULKAN_NO_SUITABLE_PHYSICAL_DEVICES,
|
||||
VULKAN_BINDLESS_DESIGN_NOT_SUPPORTED,
|
||||
VULKAN_QUEUE_NOT_SUPPORTED,
|
||||
VULKAN_FAILED_TO_CREATE_DEVICE,
|
||||
VULKAN_ALLOCATOR_CREATION_FAILED,
|
||||
@@ -31,6 +33,7 @@ enum vulkan_errors_t {
|
||||
VULKAN_COMMAND_BUFFER_ALLOCATION_FAILED,
|
||||
VULKAN_SURFACE_CREATION_FAILED,
|
||||
VULKAN_SWAPCHAIN_CREATION_FAILED,
|
||||
VULKAN_ACQUIRE_SWAPCHAIN_FAILED,
|
||||
VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED,
|
||||
VULKAN_SHADER_UNABLE_TO_OPEN,
|
||||
VULKAN_SHADER_UNABLE_TO_CREATE_SHADER,
|
||||
@@ -47,11 +50,17 @@ enum vulkan_errors_t {
|
||||
VULKAN_MESH_NO_FREE,
|
||||
VULKAN_MESH_INSTANCE_NO_FREE,
|
||||
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 */
|
||||
/* VULKAN_DEBUG_MESSENGER_SETUP_FAILED*/
|
||||
"Failed to setup debug messenger\n",
|
||||
/* VULKAN_LAYER_NOT_SUPPORTED */
|
||||
"Selected layer is not supported: %s\n",
|
||||
/* 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",
|
||||
/* VULKAN_NO_SUITABLE_PHYSICAL_DEVICES */
|
||||
"No suitable physical device found\n",
|
||||
/* VULKAN_BINDLESS_DESIGN_NOT_SUPPORTED */
|
||||
"Required features for bindless design not supported\n",
|
||||
/* VULKAN_QUEUE_NOT_SUPPORTED */
|
||||
"Selected physical device does not support required queue capabilities\n",
|
||||
/* 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",
|
||||
/* VULKAN_SWAPCHAIN_CREATION_FAILED */
|
||||
"Failed to create swapchain\n",
|
||||
/* VULKAN_ACQUIRE_SWAPCHAIN_FAILED */
|
||||
"Failed to acquire swapchain image\n",
|
||||
/* VULKAN_SWAPCHAIN_IMVIEW_CREATION_FAILED */
|
||||
"Failed to create swapchain image view\n",
|
||||
/* 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 */
|
||||
"Could not allocate new mesh instance\n",
|
||||
/* 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",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
#define window_error_messages window_error_messages_nolocale[SELECTED_LANGUAGE]
|
||||
|
||||
enum Errors
|
||||
enum window_messages_t
|
||||
{
|
||||
WINDOW_GLFW_INIT_FAILED,
|
||||
WINDOW_VULKAN_NOT_SUPPORTED,
|
||||
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 */
|
||||
/* WINDOW_GLFW_INIT_FAILED */
|
||||
"GLFW init failed!\n",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "mesh_controller.h"
|
||||
|
||||
#include "vulkan_buffers.h"
|
||||
#include "vulkan_errors.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
#include "locale_vulkan.h"
|
||||
#include "utilities/logger.h"
|
||||
|
||||
@@ -53,13 +55,12 @@ uint16_t create_mesh(struct rse_vertex_t* vertices,
|
||||
}
|
||||
|
||||
if(iter >= MAX_MESH_NUMBER) {
|
||||
LOGE(vulkan_error_messages[VULKAN_MESH_NO_FREE]);
|
||||
LOGE(vulkan_messages[VULKAN_MESH_NO_FREE]);
|
||||
/* TODO: Add error handling */
|
||||
return MAX_MESH_NUMBER;
|
||||
}
|
||||
|
||||
g_meshes[iter].is_mesh_id_taken = MESH_ID_TAKEN;
|
||||
|
||||
g_meshes[iter].unique_id = iter;
|
||||
g_meshes[iter].vertex_data.count = vertices_count;
|
||||
g_meshes[iter].index_data.count = indices_count;
|
||||
@@ -71,7 +72,7 @@ uint16_t create_mesh(struct rse_vertex_t* vertices,
|
||||
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)
|
||||
{
|
||||
size_t iter = 0U;
|
||||
@@ -83,9 +84,8 @@ void create_mesh_instance(uint16_t mesh_id,
|
||||
}
|
||||
|
||||
if(iter >= MAX_INSTANCE_NUMBER) {
|
||||
LOGE(vulkan_error_messages[VULKAN_MESH_NO_FREE]);
|
||||
/* TODO: Add error handling */
|
||||
return;
|
||||
LOGE(vulkan_messages[VULKAN_MESH_NO_FREE]);
|
||||
return VULKAN_ERROR_MAX_INSTANCE_COUNT_REACHED;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
size_t get_vertices_count(uint16_t mesh_id)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define RSE_MESH_CONTROLLER_H
|
||||
|
||||
#include "vulkan_commons.h"
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
/**
|
||||
* @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 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);
|
||||
|
||||
/**
|
||||
@@ -60,10 +61,12 @@ size_t get_indices_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);
|
||||
|
||||
VkDrawIndexedIndirectCommand get_indices_data_buffer(uint16_t mesh_id);
|
||||
|
||||
|
||||
|
||||
#endif /* RSE_MESH_CONTROLLER_H */
|
||||
+20
-12
@@ -5,13 +5,17 @@
|
||||
#include "mesh_controller.h"
|
||||
#include "vulkan_commons.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"
|
||||
|
||||
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.physical_device = VK_NULL_HANDLE;
|
||||
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.swapchain = VK_NULL_HANDLE;
|
||||
|
||||
window_init();
|
||||
STATUS_CHECK(window_init());
|
||||
STATUS_CHECK(preinit_vulkan());
|
||||
|
||||
if (0 != preinit_vulkan())
|
||||
return;
|
||||
return status;
|
||||
}
|
||||
|
||||
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
|
||||
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()) {
|
||||
return -1;
|
||||
}
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
STATUS_CHECK(init_vulkan());
|
||||
|
||||
window_loop();
|
||||
STATUS_CHECK(window_loop());
|
||||
|
||||
deinit_vulkan();
|
||||
|
||||
window_terminate();
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
@@ -29,27 +29,6 @@ static float scalar_cross_vec3(const struct vec3_t* vec1, const struct vec3_t* v
|
||||
+(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)
|
||||
{
|
||||
return degrees * (PI/180.0f);
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
#ifndef RSE_MATH_H
|
||||
#define RSE_MATH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
struct mat4_t rse_math_rotate(struct mat4_t matrix, float radians, struct vec3_t rotation_vector);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RSE_MATH_H */
|
||||
@@ -3,39 +3,40 @@
|
||||
#include "vulkan_errors.h"
|
||||
#include "locale_vulkan.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
|
||||
VkCommandPool g_command_pool = VK_NULL_HANDLE;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
static uint8_t create_command_pools()
|
||||
static rse_err_t create_command_pools()
|
||||
{
|
||||
VkCommandPoolCreateInfo create_info;
|
||||
|
||||
create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
create_info.pNext = NULL;
|
||||
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)) {
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
static uint8_t allocate_command_buffers()
|
||||
static rse_err_t allocate_command_buffers()
|
||||
{
|
||||
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.pNext = NULL;
|
||||
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;
|
||||
|
||||
if (VK_SUCCESS != vkAllocateCommandBuffers(g_vulkan_state.device,
|
||||
&allocate_info,
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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(allocate_command_buffers());
|
||||
|
||||
|
||||
@@ -14,11 +14,33 @@
|
||||
|
||||
#include "vulkan_commons.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();
|
||||
|
||||
/**
|
||||
* @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();
|
||||
|
||||
/**
|
||||
* @brief Close command buffer and execute recorded command.
|
||||
*
|
||||
* @param command_buffer Command buffer for execution
|
||||
*/
|
||||
void rse_end_single_time_comands(VkCommandBuffer command_buffer);
|
||||
|
||||
#endif /* RSE_VULKAN_COMMANDS_H */
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "utilities/file_utils.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
#include "locale_vulkan.h"
|
||||
#include "vulkan_errors.h"
|
||||
#include "rse_vulkan_commands.h"
|
||||
@@ -42,7 +43,7 @@ struct rse_vulkan_image_t g_depth_image;
|
||||
VkSampler g_sampler;
|
||||
|
||||
|
||||
static uint8_t create_sampler()
|
||||
static rse_err_t create_sampler()
|
||||
{
|
||||
VkSamplerCreateInfo create_info = {0};
|
||||
|
||||
@@ -73,17 +74,14 @@ static uint8_t create_sampler()
|
||||
return 1;
|
||||
}
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// static uint8_t has_stencil_component(VkFormat format) {
|
||||
// return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
|
||||
// }
|
||||
|
||||
static VkFormat find_supported_format(const VkFormat* candidates,
|
||||
static rse_err_t find_supported_format(const VkFormat* candidates,
|
||||
size_t candidates_count,
|
||||
VkImageTiling tiling,
|
||||
VkFormatFeatureFlags features)
|
||||
VkFormatFeatureFlags features,
|
||||
VkFormat* found_format)
|
||||
{
|
||||
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);
|
||||
|
||||
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) {
|
||||
return candidates[i];
|
||||
*found_format = candidates[i];
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
LOGE("Failed to find correct format");
|
||||
//FIXME: Add error handling
|
||||
return 0;
|
||||
LOGE(vulkan_messages[VULKAN_FORMAT_NOT_FOUND]);
|
||||
return VULKAN_ERROR_FORMAT_NOT_FOUND;
|
||||
}
|
||||
|
||||
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};
|
||||
VkExtent3D image_extent = {0};
|
||||
VkImageCreateInfo image_info = {0};
|
||||
@@ -114,7 +113,7 @@ static uint8_t create_depth_resources()
|
||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
||||
|
||||
|
||||
depth_format = find_depth_format();
|
||||
STATUS_CHECK(find_depth_format(&depth_format));
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vulkan_state.physical_device,
|
||||
g_vulkan_state.surface,
|
||||
&physical_device_surface_capabilities);
|
||||
@@ -156,8 +155,8 @@ static uint8_t create_depth_resources()
|
||||
&g_depth_image.image,
|
||||
&g_depth_image.allocation,
|
||||
&g_depth_image.allocation_info)) {
|
||||
LOGF("Failed to create image");
|
||||
return -1;
|
||||
LOGF(vulkan_messages[VULKAN_IMAGE_NOT_CREATED]);
|
||||
return VULKAN_ERROR_IMAGE_NOT_CREATED;
|
||||
}
|
||||
|
||||
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,
|
||||
NULL,
|
||||
&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 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)
|
||||
{
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
return 4;
|
||||
*format_size = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -200,12 +200,17 @@ static VkDeviceSize format_to_pixel_size(VkFormat format)
|
||||
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};
|
||||
VkDeviceSize staging_buffer_size = 0U;
|
||||
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};
|
||||
VkImageViewCreateInfo image_view_create_info = {0};
|
||||
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) {
|
||||
if(g_texture_images[i].id_taken == IMAGE_FREE) {
|
||||
free_texture_image = &g_texture_images[i];
|
||||
while(free_texture_image == NULL || *texture_id > RSE_MAX_IMAGE_COUNT) {
|
||||
if(g_texture_images[*texture_id].id_taken == IMAGE_FREE) {
|
||||
free_texture_image = &g_texture_images[*texture_id];
|
||||
} else {
|
||||
++i;
|
||||
*texture_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we found free image handle */
|
||||
if (free_texture_image == NULL) {
|
||||
LOGE("Failed to find free texture image handle");
|
||||
return -1;
|
||||
LOGE(vulkan_messages[VULKAN_MAX_TEXTURE_COUNT_REACHED]);
|
||||
*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.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->allocation,
|
||||
&free_texture_image->allocation_info)) {
|
||||
LOGF("Failed to create image");
|
||||
return -1;
|
||||
LOGF(vulkan_messages[VULKAN_IMAGE_NOT_CREATED]);
|
||||
return VULKAN_ERROR_IMAGE_NOT_CREATED;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
&staging_buffer)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return -1;
|
||||
}
|
||||
&staging_buffer));
|
||||
|
||||
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,
|
||||
NULL,
|
||||
&free_texture_image->image_view)) {
|
||||
LOGF("Failed to create image view");
|
||||
return -1;
|
||||
LOGF(vulkan_messages[VULKAN_IMAGE_VIEW_NOT_CREATED]);
|
||||
return VULKAN_ERROR_IMAGE_VIEW_NOT_CREATED;
|
||||
}
|
||||
|
||||
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_depth_resources());
|
||||
@@ -394,16 +399,14 @@ uint8_t init_vulkan_images()
|
||||
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 height = 0;
|
||||
int channels = 0;
|
||||
stbi_uc* pixel_buffer = NULL;
|
||||
|
||||
int8_t ret;
|
||||
|
||||
|
||||
pixel_buffer = stbi_load(file_path, &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (pixel_buffer == NULL) {
|
||||
@@ -412,14 +415,14 @@ int8_t rse_load_texture(const char* file_path)
|
||||
}
|
||||
|
||||
/* Create actual Vulkan Image */
|
||||
ret = create_vulkan_image(width,
|
||||
status = create_vulkan_image(width,
|
||||
height,
|
||||
VK_FORMAT_R8G8B8A8_SRGB,
|
||||
pixel_buffer);
|
||||
pixel_buffer, texture_id);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -474,16 +477,20 @@ size_t get_textures_count()
|
||||
return count;
|
||||
}
|
||||
|
||||
VkFormat find_depth_format()
|
||||
rse_err_t find_depth_format(VkFormat* found_format)
|
||||
{
|
||||
#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};
|
||||
|
||||
return find_supported_format(
|
||||
STATUS_CHECK(find_supported_format(
|
||||
formats,
|
||||
formats_count,
|
||||
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
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
#define RSE_TEXTURE_H
|
||||
|
||||
#include "utilities/file_utils.h"
|
||||
#include "utilities/rse_commons.h"
|
||||
#include "vulkan_commons.h"
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -27,17 +28,18 @@
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
* @param path Path to texture file
|
||||
* @return int8_t -1 on error. Texture ID on success
|
||||
* @param file_path Path to texture file
|
||||
* @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.
|
||||
@@ -64,9 +66,9 @@ VkSampler rse_get_texture_sampler();
|
||||
* @brief Checks if image exists for provided 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
|
||||
@@ -75,7 +77,7 @@ int8_t image_exists(uint8_t image_id);
|
||||
*/
|
||||
size_t get_textures_count();
|
||||
|
||||
VkFormat find_depth_format();
|
||||
rse_err_t find_depth_format(VkFormat* found_format);
|
||||
|
||||
VkImageView rse_get_depth_image_view();
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -1,7 +1,10 @@
|
||||
#version 450
|
||||
|
||||
/* 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 = 1) in vec2 fragTexCoord;
|
||||
|
||||
+149
-152
@@ -11,23 +11,26 @@
|
||||
|
||||
#include "vulkan_base.h"
|
||||
|
||||
#include "vulkan_errors.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
/* We are building with -Werror flag on, but there are some warning in VMA implementation. Thus diagnostic push */
|
||||
// #pragma GCC diagnostic push
|
||||
// #pragma GCC diagnostic ignored "-Wunused-function"
|
||||
// #pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
// #pragma GCC diagnostic ignored "-Wpedantic"
|
||||
// #pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
// #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
// #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
// #pragma GCC diagnostic ignored "-Wswitch"
|
||||
// #pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#include "vk_mem_alloc.h"
|
||||
#pragma GCC diagnostic pop
|
||||
// #pragma GCC diagnostic pop
|
||||
|
||||
#include "locale_vulkan.h"
|
||||
#include "utilities/locale_common.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "vulkan_errors.h"
|
||||
#include "window.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] = {};
|
||||
|
||||
|
||||
|
||||
#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
|
||||
@@ -137,15 +87,29 @@ void setup_debug_messenger()
|
||||
* @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
|
||||
*/
|
||||
VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data)
|
||||
{
|
||||
enum log_level_t log_level = LOGLEVEL_TRACE;
|
||||
(void)message_severity;
|
||||
(void)message_type;
|
||||
(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;
|
||||
}
|
||||
@@ -159,7 +123,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBit
|
||||
* @param debug_messenger Debug messanger handle
|
||||
* @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,
|
||||
VkDebugUtilsMessengerEXT* debug_messenger)
|
||||
{
|
||||
@@ -175,6 +139,34 @@ VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMes
|
||||
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
|
||||
*
|
||||
@@ -182,7 +174,7 @@ VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMes
|
||||
* @param debug_messenger Debug messanger handle
|
||||
* @param allocator Memory allocator
|
||||
*/
|
||||
void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger,
|
||||
static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger,
|
||||
const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
PFN_vkDestroyDebugUtilsMessengerEXT func =
|
||||
@@ -192,13 +184,13 @@ void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* DEBUG */
|
||||
|
||||
/**
|
||||
* @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[1] = "VK_KHR_device_group_creation";
|
||||
@@ -210,49 +202,54 @@ void set_enabled_extension()
|
||||
g_enabled_instance_extensions_names[2] = "VK_KHR_xcb_surface";
|
||||
}
|
||||
#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
|
||||
|
||||
/* Add custom extensions here and make VK_EXT_debug_utils last */
|
||||
|
||||
/* ----------------------------------------------------------- */
|
||||
|
||||
#ifndef NDEBUG
|
||||
g_enabled_instance_extensions_names[3] = "VK_EXT_debug_utils";
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_instance()
|
||||
static rse_err_t create_instance()
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
uint8_t supported = 0;
|
||||
uint32_t extensionCount = 0;
|
||||
uint32_t layersCount = 0;
|
||||
VkApplicationInfo application_info = {};
|
||||
VkInstanceCreateInfo create_info = {};
|
||||
size_t i = 0U;
|
||||
size_t j = 0U;
|
||||
uint8_t supported = 0U;
|
||||
uint32_t extensionCount = 0U;
|
||||
uint32_t layersCount = 0U;
|
||||
VkApplicationInfo application_info = {0};
|
||||
VkInstanceCreateInfo create_info = {0};
|
||||
VkLayerProperties* layer_properties;
|
||||
VkExtensionProperties* extensions_properties;
|
||||
|
||||
vkEnumerateInstanceLayerProperties(&layersCount, NULL);
|
||||
layer_properties = malloc(sizeof(VkLayerProperties) * layersCount);
|
||||
rse_malloc(layer_properties, sizeof(VkLayerProperties) * layersCount);
|
||||
vkEnumerateInstanceLayerProperties(&layersCount, layer_properties);
|
||||
|
||||
vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, NULL);
|
||||
extensions_properties = malloc(sizeof(VkExtensionProperties) * extensionCount);
|
||||
rse_malloc(extensions_properties, sizeof(VkExtensionProperties) * extensionCount);
|
||||
vkEnumerateInstanceExtensionProperties(NULL, &extensionCount, extensions_properties);
|
||||
|
||||
#ifndef NDEBUG
|
||||
LOGD("Supported Layers");
|
||||
LOGD("Supported Layers: \n");
|
||||
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++) {
|
||||
LOGD("%s", extensions_properties[i].extensionName);
|
||||
LOGD("\t-%s\n", extensions_properties[i].extensionName);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -264,14 +261,13 @@ uint8_t create_instance()
|
||||
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*/
|
||||
for (i = 0; i < ENABLED_EXTENSIONS_COUT; ++i) {
|
||||
for(j = 0; j < extensionCount; ++j) {
|
||||
@@ -280,10 +276,11 @@ uint8_t create_instance()
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(supported == 0) {
|
||||
LOGF(vulkan_error_messages[VULKAN_EXTENSION_NOT_SUPPORTED], extensions_properties[j].extensionName);
|
||||
return VULKAN_ERROR_EXTENSION_NOT_SUPPORTED;
|
||||
if(supported == 0) {
|
||||
LOGF(vulkan_messages[VULKAN_EXTENSION_NOT_SUPPORTED], extensions_properties[j].extensionName);
|
||||
return VULKAN_ERROR_EXTENSION_NOT_SUPPORTED;
|
||||
}
|
||||
supported = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_SURFACE_CREATION_FAILED]);
|
||||
LOGF(vulkan_messages[VULKAN_SURFACE_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_SURFACE_CREATION_FAILED;
|
||||
}
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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_SUITABLE_PHYSICAL_DEVICE_FOUND
|
||||
*/
|
||||
uint8_t pick_physical_device()
|
||||
static rse_err_t pick_physical_device()
|
||||
{
|
||||
uint32_t physical_device_count = 0U;
|
||||
VkPhysicalDevice* physical_devices = NULL;
|
||||
@@ -349,11 +345,12 @@ uint8_t pick_physical_device()
|
||||
vkEnumeratePhysicalDevices(g_vulkan_instance, &physical_device_count, NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* Check for suitability */
|
||||
@@ -373,35 +370,36 @@ uint8_t pick_physical_device()
|
||||
|
||||
if (VK_NULL_HANDLE == g_vulkan_state.physical_device) {
|
||||
/* 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_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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_DEVICE_CREATION_FAILED
|
||||
*/
|
||||
uint8_t create_device()
|
||||
static rse_err_t create_device()
|
||||
{
|
||||
size_t device_queues_count = 0;
|
||||
uint32_t queue_families_property_count = 0U;
|
||||
ssize_t graphics_family_idx = -1;
|
||||
ssize_t presentation_familiy_idx = -1;
|
||||
VkQueueFamilyProperties* queue_family_properties = NULL;
|
||||
VkDeviceCreateInfo device_create_info = {};
|
||||
VkDeviceQueueCreateInfo device_queue_createinfos[2] = {}; /* TODO: Change when we want more queues */
|
||||
VkDeviceCreateInfo device_create_info = {0};
|
||||
VkDeviceQueueCreateInfo device_queue_createinfos[2] = {0};
|
||||
float* graphics_familiy_queue_priorities = NULL;
|
||||
float* presentation_familiy_queue_priorities = NULL;
|
||||
VkPhysicalDeviceFeatures2 physical_features2 = {0};
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures indexing_features = {0};
|
||||
VkBool32 bindless_supported = VK_FALSE;
|
||||
|
||||
/* Enable descriptori indexing for bindless textures */
|
||||
indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
|
||||
|
||||
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;
|
||||
if (bindless_supported == VK_FALSE) {
|
||||
LOGE("This engine requires bindless support");
|
||||
return 1;
|
||||
LOGF(vulkan_messages[VULKAN_BINDLESS_DESIGN_NOT_SUPPORTED]);
|
||||
return VULKAN_ERROR_MISSING_FEATURES_FOR_BINDLESS_DESIGN;
|
||||
}
|
||||
|
||||
/* Get information about supported queue families */
|
||||
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,
|
||||
queue_family_properties);
|
||||
|
||||
@@ -442,11 +440,9 @@ uint8_t create_device()
|
||||
if (presentSupport) {
|
||||
presentation_familiy_idx = familyIdx;
|
||||
/* 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) {
|
||||
device_queues_count++;
|
||||
}
|
||||
LOGI("Setting present family idx to %d", familyIdx);
|
||||
}
|
||||
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
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++) {
|
||||
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++) {
|
||||
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;
|
||||
@@ -497,27 +494,26 @@ uint8_t create_device()
|
||||
device_create_info.ppEnabledLayerNames = NULL;
|
||||
device_create_info.enabledExtensionCount = ENABLED_DEVICE_EXTENSIONS_COUT;
|
||||
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)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_FAILED_TO_CREATE_DEVICE]);
|
||||
LOGF(vulkan_messages[VULKAN_FAILED_TO_CREATE_DEVICE]);
|
||||
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, presentation_familiy_idx, 0, &g_present_queue);
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_memory_allocator()
|
||||
static rse_err_t create_memory_allocator()
|
||||
{
|
||||
VmaVulkanFunctions vulkan_functions = {0};
|
||||
vulkan_functions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
|
||||
@@ -531,21 +527,21 @@ uint8_t create_memory_allocator()
|
||||
allocator_create_info.pVulkanFunctions = &vulkan_functions;
|
||||
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_sync_objects()
|
||||
static rse_err_t create_sync_objects()
|
||||
{
|
||||
VkSemaphoreCreateInfo semaphore_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]) ||
|
||||
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])) {
|
||||
LOGF(vulkan_error_messages[VULKAN_SYNCOBJCTS_CREATION_FAILED]);
|
||||
LOGF(vulkan_messages[VULKAN_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();
|
||||
STATUS_CHECK(create_instance());
|
||||
#ifndef NDEBUG
|
||||
setup_debug_messenger();
|
||||
STATUS_CHECK(setup_debug_messenger());
|
||||
#endif
|
||||
STATUS_CHECK(create_surface());
|
||||
STATUS_CHECK(pick_physical_device());
|
||||
@@ -587,27 +583,28 @@ uint8_t preinit_vulkan()
|
||||
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_descriptors());
|
||||
STATUS_CHECK(create_sync_objects());
|
||||
|
||||
rse_init_time();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void draw_frame()
|
||||
rse_err_t draw_frame()
|
||||
{
|
||||
uint32_t image_index = 0U;
|
||||
VkResult result = VK_FALSE;
|
||||
VkSubmitInfo submit_info = {};
|
||||
VkSemaphore wait_semaphores[1]; //TODO: Increase when needed
|
||||
VkSubmitInfo submit_info = {0};
|
||||
VkSemaphore wait_semaphores[1];
|
||||
VkPipelineStageFlags wait_stages[1];
|
||||
VkSemaphore signal_semaphores[1];
|
||||
VkPresentInfoKHR present_info = {};
|
||||
VkPresentInfoKHR present_info = {0};
|
||||
VkSwapchainKHR swap_chains[1];
|
||||
|
||||
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) {
|
||||
recreate_swapchain();
|
||||
return;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||
// throw std::runtime_error("failed to acquire swap chain image!");
|
||||
return;
|
||||
LOGF(vulkan_messages[VULKAN_ACQUIRE_SWAPCHAIN_FAILED]);
|
||||
return VULKAN_ERROR_ACQUIRE_SWAPCHAIN_FAILED;
|
||||
}
|
||||
|
||||
update_uniform_buffers();
|
||||
@@ -633,7 +630,6 @@ void draw_frame()
|
||||
|
||||
record_command_buffer(image_index);
|
||||
|
||||
|
||||
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
|
||||
wait_semaphores[0] = g_image_available_semaphores[g_vulkan_state.current_frame];
|
||||
@@ -650,11 +646,10 @@ void draw_frame()
|
||||
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) {
|
||||
LOGF(vulkan_error_messages[VULAKN_DRAW_FAILED]);
|
||||
return;
|
||||
LOGF(vulkan_messages[VULAKN_DRAW_FAILED]);
|
||||
return VULKAN_ERROR_DRAW_FAILED;
|
||||
}
|
||||
|
||||
|
||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
|
||||
present_info.waitSemaphoreCount = 1;
|
||||
@@ -669,6 +664,8 @@ void draw_frame()
|
||||
vkQueuePresentKHR(g_present_queue, &present_info);
|
||||
|
||||
g_vulkan_state.current_frame = (g_vulkan_state.current_frame + 1) % SWAP_BUFFER_COUNT;
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
void deinit_vulkan()
|
||||
|
||||
@@ -17,35 +17,33 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "vulkan_commons.h"
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize Vulkan backend for buffers and stuff
|
||||
*
|
||||
* @param state
|
||||
* @return uint8_t 0 on success. Status code on failure
|
||||
* @return rse_err_t 0 on success. Status code on failure
|
||||
*/
|
||||
uint8_t preinit_vulkan();
|
||||
rse_err_t preinit_vulkan();
|
||||
|
||||
/**
|
||||
* @brief Initialize Vulkan backend with descriptors
|
||||
*
|
||||
* @param state
|
||||
* @return uint8_t 0 on success. Status code on failure
|
||||
* @return rse_err_t 0 on success. Status code on failure
|
||||
*/
|
||||
uint8_t init_vulkan();
|
||||
rse_err_t init_vulkan();
|
||||
|
||||
/**
|
||||
* @brief Deinitialize Vulkan backend
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
* */
|
||||
void deinit_vulkan();
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "vulkan_errors.h"
|
||||
#include "locale_vulkan.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
#include "mesh_controller.h"
|
||||
#include "rse_math.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
|
||||
*
|
||||
* @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_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;
|
||||
|
||||
buffer_size = MAX_VERTEX_BUFFER_SIZE;
|
||||
|
||||
/* 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,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
|
||||
0, /* Will not be mapped with vmaMapMemory */
|
||||
&g_vertex_buffer)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
&g_vertex_buffer));
|
||||
|
||||
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
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
static uint8_t create_index_buffer()
|
||||
static rse_err_t create_index_buffer()
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
VkDeviceSize buffer_size;
|
||||
|
||||
buffer_size = MAX_VERTEX_BUFFER_SIZE;
|
||||
|
||||
/* 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,
|
||||
0, /* Will not be mapped with vmaMapMemory */
|
||||
&g_index_buffer)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
&g_index_buffer));
|
||||
|
||||
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;
|
||||
VkDeviceSize buffer_size;
|
||||
|
||||
@@ -106,51 +104,45 @@ static uint8_t create_instance_buffers()
|
||||
|
||||
for (iter = 0; iter < MAX_MESH_NUMBER; ++iter) {
|
||||
/* 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,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE, 0, /* Will not be mapped with vmaMapMemory */
|
||||
&g_instance_buffers[iter])) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
&g_instance_buffers[iter]));
|
||||
|
||||
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_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
&g_draw_indirect_command_buffer)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
|
||||
&g_draw_indirect_command_buffer));
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
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,
|
||||
&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,
|
||||
VmaMemoryUsage memory_usage,
|
||||
const VmaAllocationCreateFlags allocation_flags,
|
||||
@@ -183,11 +175,11 @@ uint8_t create_buffer(const VkDeviceSize size,
|
||||
&buffer->buffer,
|
||||
&buffer->allocation,
|
||||
&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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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 uint16_t* indices,
|
||||
struct rse_buffer_data_t* vertex_data,
|
||||
struct rse_buffer_data_t* index_data)
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
VkDrawIndexedIndirectCommand draw_indirect_command;
|
||||
struct rse_vulkan_buffer_t staging_buffer;
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
&staging_buffer)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
&staging_buffer));
|
||||
|
||||
/* Fill staging buffer with vertex data */
|
||||
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));
|
||||
|
||||
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;
|
||||
struct rse_vulkan_buffer_t staging_buffer;
|
||||
struct rse_vulkan_buffer_t* instance_buffer = &g_instance_buffers[mesh_id];
|
||||
size_t instance_size = sizeof(struct rse_instance_data_t);
|
||||
|
||||
/* 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,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||
| VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
&staging_buffer)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_BUFFER_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_BUFFER_CREATION_FAILED;
|
||||
}
|
||||
&staging_buffer));
|
||||
|
||||
/* Copy transformation information about instance */
|
||||
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++;
|
||||
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 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
|
||||
*/
|
||||
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];
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -401,16 +389,16 @@ uint8_t record_command_buffer(uint32_t image_index)
|
||||
vkCmdEndRenderPass(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_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_index_buffer());
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#define RSE_VULKAN_BUFFERS_H
|
||||
|
||||
#include "vulkan_commons.h"
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -21,9 +23,9 @@ struct rse_buffer_data_t
|
||||
/**
|
||||
* @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
|
||||
@@ -38,9 +40,9 @@ void update_uniform_buffers();
|
||||
* @param indices Indices to add
|
||||
* @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
|
||||
* @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 uint16_t* indices,
|
||||
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 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
|
||||
*
|
||||
* @param vulkan_state
|
||||
* @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.
|
||||
@@ -87,10 +89,10 @@ void destroy_buffers();
|
||||
* @param memory_usage memory usage flags (mostly VMA_MEMORY_USAGE_AUTO)
|
||||
* @param allocation_flags VMA allocation flags
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_buffer(const VkDeviceSize size,
|
||||
rse_err_t create_buffer(const VkDeviceSize size,
|
||||
VkBufferUsageFlags buffer_usage,
|
||||
VmaMemoryUsage memory_usage,
|
||||
const VmaAllocationCreateFlags allocation_flags,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "locale_vulkan.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
#include "vulkan_errors.h"
|
||||
#include "vulkan_commons.h"
|
||||
#include "rse_vulkan_image.h"
|
||||
@@ -12,16 +13,13 @@
|
||||
VkDescriptorPool gDescriptorPool;
|
||||
VkDescriptorPool gDescriptorPool_bindless;
|
||||
|
||||
static uint8_t create_descriptor_pool();
|
||||
static uint8_t create_descriptor_sets();
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_descriptor_pool()
|
||||
static rse_err_t create_descriptor_pool()
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[2] = {};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
@@ -38,7 +36,7 @@ uint8_t create_descriptor_pool()
|
||||
|
||||
pool_info.maxSets = (uint32_t)(SWAP_BUFFER_COUNT);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -47,19 +45,19 @@ uint8_t create_descriptor_pool()
|
||||
pool_info.pPoolSizes = &pool_sizes[1];
|
||||
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
uint8_t create_descriptor_sets()
|
||||
static rse_err_t create_descriptor_sets()
|
||||
{
|
||||
uint32_t max_binding = MAX_BINDLESS_RESOURCES - 1;
|
||||
VkDescriptorSetLayout layouts[SWAP_BUFFER_COUNT] = {
|
||||
@@ -90,12 +88,12 @@ uint8_t create_descriptor_sets()
|
||||
allocInfo_bindless.descriptorSetCount = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -138,12 +136,12 @@ uint8_t create_descriptor_sets()
|
||||
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_sets());
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#define RSE_VULKAN_DESCRIPTORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
|
||||
#define MAX_BINDLESS_RESOURCES 16536
|
||||
|
||||
@@ -9,14 +11,13 @@
|
||||
* @brief Create descriptors
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @param vulkan_state
|
||||
*/
|
||||
void destroy_descriptors();
|
||||
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
#ifndef VULKAN_ERRORS_H
|
||||
#define VULKAN_ERRORS_H
|
||||
|
||||
/* Macro for checking status of function execution in initVulkan. Created to avoid writing boilerplate code */
|
||||
#define STATUS_CHECK(FUNC) \
|
||||
status = FUNC; \
|
||||
if (VULKAN_ERROR_NO_ERROR != status) { \
|
||||
return status; \
|
||||
}
|
||||
#define RSE_VULKAN_MODULE_ID 0x0300U
|
||||
|
||||
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_EXTENSION_NOT_SUPPORTED,
|
||||
VULKAN_ERROR_INSTANCE_INIT_FAILED,
|
||||
VULKAN_ERROR_NO_PHYSICAL_DEVICE_FOUND,
|
||||
VULKAN_ERROR_NO_SUITABLE_PHYSICAL_DEVICE_FOUND,
|
||||
VULKAN_ERROR_MISSING_FEATURES_FOR_BINDLESS_DESIGN,
|
||||
VULKAN_ERROR_QUEUE_NOT_SUPPORTED,
|
||||
VULKAN_ERROR_DEVICE_CREATION_FAILED,
|
||||
VULKAN_ERROR_ALLOCATOR_CREATION_FAILED,
|
||||
@@ -31,6 +27,7 @@ enum VULKAN_ERROR
|
||||
VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED,
|
||||
VULKAN_ERROR_RENDERPASS_CREATION_FAILED,
|
||||
VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED,
|
||||
VULKAN_ERROR_FORMAT_NOT_FOUND,
|
||||
VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED,
|
||||
VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED,
|
||||
VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED,
|
||||
@@ -38,6 +35,12 @@ enum VULKAN_ERROR
|
||||
VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED,
|
||||
VULKAN_ERROR_RECORD_COMMAND_BUFFER_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
|
||||
+198
-221
@@ -3,6 +3,7 @@
|
||||
#include "locale_vulkan.h"
|
||||
#include "utilities/file_utils.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/rse_errors_common.h"
|
||||
#include "vulkan_errors.h"
|
||||
#include "mesh_controller.h"
|
||||
#include "rse_vulkan_image.h"
|
||||
@@ -31,35 +32,10 @@ VkShaderModule g_shader_modules[SHADER_MODULES_COUNT];
|
||||
|
||||
|
||||
const char* g_shader_paths[] = {
|
||||
/* TODO: When changing to release and install, move those files*/
|
||||
"../graphics/shaders/shader.vert.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()
|
||||
{
|
||||
VkVertexInputBindingDescription binding_description;
|
||||
@@ -98,11 +74,10 @@ static VkVertexInputAttributeDescription* get_attribute_descriptions()
|
||||
* @brief Creates shader module
|
||||
*
|
||||
* @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 = {};
|
||||
|
||||
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.pCode = (const uint32_t*)(binary_data);
|
||||
|
||||
if (VK_SUCCESS != vkCreateShaderModule(g_vulkan_state.device, &create_info, NULL, &shader_module)) {
|
||||
LOGF(vulkan_error_messages[VULKAN_SHADER_UNABLE_TO_CREATE_SHADER]);
|
||||
// TODO: Add error handling
|
||||
return shader_module;
|
||||
if (VK_SUCCESS != vkCreateShaderModule(g_vulkan_state.device, &create_info, NULL, shader_module)) {
|
||||
LOGF(vulkan_messages[VULKAN_SHADER_UNABLE_TO_CREATE_SHADER]);
|
||||
return VULKAN_ERROR_SHADER_CREATION_FAILED;
|
||||
}
|
||||
|
||||
return shader_module;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_swapchain()
|
||||
static rse_err_t create_swapchain()
|
||||
{
|
||||
VkSwapchainCreateInfoKHR create_info;
|
||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
||||
@@ -150,22 +124,22 @@ uint8_t create_swapchain()
|
||||
create_info.flags = 0U;
|
||||
create_info.surface = g_vulkan_state.surface;
|
||||
create_info.minImageCount = SWAP_BUFFER_COUNT + 1;
|
||||
create_info.imageFormat = IMAGE_FORMAT; /* TODO: Check for supported formats */
|
||||
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; /* TODO: Check for supported color space */
|
||||
create_info.imageFormat = IMAGE_FORMAT;
|
||||
create_info.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
create_info.imageExtent = g_vulkan_state.swapchain_extent;
|
||||
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.queueFamilyIndexCount = 1U;
|
||||
create_info.pQueueFamilyIndices = g_vulkan_state.queue_family_indices;
|
||||
create_info.preTransform = physical_device_surface_capabilities.currentTransform;
|
||||
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.oldSwapchain = VK_NULL_HANDLE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -174,15 +148,15 @@ uint8_t create_swapchain()
|
||||
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);
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
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;
|
||||
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
uint8_t create_render_pass()
|
||||
static rse_err_t create_render_pass()
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
VkAttachmentDescription attachments[2] = {};
|
||||
VkAttachmentDescription color_attachment = {};
|
||||
VkAttachmentReference color_attachment_ref = {};
|
||||
@@ -230,7 +205,8 @@ uint8_t create_render_pass()
|
||||
VkAttachmentReference depth_attachment_ref = {};
|
||||
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.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
@@ -280,19 +256,19 @@ uint8_t create_render_pass()
|
||||
renderpass_info.pDependencies = &dependency;
|
||||
|
||||
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_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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_bindless = {};
|
||||
@@ -328,7 +304,7 @@ uint8_t create_descriptor_set_layout()
|
||||
layout_info.pBindings = &bindings[0];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -338,19 +314,19 @@ uint8_t create_descriptor_set_layout()
|
||||
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) {
|
||||
LOGF(vulkan_error_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]);
|
||||
LOGF(vulkan_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]);
|
||||
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
|
||||
}
|
||||
|
||||
return VULKAN_ERROR_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
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};
|
||||
VkPipelineLayoutCreateInfo create_info = {};
|
||||
@@ -363,161 +339,24 @@ uint8_t create_pipeline_layout()
|
||||
create_info.pPushConstantRanges = NULL;
|
||||
|
||||
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_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);
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates shader stages from hardcoded shader paths. Changes input
|
||||
*
|
||||
* @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_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;
|
||||
long buffer_size;
|
||||
VkShaderModule vertex_shader_module;
|
||||
@@ -529,18 +368,16 @@ static uint8_t fill_shader_stages(VkPipelineShaderStageCreateInfo* shader_stages
|
||||
buffer = malloc(buffer_size);
|
||||
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);
|
||||
|
||||
rse_read_file(g_shader_paths[FRAGMENTS], &buffer_size, NULL);
|
||||
buffer = malloc(buffer_size);
|
||||
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);
|
||||
|
||||
//TODO: Shader creation might have failed. Add error handling
|
||||
|
||||
/* Vertex Shader Pipeline Stage */
|
||||
vert_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
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[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
|
||||
*/
|
||||
void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state)
|
||||
static void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_state)
|
||||
{
|
||||
VkDynamicState* dynamic_states;
|
||||
/*
|
||||
@@ -601,7 +438,7 @@ void fill_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -611,7 +448,7 @@ void free_dynamic_pipeline_state_info(VkPipelineDynamicStateCreateInfo* dynamic_
|
||||
*
|
||||
* @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 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[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;
|
||||
|
||||
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
|
||||
*/
|
||||
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((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
|
||||
*/
|
||||
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->pNext = NULL;
|
||||
input_assembly->flags = 0U;
|
||||
input_assembly->topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; // TODO: Change to _STRIP
|
||||
input_assembly->primitiveRestartEnable = VK_FALSE; /* If I want to break lines during _STRIP,
|
||||
* I must set this to VK_TRUE */
|
||||
input_assembly->topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
input_assembly->primitiveRestartEnable = VK_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -694,7 +530,7 @@ void fill_input_assembly_info(VkPipelineInputAssemblyStateCreateInfo* input_asse
|
||||
*
|
||||
* @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));
|
||||
VkRect2D* scissor = malloc(sizeof(VkRect2D));
|
||||
@@ -723,7 +559,7 @@ void fill_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state)
|
||||
*
|
||||
* @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((VkRect2D*)viewport_state->pScissors);
|
||||
@@ -734,7 +570,7 @@ void free_viewport_state_info(VkPipelineViewportStateCreateInfo* viewport_state)
|
||||
*
|
||||
* @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->pNext = NULL;
|
||||
@@ -756,7 +592,7 @@ void fill_rasterization_info(VkPipelineRasterizationStateCreateInfo* rasterizer)
|
||||
*
|
||||
* @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->pNext = NULL;
|
||||
@@ -774,7 +610,7 @@ void fill_multisampling_state_info(VkPipelineMultisampleStateCreateInfo* multisa
|
||||
*
|
||||
* @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));
|
||||
|
||||
@@ -806,14 +642,155 @@ void fill_color_blend_state_info(VkPipelineColorBlendStateCreateInfo* color_blen
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
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_image_views());
|
||||
|
||||
@@ -2,35 +2,32 @@
|
||||
#define RSE_VULKAN_PIPELINE_H
|
||||
|
||||
#include "vulkan_commons.h"
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Create a graphics pipeline
|
||||
*
|
||||
* @param vulkan_state
|
||||
* @return uint8_t
|
||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||
*/
|
||||
uint8_t create_pipeline(void);
|
||||
rse_err_t create_pipeline(void);
|
||||
|
||||
/**
|
||||
* @brief Cleanup swapchain
|
||||
*
|
||||
* @param vulkan_state
|
||||
*/
|
||||
void cleanup_swapchain(void);
|
||||
|
||||
/**
|
||||
* @brief Recreates swapchain
|
||||
*
|
||||
* @param vulkan_state
|
||||
*/
|
||||
void recreate_swapchain(void);
|
||||
|
||||
/**
|
||||
* @brief Destroy all vulkan pipeline objects
|
||||
*
|
||||
* @param vulkan_state
|
||||
*/
|
||||
void destroy_pipeline(void);
|
||||
|
||||
|
||||
+5
-12
@@ -13,16 +13,9 @@
|
||||
|
||||
#include "locale_window.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/rse_errors_common.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;
|
||||
|
||||
/**
|
||||
@@ -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 */
|
||||
if (GLFW_TRUE != glfwInit())
|
||||
@@ -89,17 +82,17 @@ uint16_t window_init()
|
||||
|
||||
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)) {
|
||||
glfwPollEvents();
|
||||
draw_frame();
|
||||
}
|
||||
|
||||
return WINDOW_ERROR_NO_ERROR;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
void window_terminate()
|
||||
|
||||
@@ -17,23 +17,26 @@
|
||||
/* Vulkan header MUST be included before glfw */
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "rse_window_errors.h"
|
||||
#include "utilities/rse_commons.h"
|
||||
|
||||
/**
|
||||
* @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_WINDOW_NOT_CREATED
|
||||
*
|
||||
*/
|
||||
uint16_t window_init();
|
||||
rse_err_t window_init();
|
||||
|
||||
/**
|
||||
* @brief Main window loop
|
||||
*
|
||||
* @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
|
||||
|
||||
Reference in new issue
Block a user