From bd05c03a12ce00f6e050ce7858f3ae2f165963c9 Mon Sep 17 00:00:00 2001 From: Piotr Krygier Date: Thu, 19 Jun 2025 18:49:25 +0200 Subject: [PATCH] Continue working on pipeline --- .clangd | 14 +- CMakeLists.txt | 1 + CMakeUserPresets.json | 2 +- conanfile.txt | 6 + graphics/CMakeLists.txt | 17 ++- graphics/rse_graphics.h | 2 +- graphics/shaders/solid_objects.frag | 2 +- graphics/src/descriptor_builder.c | 116 +++++++++++++-- graphics/src/descriptor_builder.h | 49 ++++++- graphics/src/graphics_context.h | 4 +- graphics/src/pipeline_builder.c | 20 +-- graphics/src/pipeline_builder.h | 4 +- graphics/src/rse_graphics.c | 45 ++++-- graphics/src/vulkan_base.c | 18 +-- graphics/src/vulkan_buffers.c | 218 ++++++++++++---------------- graphics/src/vulkan_buffers.h | 13 +- graphics/src/vulkan_descriptors.c | 163 --------------------- graphics/src/vulkan_descriptors.h | 26 ---- graphics/src/vulkan_errors.h | 1 - graphics/src/vulkan_image.c | 16 +- graphics/src/vulkan_image.h | 8 +- graphics/src/vulkan_swapchain.c | 3 +- red_scarf_engine/src/main.c | 17 ++- utilities/CMakeLists.txt | 4 +- utilities/errors_common.h | 2 + utilities/file_utils.h | 3 + utilities/linked_list.h | 20 +-- utilities/src/file_utils.c | 82 ++++++++++- 28 files changed, 453 insertions(+), 423 deletions(-) delete mode 100644 graphics/src/vulkan_descriptors.c delete mode 100644 graphics/src/vulkan_descriptors.h diff --git a/.clangd b/.clangd index 0f7bb3a3..f6e67f3f 100644 --- a/.clangd +++ b/.clangd @@ -1,2 +1,14 @@ CompileFlags: - Add: -ferror-limit=1000 + Add: [ + "-ferror-limit=0", + "-Wall", + "-Wpedantic", + "-Werror", + "-Wno-gnu-statement-expression", + "-I/home/nonadmin/workspace/RedScarfEngine/", + "-I/home/nonadmin/workspace/RedScarfEngine/graphics", + "-I/home/nonadmin/workspace/RedScarfEngine/utilites", + "-I/home/nonadmin/workspace/RedScarfEngine/third_party/include", + "-I/home/nonadmin/.conan2/p/stb19b77fb56ffd7/p/include/" + ] + diff --git a/CMakeLists.txt b/CMakeLists.txt index e324e603..4670afa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ project("RedScarfEngine" set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") add_subdirectory(red_scarf_engine) add_subdirectory(utilities) diff --git a/CMakeUserPresets.json b/CMakeUserPresets.json index 02793486..945b382c 100644 --- a/CMakeUserPresets.json +++ b/CMakeUserPresets.json @@ -4,6 +4,6 @@ "conan": {} }, "include": [ - "build\\CMakePresets.json" + "build/CMakePresets.json" ] } \ No newline at end of file diff --git a/conanfile.txt b/conanfile.txt index d7885a80..0a620f0d 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -1,9 +1,15 @@ [requires] vulkan-headers/1.4.309.0 +vulkan-loader/1.4.309.0 +libgettext/0.22 glfw/3.4 freetype/2.13.3 +stb/cci.20240531 +sdl/3.2.14 [generators] CMakeDeps CMakeToolchain +[options] +sdl/*:wayland=False diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index f8beb55a..31ab8eb7 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -1,8 +1,12 @@ find_package(VulkanHeaders REQUIRED) +find_package(VulkanLoader REQUIRED) +# find_package(vulkan-validationlayers) find_package(glfw3 REQUIRED) find_package(freetype REQUIRED) +find_package(stb REQUIRED) +find_package(SDL3 REQUIRED) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -g") add_library(graphics SHARED) @@ -11,9 +15,8 @@ ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/third_party/include/ ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} - ${vma_INCLUDE_DIR} - ${glfw3_INCLUDE_DIR} - ${stb_INCLUDE_DIR} +${stb_INCLUDE_DIR} +${freetype_INCLUDE_DIR} ) target_sources(graphics PRIVATE @@ -21,10 +24,10 @@ src/vma_port.cpp src/window.c src/vulkan_base.c src/vulkan_commands.c -src/vulkan_buffers.c src/rse_graphics.c src/math.c src/mesh_controller.c +src/vulkan_buffers.c src/vulkan_commons.c src/vulkan_image.c src/vulkan_render_pass.c @@ -37,6 +40,10 @@ src/descriptor_builder.c target_link_libraries(graphics PUBLIC utilities vulkan-headers::vulkan-headers + Vulkan::Loader + # vulkan-validationlayers::vulkan-validationlayers glfw Freetype::Freetype + stb::stb + sdl::sdl ) diff --git a/graphics/rse_graphics.h b/graphics/rse_graphics.h index 899de480..94e07e08 100644 --- a/graphics/rse_graphics.h +++ b/graphics/rse_graphics.h @@ -19,7 +19,7 @@ rse_err_t rse_graphics_init(struct rse_graphics_context_t** context); * * @return rse_err_t RSE_ERROR_NO_ERROR on success */ -rse_err_t rse_graphics_run(struct rse_graphics_context_t* context); +int rse_graphics_run(void* arg); /** diff --git a/graphics/shaders/solid_objects.frag b/graphics/shaders/solid_objects.frag index 21b022a4..7b4cada2 100644 --- a/graphics/shaders/solid_objects.frag +++ b/graphics/shaders/solid_objects.frag @@ -1,7 +1,7 @@ #version 450 #extension GL_EXT_nonuniform_qualifier : enable -layout(set = 1, binding = 1) uniform sampler2D texSampler[]; +layout(set = 0, binding = 1) uniform sampler2D texSampler[]; layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoord; diff --git a/graphics/src/descriptor_builder.c b/graphics/src/descriptor_builder.c index ffb47bed..58f9bc99 100644 --- a/graphics/src/descriptor_builder.c +++ b/graphics/src/descriptor_builder.c @@ -11,9 +11,11 @@ #include "descriptor_builder.h" +#include #include #include "src/graphics_context.h" +#include "src/vulkan_commons.h" #include "utilities/commons.h" #include "utilities/errors_common.h" #include "utilities/linked_list.h" @@ -30,7 +32,7 @@ struct descriptor_t VkDescriptorType type; uint32_t descriptor_count; VkShaderStageFlags shader_stages; - VkSampler immutable_sampler; + VkSampler* immutable_sampler; }; RSE_LINKED_LIST_DEFINE(descriptor_set_list_t, struct descriptor_t); @@ -40,6 +42,7 @@ struct descriptor_set_handle_t VkDescriptorSet descriptor_sets; VkDescriptorPool descriptor_pool; VkDescriptorSetLayout descriptor_sets_layout; + struct descriptor_set_list_t* descriptor_set_list; }; /* FIXME: When new descriptors are introduced to Vulkan, this enum has to be @@ -66,8 +69,38 @@ enum descriptor_type_id_t DESCRIPTOR_TYPE_ID_MAX_ENUM, }; -rse_err_t descriptor_add_set(struct descriptor_set_list_t* descriptor_set_list, uint32_t binding, VkDescriptorType type, - uint32_t descriptor_count, VkShaderStageFlags shader_stages, VkSampler sampler) +rse_err_t descriptor_initialize_handle(struct descriptor_set_handle_t **descriptor_set_handle) +{ + if (NULL != *descriptor_set_handle) { + LOGE(_("Desciptor already initialized\n")); + + return RSE_ERROR_INVALID_PARAM; + } + + rse_malloc(*descriptor_set_handle, sizeof(struct descriptor_set_handle_t)); + (*descriptor_set_handle)->descriptor_set_list = NULL; + + return RSE_ERROR_NO_ERROR; +} + +rse_err_t descriptor_free_handle(struct descriptor_set_handle_t **descriptor_set_handle) +{ + if (NULL == *descriptor_set_handle) { + LOGE(_("Provided NULL handle\n")); + + return RSE_ERROR_INVALID_PARAM; + } + + RSE_LINKED_LIST_CLEAR((*descriptor_set_handle)->descriptor_set_list); + rse_free(*descriptor_set_handle); + + *descriptor_set_handle = NULL; + + return RSE_ERROR_NO_ERROR; +} + +rse_err_t descriptor_add_set(struct descriptor_set_handle_t* descriptor_set_handle, uint32_t binding, VkDescriptorType type, + uint32_t descriptor_count, VkShaderStageFlags shader_stages, VkSampler* sampler) { struct descriptor_t descriptor_sets = {.binding = binding, .type = type, @@ -75,13 +108,12 @@ rse_err_t descriptor_add_set(struct descriptor_set_list_t* descriptor_set_list, .shader_stages = shader_stages, .immutable_sampler = sampler}; - RSE_LINKED_LIST_PUSH_BACK(descriptor_set_list, descriptor_sets); + RSE_LINKED_LIST_PUSH_BACK(descriptor_set_handle->descriptor_set_list, descriptor_sets); return RSE_ERROR_NO_ERROR; } -rse_err_t descriptors_build(struct graphics_context_t* context, struct descriptor_set_list_t* descriptors, - struct descriptor_set_handle_t* descriptor_set_handle) +rse_err_t descriptors_build(struct graphics_context_t* context, struct descriptor_set_handle_t* descriptor_set_handle) { size_t iterator = 0U; size_t pool_size_count = 0U; @@ -104,8 +136,20 @@ rse_err_t descriptors_build(struct graphics_context_t* context, struct descripto return RSE_ERROR_NULL_POINTER; } + if (NULL == descriptor_set_handle) { + LOGF(_("Descriptor set handle is null.\n")); + + return RSE_ERROR_NULL_POINTER; + } + + if (RSE_LINKED_LIST_IS_EMPTY(descriptor_set_handle->descriptor_set_list)) { + LOGF(_("Provided empty descriptors list\n")); + + return RSE_ERROR_NULL_POINTER; + } + iterator = 0U; - RSE_LINKED_LIST_FOREACH(descriptors, descriptor) + RSE_LINKED_LIST_FOREACH(descriptor_set_handle->descriptor_set_list, descriptor) { switch (descriptor->data.type) { case VK_DESCRIPTOR_TYPE_SAMPLER: @@ -195,6 +239,7 @@ rse_err_t descriptors_build(struct graphics_context_t* context, struct descripto layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layout_create_info.bindingCount = iterator; layout_create_info.pBindings = layout_bindings; + if (VK_SUCCESS != vkCreateDescriptorSetLayout(context->device, &layout_create_info, NULL, &set_layout)) { LOGF(_("Failed to create descriptor sets layout\n")); return VULKAN_ERROR_DESCRIPTOR_SET_LAYOUT_CREATION_FAILED; @@ -204,7 +249,7 @@ rse_err_t descriptors_build(struct graphics_context_t* context, struct descripto * What I'm doing here is calculating minimum viable number of pool max sets. This is a bit tricky, as * (unintuitively) we have to select the MINIMUM number of sets, not maximum. This makes sense, but is difficult to * wrap headr around */ - RSE_LINKED_LIST_FOREACH(descriptors, descriptor) + RSE_LINKED_LIST_FOREACH(descriptor_set_handle->descriptor_set_list, descriptor) { switch (descriptor->data.type) { case VK_DESCRIPTOR_TYPE_SAMPLER: @@ -308,10 +353,10 @@ rse_err_t descriptors_build(struct graphics_context_t* context, struct descripto } /* Allocate descriptors from the pool */ - alloc_info.descriptorPool = &descriptor_pool; + alloc_info.descriptorPool = descriptor_pool; alloc_info.descriptorSetCount = pool_max_sets; /* TODO: Always allocating maximum number of sets? This might get weird */ - alloc_info.pSetLayouts = set_layout; + alloc_info.pSetLayouts = &set_layout; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; if (VK_SUCCESS != vkAllocateDescriptorSets(context->device, &alloc_info, &descriptor_sets)) { @@ -323,7 +368,56 @@ rse_err_t descriptors_build(struct graphics_context_t* context, struct descripto descriptor_set_handle->descriptor_sets = descriptor_sets; descriptor_set_handle->descriptor_sets_layout = set_layout; + context->descriptor_sets = descriptor_set_handle; + return RSE_ERROR_NO_ERROR; } -rse_err_t descriptor_get_layouts() \ No newline at end of file +rse_err_t descriptor_get_layout(struct descriptor_set_handle_t* descriptor_set_handle, + VkDescriptorSetLayout* descriptor_sets_layout) +{ + if (NULL == descriptor_set_handle->descriptor_sets_layout) { + LOGF(_("Requested descriptor set layout is NULL\n")); + + return RSE_ERROR_NULL_POINTER; + } + + *descriptor_sets_layout = descriptor_set_handle->descriptor_sets_layout; + + return RSE_ERROR_NO_ERROR; +} + +rse_err_t descriptor_get_vkhandle(struct descriptor_set_handle_t* descriptor_set_handle, VkDescriptorSet* descriptor_set) +{ + if (NULL == descriptor_set_handle) { + LOGF(_("Provided handle is NULL\n")); + + return RSE_ERROR_NULL_POINTER; + } + + *descriptor_set = descriptor_set_handle->descriptor_sets; + + return RSE_ERROR_NO_ERROR; +} + +rse_err_t descriptor_attach_buffer(struct graphics_context_t* context, struct descriptor_set_handle_t* descriptor_set_handle, struct vulkan_buffer_t* buffer, uint32_t binding, VkDescriptorType type) +{ + VkDescriptorBufferInfo buffer_info = {0}; + VkWriteDescriptorSet write_set = {0}; + + buffer_info.buffer = buffer->buffer; + buffer_info.offset = 0U; + buffer_info.range = buffer->allocated_size; + + write_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_set.pBufferInfo = &buffer_info; + write_set.dstSet = descriptor_set_handle->descriptor_sets; + write_set.dstBinding = binding; + write_set.dstArrayElement = 0U; + write_set.descriptorType = type; + write_set.descriptorCount = 1; + + vkUpdateDescriptorSets(context->device, 1U, &write_set, 0, NULL); + + return RSE_ERROR_NO_ERROR; +} diff --git a/graphics/src/descriptor_builder.h b/graphics/src/descriptor_builder.h index e0e8a170..07f8267c 100644 --- a/graphics/src/descriptor_builder.h +++ b/graphics/src/descriptor_builder.h @@ -12,13 +12,33 @@ #ifndef DESCRIPTOR_BUILDER_H #define DESCRIPTOR_BUILDER_H +#include + +#include "src/graphics_context.h" + struct descriptor_set_handle_t; struct descriptor_set_list_t; +/** + * @brief Initialize new descriptor set handle + * + * @param descriptor_set_handle Handle to initialize + * #return RSE_ERROR_NO_ERROR on success + */ +rse_err_t descriptor_initialize_handle(struct descriptor_set_handle_t **descriptor_set_handle); + +/** + * @brief Destroy descritptor set handle + * + * @param descriptor_set_handle Handle to destroy + * @return RSE_ERROR_NO_ERROR on succes + */ +rse_err_t descriptor_free_handle(struct descriptor_set_handle_t **descriptor_set_handle); + /** * @brief Add descriptor set to provided list * - * @param descriptor_set_list List to be filled + * @param descriptor_set_handle Handle for given descriptor set * @param binding Descriptors binding * @param type Type of descriptors * @param descriptor_count Number of descriptors in this set @@ -26,18 +46,35 @@ struct descriptor_set_list_t; * @param sampler If descriptor set is a sampler, provide it here * @return rse_err_t RSE_ERROR_NO_ERROR on success, error code on failure */ -rse_err_t descriptor_add_set(struct descriptor_set_list_t* descriptor_set_list, uint32_t binding, VkDescriptorType type, - uint32_t descriptor_count, VkShaderStageFlags shader_stages, VkSampler sampler); +rse_err_t descriptor_add_set(struct descriptor_set_handle_t* descriptor_set_handle, uint32_t binding, VkDescriptorType type, + uint32_t descriptor_count, VkShaderStageFlags shader_stages, VkSampler* sampler); /** * @brief Allocate descriptor sets from provided list. The data will be stored in opaque descriptor handle * * @param context Graphics context - * @param descriptors List of descriptors to build descriptor handle from. * @param descriptor_set_handle Opaque descriptor handle object. * @return rse_err_t RSE_ERROR_NO_ERROR on success, error code on failure */ -rse_err_t descriptors_build(struct graphics_context_t* context, struct descriptor_set_list_t* descriptors, - struct descriptor_set_handle_t* descriptor_set_handle); +rse_err_t descriptors_build(struct graphics_context_t* context, struct descriptor_set_handle_t* descriptor_set_handle); + +/** + * @brief Return descriptor set layouts from descritptor handle + * + * @param descriptor_set_handle Handle for descriptor set + * @return rse_err_t RSE_ERROR_NO_ERROR on success + */ +rse_err_t descriptor_get_layout(struct descriptor_set_handle_t* descriptor_set_handle, + VkDescriptorSetLayout* descritptor_sets_layout); + +/** + * @brief Get VkDescriptorSet from descriptor handle + * + * @param descriptor_set_handle_t Handle to get VkDescriptorSet from + * @return rse_err_t RSE_ERROR_NO_ERROR on success + */ +rse_err_t descriptor_get_vkhandle(struct descriptor_set_handle_t* descriptor_set_handle, VkDescriptorSet* descriptor_set); + +rse_err_t descriptor_attach_buffer(struct graphics_context_t* context, struct descriptor_set_handle_t* descriptor_set_handle, struct vulkan_buffer_t* buffer, uint32_t binding, VkDescriptorType type); #endif // !DESCRIPTOR_BUILDER_H diff --git a/graphics/src/graphics_context.h b/graphics/src/graphics_context.h index b558620f..c72f3901 100644 --- a/graphics/src/graphics_context.h +++ b/graphics/src/graphics_context.h @@ -114,13 +114,11 @@ struct graphics_context_t VkSemaphore render_finished_semaphores[SWAP_BUFFER_COUNT]; VkFence in_flight_fences[SWAP_BUFFER_COUNT]; struct pipeline_internal_t pipelines_data; -#ifndef NDEBUG + struct descriptor_set_handle_t* descriptor_sets; VkDebugUtilsMessengerEXT debug_messenger; -#endif // !NDEBUG bool is_framebuffer_resized; // TODO: Consider moving this to heap uint32_t current_frame; uint32_t queue_family_indices[1]; - struct vulkan_buffer_t uniform_buffers[SWAP_BUFFER_COUNT]; /* GPU visible buffer */ size_t vertex_offset; struct vulkan_buffer_t vertex_buffer; diff --git a/graphics/src/pipeline_builder.c b/graphics/src/pipeline_builder.c index e72d93fd..073ad40b 100644 --- a/graphics/src/pipeline_builder.c +++ b/graphics/src/pipeline_builder.c @@ -14,7 +14,7 @@ #include #include -#include "descriptor_builder.h" +#include "src/descriptor_builder.h" #include "src/graphics_context.h" #include "utilities/commons.h" #include "utilities/errors_common.h" @@ -23,7 +23,6 @@ #include "utilities/localization.h" #include "vulkan/vulkan_core.h" #include "vulkan_errors.h" -#include "vulkan_image.h" #define MAX_BINDLESS_RESOURCES 1000 @@ -58,6 +57,7 @@ struct pipeline_t struct shader_attribute_list_t* shader_attributes; struct dynamic_state_list_t* dynamic_states; struct required_dynamic_states_t required_dynamic_states; + struct descriptor_set_handle_t* descriptor_sets; }; /** @@ -210,17 +210,19 @@ static rse_err_t pipeline_add_depth_stencil(struct pipeline_t* pipeline) * VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED */ static rse_err_t create_pipeline_layout(struct graphics_context_t* context, - struct descriptors_set_handle_t* descriptor_set_handle) + struct descriptor_set_handle_t* descriptor_set_handle) { - uint32_t descriptor_set_layouts_count = 0; - VkDescriptorSetLayout descriptor_set_layouts = VK_NULL_HANDLE; + rse_err_t status = RSE_ERROR_NO_ERROR; + VkDescriptorSetLayout descriptor_sets_layouts = VK_NULL_HANDLE; + + STATUS_CHECK(descriptor_get_layout(descriptor_set_handle, &descriptor_sets_layouts)); VkPipelineLayoutCreateInfo create_info = {0}; create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; create_info.pNext = NULL; create_info.flags = 0U; - create_info.setLayoutCount = context->pipelines_data.descriptor_set_layouts_count; - create_info.pSetLayouts = context->pipelines_data.descriptor_set_layouts; + create_info.setLayoutCount = 1; // FIXME: Make sure we can enable more than one layout + create_info.pSetLayouts = &descriptor_sets_layouts; create_info.pushConstantRangeCount = 0U; create_info.pPushConstantRanges = NULL; @@ -385,7 +387,7 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline, const return RSE_ERROR_NO_ERROR; } -rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_list_t* pipelines_infos_list) +rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_list_t* pipelines_infos_list, struct descriptor_set_handle_t* descriptor_set_handles) { assert(NULL != context); assert(NULL != pipelines_infos_list); @@ -397,7 +399,7 @@ rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_in context->pipelines_data.pipelines_count = pipelines_count; - STATUS_CHECK(create_pipeline_layout(context)); + STATUS_CHECK(create_pipeline_layout(context, descriptor_set_handles)); rse_malloc(pipeline_infos, sizeof(VkGraphicsPipelineCreateInfo) * pipelines_count); diff --git a/graphics/src/pipeline_builder.h b/graphics/src/pipeline_builder.h index c7676e93..8982abf0 100644 --- a/graphics/src/pipeline_builder.h +++ b/graphics/src/pipeline_builder.h @@ -15,6 +15,7 @@ #include #include +#include "descriptor_builder.h" #include "graphics_context.h" #include "utilities/commons.h" #include "utilities/linked_list.h" @@ -85,9 +86,10 @@ rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, const VkDynami * * param[in/out] context Graphics context handle * @param[in] pipeline Pipelines list to build + * @param[in] descriptor_set_handle Filled handle with descriptor sets * @return RSE_SUCCESS on success, error code otherwise */ -rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_list_t* pipelines); +rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_list_t* pipelines, struct descriptor_set_handle_t* descriptor_set_handle); /** * @brief Add pipeline to list of pipelines diff --git a/graphics/src/rse_graphics.c b/graphics/src/rse_graphics.c index 1048e367..64eac095 100644 --- a/graphics/src/rse_graphics.c +++ b/graphics/src/rse_graphics.c @@ -1,16 +1,20 @@ #include "rse_graphics.h" - +#include +#include #include "descriptor_builder.h" #include "graphics_context.h" #include "math.h" #include "mesh_controller.h" #include "pipeline_builder.h" +#include "src/vulkan_buffers.h" #include "utilities/commons.h" #include "utilities/errors_common.h" +#include "utilities/file_utils.h" #include "utilities/localization.h" #include "utilities/logger.h" #include "vulkan_base.h" #include "vulkan_commons.h" +#include "vulkan_image.h" #include "window.h" struct rse_graphics_context_t @@ -41,15 +45,13 @@ rse_err_t rse_graphics_init(struct rse_graphics_context_t** context) void rse_graphics_test_function(struct rse_graphics_context_t* rse_context) { + char curr_path[4096] = {0}; struct graphics_context_t* context = rse_context->context; - // rse_err_t status = RSE_ERROR_NO_ERROR; uint16_t tex_id_2 = 0; - size_t ubo_index = 0; - size_t sampler_index = 0; struct pipeline_t* pipeline = NULL; - struct descriptor_set_list_t* descriptor_set_list; - struct descriptor_set_handle_t* descriptor_set_handle; + struct descriptor_set_handle_t* descriptor_set_handle = NULL; struct pipeline_infos_list_t* pipeline_infos = NULL; + struct vulkan_buffer_t ubo = {}; // status = load_texture_from_file("../../test_image.jpg", &tex_id_2); // if (status != RSE_ERROR_NO_ERROR) { @@ -92,9 +94,12 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context) /* Initialize pipeline */ pipeline_builder_init(&pipeline); - pipeline_add_shader_stage(context, pipeline, "../graphics/shaders/shader.vert.num", VK_SHADER_STAGE_VERTEX_BIT); - pipeline_add_shader_stage(context, pipeline, "../graphics/shaders/solid_objects.frag.num", - VK_SHADER_STAGE_FRAGMENT_BIT); + get_curr_path(curr_path, 4096); + strncat(curr_path, "shader.vert.num", 4095); + pipeline_add_shader_stage(context, pipeline, curr_path, VK_SHADER_STAGE_VERTEX_BIT); + get_curr_path(curr_path, 4096); + strncat(curr_path, "solid_objects.frag.num", 4095); + pipeline_add_shader_stage(context, pipeline, curr_path, VK_SHADER_STAGE_FRAGMENT_BIT); pipeline_add_vertex_input_binding(pipeline, 0, sizeof(struct vertex_t), VK_VERTEX_INPUT_RATE_VERTEX); pipeline_add_vertex_input_binding(pipeline, 1, sizeof(struct vertex_t), VK_VERTEX_INPUT_RATE_INSTANCE); @@ -115,25 +120,33 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context) VkSampler sampler = VK_NULL_HANDLE; - create_sampler(context, sampler); + sampler_create(context, &sampler); - descriptor_add_set(descriptor_set_list, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, NULL); - descriptor_add_set(descriptor_set_list, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, - VK_SHADER_STAGE_FRAGMENT_BIT, sampler); + descriptor_initialize_handle(&descriptor_set_handle); - descriptors_build(context, descriptor_set_list, descriptor_set_handle); + descriptor_add_set(descriptor_set_handle, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, NULL); + descriptor_add_set(descriptor_set_handle, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, + VK_SHADER_STAGE_FRAGMENT_BIT, &sampler); + + descriptors_build(context, descriptor_set_handle); add_pipeline(context, pipeline, &pipeline_infos); - build_pipelines(context, pipeline_infos); + pipelines_build(context, pipeline_infos, descriptor_set_handle); + + create_uniform_buffer(context, &ubo); + update_uniform_buffers(context, &ubo); + + descriptor_attach_buffer(context, descriptor_set_handle, &ubo, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); // TODO: Add a shader for text rendering // pipeline_add_shader_stage("../graphics/shaders/on_screen_text.frag.num", VK_SHADER_STAGE_FRAGMENT_BIT); } -rse_err_t rse_graphics_run(struct rse_graphics_context_t* rse_context) +int rse_graphics_run(void* arg) { rse_err_t status = RSE_ERROR_NO_ERROR; + struct rse_graphics_context_t* rse_context = (struct rse_graphics_context_t*)arg; struct graphics_context_t* context = rse_context->context; STATUS_CHECK(run_vulkan(context)); diff --git a/graphics/src/vulkan_base.c b/graphics/src/vulkan_base.c index 1464d3e5..4a36ce2a 100644 --- a/graphics/src/vulkan_base.c +++ b/graphics/src/vulkan_base.c @@ -36,7 +36,6 @@ #define APPLICATION_NAME "RedScarfEngine PoC" #define ENGINE_NAME "RedScarf Engine" -#ifndef NDEBUG /** * @brief Calback for debug messenger * @@ -145,8 +144,6 @@ static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMesse } } -#endif /* DEBUG */ - /** * @brief Create the Vulkan Instance object * @@ -178,18 +175,15 @@ static rse_err_t create_instance(VkInstance* instance) #elif defined(_WIN32) || defined(WIN32) "VK_KHR_win32_surface", #endif /* _WIN32 || WIN32 */ -#ifndef NDEBUG "VK_EXT_debug_utils", -#endif /* NDEBUG */ }; -#ifndef NDEBUG uint32_t enabled_instance_extensions_count = 4; uint32_t enabled_instance_layers_count = 1; const char* enabled_instance_layers_names[] = { "VK_LAYER_KHRONOS_validation", }; -#else +#if 0 uint32_t enabled_instance_extensions_count = 3; uint32_t enabled_instance_layers_count = 0; const char* enabled_instance_layers_names[] = {}; @@ -261,11 +255,7 @@ static rse_err_t create_instance(VkInstance* instance) create_info.flags = 0U; create_info.pApplicationInfo = &application_info; create_info.enabledLayerCount = enabled_instance_layers_count; -#ifndef NDEBUG create_info.ppEnabledLayerNames = enabled_instance_layers_names; -#else - create_info.ppEnabledLayerNames = NULL; -#endif create_info.enabledExtensionCount = enabled_instance_extensions_count; create_info.ppEnabledExtensionNames = enabled_instance_extensions_names; @@ -546,9 +536,7 @@ rse_err_t init_vulkan(struct graphics_context_t* context) rse_err_t status = RSE_ERROR_NO_ERROR; STATUS_CHECK(create_instance(&context->instance)); -#ifndef NDEBUG STATUS_CHECK(setup_debug_messenger(context->instance, &context->debug_messenger)); -#endif STATUS_CHECK(create_surface(context->instance, context->window_handle, &context->surface)); STATUS_CHECK(pick_physical_device(context->instance, &context->physical_device)); STATUS_CHECK(create_device(context)); @@ -599,7 +587,7 @@ rse_err_t draw_frame(struct graphics_context_t* context) return VULKAN_ERROR_ACQUIRE_SWAPCHAIN_FAILED; } - update_uniform_buffers(context); + // update_uniform_buffers(context); /* Only reset the fence if we are submitting work */ vkResetFences(context->device, 1, &context->in_flight_fences[context->current_frame]); @@ -672,9 +660,7 @@ void deinit_vulkan(struct graphics_context_t* context) vmaDestroyAllocator(context->allocator); vkDestroyDevice(context->device, NULL); -#ifndef NDEBUG DestroyDebugUtilsMessengerEXT(context->instance, context->debug_messenger, NULL); -#endif vkDestroySurfaceKHR(context->instance, context->surface, NULL); vkDestroyInstance(context->instance, NULL); } diff --git a/graphics/src/vulkan_buffers.c b/graphics/src/vulkan_buffers.c index 0f295d47..1fdc3ce7 100644 --- a/graphics/src/vulkan_buffers.c +++ b/graphics/src/vulkan_buffers.c @@ -1,18 +1,19 @@ #include "vulkan_buffers.h" -#include "src/graphics_context.h" -#include "src/vulkan_commons.h" -#include "utilities/commons.h" -#include "utilities/linked_list.h" -#include "vulkan_errors.h" -#include "utilities/logger.h" -#include "utilities/localization.h" -#include "utilities/errors_common.h" -#include "math.h" -#include "vulkan_commands.h" - #include #include +#include + +#include "math.h" +#include "src/descriptor_builder.h" +#include "src/graphics_context.h" +#include "src/vulkan_commons.h" +#include "utilities/commons.h" +#include "utilities/errors_common.h" +#include "utilities/localization.h" +#include "utilities/logger.h" +#include "vulkan_commands.h" +#include "vulkan_errors.h" #define MAX_VERTEX_BUFFER_SIZE 33554432 /* 32 MB*/ @@ -23,7 +24,8 @@ * @param dst Destination buffer * @param size Size of buffer to copy */ -static void copy_buffer(struct graphics_context_t* context, VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset) +static void copy_buffer(struct graphics_context_t* context, VkBuffer src, VkBuffer dst, VkDeviceSize size, + VkDeviceSize dest_offset) { /* Vulkan buffers can only be copied using command buffers */ VkBufferCopy copy_region = {0}; @@ -40,7 +42,6 @@ static void copy_buffer(struct graphics_context_t* context, VkBuffer src, VkBuff end_single_time_comands(context, command_buffer); } - /** * @brief Create a buffer holding all vertex data * @@ -58,10 +59,9 @@ static rse_err_t create_vertex_buffer(struct graphics_context_t* context) /* Create Vertex Buffer*/ STATUS_CHECK(create_buffer(context, 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 */ - &context->vertex_buffer)); + 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 */ + &context->vertex_buffer)); context->vertex_buffer.allocated_size = 0; return RSE_ERROR_NO_ERROR; @@ -82,10 +82,10 @@ static rse_err_t create_index_buffer(struct graphics_context_t* context) buffer_size = MAX_VERTEX_BUFFER_SIZE; /* Create Index Buffer*/ - STATUS_CHECK(create_buffer(context, 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 */ - &context->index_buffer)); + STATUS_CHECK(create_buffer(context, 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 */ + &context->index_buffer)); context->index_buffer.allocated_size = 0; return RSE_ERROR_NO_ERROR; @@ -108,49 +108,38 @@ static rse_err_t create_instance_buffers(struct graphics_context_t* context) for (iter = 0; iter < MAX_MESH_NUMBER; ++iter) { /* Create Instance Buffer */ STATUS_CHECK(create_buffer(context, 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 */ - &context->instance_buffers[iter])); + 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 */ + &context->instance_buffers[iter])); context->instance_buffers[iter].allocated_size = 0; - } - STATUS_CHECK(create_buffer(context, 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, - &context->draw_indirect_command_buffer)); + STATUS_CHECK(create_buffer( + context, 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, + &context->draw_indirect_command_buffer)); return RSE_ERROR_NO_ERROR; } -/** - * @brief Create a Uniform Buffers - * - * @param context Graphics context handle - * @return rse_err_t RSE_ERROR_NO_ERROR on success. - */ -static rse_err_t create_uniform_buffer(struct graphics_context_t* context) +rse_err_t create_uniform_buffer(struct graphics_context_t* context, struct vulkan_buffer_t* buffer) { rse_err_t status = RSE_ERROR_NO_ERROR; - VkDeviceSize buffer_size = sizeof(struct uniform_buffer_object_t); + VkDeviceSize buffer_size = + sizeof(struct uniform_buffer_object_t); // TODO: Change later. Uniform buffer is not only MVP - for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) { - STATUS_CHECK(create_buffer(context, 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, - &context->uniform_buffers[i])); - } + STATUS_CHECK(create_buffer( + context, 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, buffer)); return RSE_ERROR_NO_ERROR; } -rse_err_t create_buffer(struct graphics_context_t* context, const VkDeviceSize size, - VkBufferUsageFlags buffer_usage, - VmaMemoryUsage memory_usage, - const VmaAllocationCreateFlags allocation_flags, - struct vulkan_buffer_t* buffer) +rse_err_t create_buffer(struct graphics_context_t* context, const VkDeviceSize size, VkBufferUsageFlags buffer_usage, + VmaMemoryUsage memory_usage, const VmaAllocationCreateFlags allocation_flags, + struct vulkan_buffer_t* buffer) { VkBufferCreateInfo vertex_buffer_info = {0}; VmaAllocationCreateInfo create_info = {0}; @@ -173,16 +162,14 @@ rse_err_t create_buffer(struct graphics_context_t* context, const VkDeviceSize s create_info.pUserData = VK_NULL_HANDLE; create_info.priority = 0.0f; - if (VK_SUCCESS != vmaCreateBuffer(context->allocator, - &vertex_buffer_info, - &create_info, - &buffer->buffer, - &buffer->allocation, - &buffer->allocation_info)) { + if (VK_SUCCESS != vmaCreateBuffer(context->allocator, &vertex_buffer_info, &create_info, &buffer->buffer, + &buffer->allocation, &buffer->allocation_info)) { LOGF(_("Failed to create a vertex buffer\n")); return VULKAN_ERROR_BUFFER_CREATION_FAILED; } + buffer->allocated_size = size; + return RSE_ERROR_NO_ERROR; } @@ -191,8 +178,7 @@ void destroy_buffer(struct graphics_context_t* context, struct vulkan_buffer_t* vmaDestroyBuffer(context->allocator, buffer->buffer, buffer->allocation); } - -void update_uniform_buffers(struct graphics_context_t* context) +void update_uniform_buffers(struct graphics_context_t* context, const struct vulkan_buffer_t* buffer) { struct uniform_buffer_object_t ubo = {0}; struct vec3_t eye = {0}; @@ -213,18 +199,13 @@ void update_uniform_buffers(struct graphics_context_t* context) ubo.model = math_rotate(math_uniform_mat4(), math_deg_to_radians(0.0f), rotation_vec); ubo.view = math_look_at(&eye, ¢er, &up); - ubo.proj = math_perspective(fovy, - context->swapchain_extent.width / (float)context->swapchain_extent.height, - z_near, - z_far); - memcpy(context->uniform_buffers[context->current_frame].allocation_info.pMappedData, &ubo, sizeof(ubo)); + ubo.proj = math_perspective(fovy, context->swapchain_extent.width / (float)context->swapchain_extent.height, z_near, + z_far); + memcpy(buffer->allocation_info.pMappedData, &ubo, sizeof(ubo)); } -rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, - const struct vertex_t* vertices, - const uint16_t* indices, - struct buffer_data_t* vertex_data, - struct buffer_data_t* index_data) +rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, const struct vertex_t* vertices, + const uint16_t* indices, struct buffer_data_t* vertex_data, struct buffer_data_t* index_data) { rse_err_t status = RSE_ERROR_NO_ERROR; VkDrawIndexedIndirectCommand draw_indirect_command; @@ -235,20 +216,15 @@ rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, struct vulkan_buffer_t* index_buffer = &context->index_buffer; /* Creating staging buffer*/ - STATUS_CHECK(create_buffer(context, 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)); + STATUS_CHECK(create_buffer( + context, 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)); /* Fill staging buffer with vertex data */ memset(staging_buffer.allocation_info.pMappedData, 0, MAX_VERTEX_BUFFER_SIZE); memcpy(staging_buffer.allocation_info.pMappedData, vertices, vertices_size); - copy_buffer(context, staging_buffer.buffer, - context->vertex_buffer.buffer, - vertices_size, - context->vertex_buffer.allocated_size); + copy_buffer(context, staging_buffer.buffer, context->vertex_buffer.buffer, vertices_size, + context->vertex_buffer.allocated_size); vertex_data->buffer_offset = context->vertex_offset; context->vertex_offset += vertex_data->count; @@ -257,10 +233,7 @@ rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, /* Fill staging buffer with index data */ memset(staging_buffer.allocation_info.pMappedData, 0, indices_size); memcpy(staging_buffer.allocation_info.pMappedData, indices, indices_size); - copy_buffer(context, staging_buffer.buffer, - index_buffer->buffer, - indices_size, - index_buffer->allocated_size); + copy_buffer(context, staging_buffer.buffer, index_buffer->buffer, indices_size, index_buffer->allocated_size); index_data->buffer_offset = index_buffer->allocated_size; index_buffer->allocated_size += indices_size; @@ -272,12 +245,15 @@ rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, draw_indirect_command.vertexOffset = vertex_data->buffer_offset; draw_indirect_command.firstInstance = 0; - memcpy(context->draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); + memcpy((char*)context->draw_indirect_command_buffer.allocation_info.pMappedData + + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), + &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); return RSE_ERROR_NO_ERROR; } -rse_err_t update_mesh_instances(struct graphics_context_t* context, uint16_t mesh_id, struct instance_data_t* instance_data) +rse_err_t update_mesh_instances(struct graphics_context_t* context, uint16_t mesh_id, + struct instance_data_t* instance_data) { rse_err_t status = RSE_ERROR_NO_ERROR; VkDrawIndexedIndirectCommand draw_indirect_command; @@ -286,27 +262,27 @@ rse_err_t update_mesh_instances(struct graphics_context_t* context, uint16_t mes size_t instance_size = sizeof(struct instance_data_t); /* Creating staging buffer*/ - STATUS_CHECK(create_buffer(context, instance_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)); + STATUS_CHECK(create_buffer( + context, instance_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)); /* Copy transformation information about instance */ memcpy(staging_buffer.allocation_info.pMappedData, instance_data, instance_size); - copy_buffer(context, staging_buffer.buffer, - instance_buffer->buffer, - instance_size, - instance_buffer->allocated_size); + copy_buffer(context, staging_buffer.buffer, instance_buffer->buffer, instance_size, + instance_buffer->allocated_size); destroy_buffer(context, &staging_buffer); instance_buffer->allocated_size += instance_size; - memcpy(&draw_indirect_command, context->draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), sizeof(VkDrawIndexedIndirectCommand)); + memcpy(&draw_indirect_command, + (char*)context->draw_indirect_command_buffer.allocation_info.pMappedData + + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), + sizeof(VkDrawIndexedIndirectCommand)); draw_indirect_command.instanceCount++; - memcpy(context->draw_indirect_command_buffer.allocation_info.pMappedData + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); + memcpy((char*)context->draw_indirect_command_buffer.allocation_info.pMappedData + + (mesh_id * sizeof(VkDrawIndexedIndirectCommand)), + &draw_indirect_command, sizeof(VkDrawIndexedIndirectCommand)); return RSE_ERROR_NO_ERROR; } @@ -322,17 +298,17 @@ rse_err_t update_mesh_instances(struct graphics_context_t* context, uint16_t mes rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t image_index) { VkCommandBuffer command_buffer = context->command_buffers[context->current_frame]; - VkDescriptorSet* descriptor_sets = NULL; - VkCommandBufferBeginInfo begin_info = {}; - VkRenderPassBeginInfo render_pass_info = {}; - VkViewport viewport = {}; - VkRect2D scissor = {}; + VkCommandBufferBeginInfo begin_info = {0}; + VkRenderPassBeginInfo render_pass_info = {0}; + VkViewport viewport = {0}; + VkRect2D scissor = {0}; VkDeviceSize offsets[] = {0}; - VkClearValue clear_values[2] = {}; //For color and depth stencil + VkClearValue clear_values[2] = {0}; // For color and depth stencil + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; size_t i = 0U; - - RSE_LINKED_LIST_TO_ARRAY(context->pipelines_data.descriptor_sets, descriptor_sets); + // FIXME: Do something with this list + // RSE_LINKED_LIST_TO_ARRAY(context->pipelines_data.descriptor_sets, descriptor_sets); clear_values[0].color.float32[0] = 0.0f; clear_values[0].color.float32[1] = 0.0f; @@ -345,6 +321,12 @@ rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t ima begin_info.flags = 0; begin_info.pInheritanceInfo = NULL; + if (RSE_ERROR_NO_ERROR != descriptor_get_vkhandle(context->descriptor_sets, &descriptor_set)) { + LOGF(_("Failed to get vk handle from descriptor set handle\n")); + + return VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED; + } + if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) { LOGF(_("Failed to start recording command buffer\n")); return VULKAN_ERROR_RECORD_COMMAND_BEGIN_FAILED; @@ -378,19 +360,17 @@ rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t ima vkCmdBindVertexBuffers(command_buffer, 0, 1, &context->vertex_buffer.buffer, offsets); vkCmdBindIndexBuffer(command_buffer, context->index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipeline_layout, 0, 2, - descriptor_sets, 0, NULL); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipeline_layout, 0, + 1, &descriptor_set, 0, NULL); for (i = 0; i < MAX_MESH_NUMBER; ++i) { VkBuffer instance_buffer = {context->instance_buffers[i].buffer}; vkCmdBindVertexBuffers(command_buffer, 1, 1, &instance_buffer, offsets); - vkCmdDrawIndexedIndirect(command_buffer, - context->draw_indirect_command_buffer.buffer, - sizeof(VkDrawIndexedIndirectCommand) * i, - 1, - 0); /* Can be 0 since we are not doing multiple draws each loop */ + vkCmdDrawIndexedIndirect(command_buffer, context->draw_indirect_command_buffer.buffer, + sizeof(VkDrawIndexedIndirectCommand) * i, 1, + 0); /* Can be 0 since we are not doing multiple draws each loop */ } vkCmdEndRenderPass(command_buffer); @@ -410,7 +390,6 @@ rse_err_t create_buffers(struct graphics_context_t* context) STATUS_CHECK(create_vertex_buffer(context)); STATUS_CHECK(create_index_buffer(context)); STATUS_CHECK(create_instance_buffers(context)); - STATUS_CHECK(create_uniform_buffer(context)); return status; } @@ -420,22 +399,17 @@ void reset_command_buffer(struct graphics_context_t* context) vkResetCommandBuffer(context->command_buffers[context->current_frame], /*VkCommandBufferResetFlagBits*/ 0); } - void destroy_buffers(struct graphics_context_t* context) { size_t i = 0U; - for (i = 0; i < SWAP_BUFFER_COUNT; ++i) { - vmaDestroyBuffer(context->allocator, - context->uniform_buffers[i].buffer, - context->uniform_buffers[i].allocation); - } - vmaDestroyBuffer(context->allocator, context->vertex_buffer.buffer, context->vertex_buffer.allocation); vmaDestroyBuffer(context->allocator, context->index_buffer.buffer, context->index_buffer.allocation); - vmaDestroyBuffer(context->allocator, context->draw_indirect_command_buffer.buffer, context->draw_indirect_command_buffer.allocation); + vmaDestroyBuffer(context->allocator, context->draw_indirect_command_buffer.buffer, + context->draw_indirect_command_buffer.allocation); - for(i = 0; i < MAX_MESH_NUMBER; ++i) { - vmaDestroyBuffer(context->allocator, context->instance_buffers[i].buffer, context->instance_buffers[i].allocation); + for (i = 0; i < MAX_MESH_NUMBER; ++i) { + vmaDestroyBuffer(context->allocator, context->instance_buffers[i].buffer, + context->instance_buffers[i].allocation); } } diff --git a/graphics/src/vulkan_buffers.h b/graphics/src/vulkan_buffers.h index d0c19cd9..9e5672c0 100644 --- a/graphics/src/vulkan_buffers.h +++ b/graphics/src/vulkan_buffers.h @@ -18,13 +18,22 @@ */ rse_err_t create_buffers(struct graphics_context_t* context); +/** + * @brief Create a Uniform Buffers + * + * @param context Graphics context handle + * @param buffer Buffer handle to hold new buffer + * @return rse_err_t RSE_ERROR_NO_ERROR on success. + */ +rse_err_t create_uniform_buffer(struct graphics_context_t* context, struct vulkan_buffer_t* buffer); + /** * @brief Update uniform buffers * * @param context Graphics context handle - * + * @param buffer Uniform buffer to update */ -void update_uniform_buffers(struct graphics_context_t* context); +void update_uniform_buffers(struct graphics_context_t* context, const struct vulkan_buffer_t* ubo); /** * @brief Add vertices and indices to vulkan buffers diff --git a/graphics/src/vulkan_descriptors.c b/graphics/src/vulkan_descriptors.c deleted file mode 100644 index 58296149..00000000 --- a/graphics/src/vulkan_descriptors.c +++ /dev/null @@ -1,163 +0,0 @@ -#include "vulkan_descriptors.h" - -#include "utilities/errors_common.h" -#include "utilities/localization.h" -#include "utilities/logger.h" -#include "vulkan_commons.h" -#include "vulkan_errors.h" -#include "vulkan_image.h" - -/** - * @brief Create a Descriptor Pool - * - * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors: - * VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED - */ -static rse_err_t create_descriptor_pool(struct graphics_context_t* context) -{ - VkDescriptorPoolSize pool_sizes[2] = {}; - VkDescriptorPoolCreateInfo pool_info = {}; - - pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - pool_sizes[0].descriptorCount = (uint32_t)(SWAP_BUFFER_COUNT); - - pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - pool_sizes[1].descriptorCount = MAX_BINDLESS_RESOURCES; - - pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - pool_info.poolSizeCount = 1; - pool_info.pPoolSizes = &pool_sizes[0]; - - pool_info.maxSets = (uint32_t)(SWAP_BUFFER_COUNT); - if (vkCreateDescriptorPool(context->device, &pool_info, NULL, - &context->descriptor_pool) != VK_SUCCESS) { - LOGF(_("Failed to create descriptor pool\n")); - return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED; - } - - pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT; - pool_info.maxSets = MAX_BINDLESS_RESOURCES * 2; - pool_info.pPoolSizes = &pool_sizes[1]; - - if (vkCreateDescriptorPool(context->device, &pool_info, NULL, - &context->descriptor_pool_bindless) != - VK_SUCCESS) { - LOGF(_("Failed to create descriptor pool\n")); - return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED; - } - - return RSE_ERROR_NO_ERROR; -} - -/** - * @brief Create a Descriptor Sets - * - * @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors: - * VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED */ -static rse_err_t create_descriptor_sets(struct graphics_context_t* context) -{ - uint32_t max_binding = MAX_BINDLESS_RESOURCES - 1; - VkDescriptorSetLayout layouts[SWAP_BUFFER_COUNT] = { - context->descriptor_set_layout, context->descriptor_set_layout}; - VkDescriptorSetLayout layouts_bindless[SWAP_BUFFER_COUNT] = { - context->descriptor_set_layout_bindless, - context->descriptor_set_layout_bindless}; - VkDescriptorSetAllocateInfo allocInfo = {}; - VkDescriptorSetAllocateInfo allocInfo_bindless = {}; - VkDescriptorSetVariableDescriptorCountAllocateInfoEXT count_info = {}; - - count_info.sType = - VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT; - count_info.descriptorSetCount = 1; - count_info.pDescriptorCounts = &max_binding; - - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = context->descriptor_pool; - allocInfo.descriptorSetCount = (uint32_t)(SWAP_BUFFER_COUNT); - allocInfo.pSetLayouts = layouts; - - allocInfo_bindless = allocInfo; - allocInfo_bindless.descriptorPool = context->descriptor_pool_bindless; - allocInfo_bindless.pSetLayouts = layouts_bindless; - allocInfo_bindless.pNext = &count_info; - allocInfo_bindless.descriptorSetCount = 1; - - if (vkAllocateDescriptorSets(context->device, &allocInfo, - context->descriptor_sets) != VK_SUCCESS) { - LOGF(_("Failed to allocate descriptor sets\n")); - return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED; - } - - if (vkAllocateDescriptorSets(context->device, &allocInfo_bindless, - &context->descriptor_sets_bindless) != - VK_SUCCESS) { - LOGF(_("Failed to allocate descriptor sets\n")); - return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED; - } - - for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) { - VkDescriptorBufferInfo buffer_info = {}; - VkWriteDescriptorSet descriptor_writes[2] = {}; - VkDescriptorImageInfo image_infos[RSE_MAX_IMAGE_COUNT] = {}; - size_t image_iterator = 0U; - size_t image_info_iterator = 0U; - - buffer_info.buffer = context->uniform_buffers[i].buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(struct uniform_buffer_object_t); - - for (image_iterator = 0U; image_iterator < RSE_MAX_IMAGE_COUNT; - ++image_iterator) { - if (image_exists(context, image_iterator)) { - image_infos[image_info_iterator].imageLayout = - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_infos[image_info_iterator].imageView = - context->swapchain_image_views[image_iterator]; - image_infos[image_info_iterator].sampler = context->sampler; - image_info_iterator++; - } - } - - descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[0].dstSet = context->descriptor_sets[i]; - descriptor_writes[0].dstBinding = 0; - descriptor_writes[0].dstArrayElement = 0; - descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_writes[0].descriptorCount = 1; - descriptor_writes[0].pBufferInfo = &buffer_info; - - descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_writes[1].dstSet = context->descriptor_sets_bindless; - descriptor_writes[1].dstBinding = 1; - descriptor_writes[1].dstArrayElement = 0; - descriptor_writes[1].descriptorType = - VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptor_writes[1].descriptorCount = image_info_iterator; - descriptor_writes[1].pImageInfo = image_infos; - - vkUpdateDescriptorSets(context->device, 2, descriptor_writes, 0, NULL); - } - - return RSE_ERROR_NO_ERROR; -} - -rse_err_t create_descriptors(struct graphics_context_t* context) -{ - rse_err_t status = RSE_ERROR_NO_ERROR; - - STATUS_CHECK(create_descriptor_pool(context)); - STATUS_CHECK(create_descriptor_sets(context)); - - return status; -} - -void destroy_descriptors(struct graphics_context_t* context) -{ - vkDestroyDescriptorPool(context->device, context->descriptor_pool, NULL); - vkDestroyDescriptorPool(context->device, context->descriptor_pool_bindless, - NULL); - vkDestroyDescriptorSetLayout(context->device, - context->descriptor_set_layout, NULL); - vkDestroyDescriptorSetLayout(context->device, - context->descriptor_set_layout_bindless, NULL); -} diff --git a/graphics/src/vulkan_descriptors.h b/graphics/src/vulkan_descriptors.h deleted file mode 100644 index 267d04d7..00000000 --- a/graphics/src/vulkan_descriptors.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef VULKAN_DESCRIPTORS_H -#define VULKAN_DESCRIPTORS_H - -#include "utilities/commons.h" -#include "graphics_context.h" - - -#define MAX_BINDLESS_RESOURCES 16536 - -/** - * @brief Create descriptors - * - * @param context Graphics context handle - * @param vulkan_state - * @return rse_err_t RSE_ERROR_NO_ERROR on success - */ -rse_err_t create_descriptors(struct graphics_context_t* context); - -/** - * @brief Destroy all descriptors - * - * @param context Graphics context handle - */ -void destroy_descriptors(struct graphics_context_t* context); - -#endif /* VULKAN_DESCRIPTORS_H */ diff --git a/graphics/src/vulkan_errors.h b/graphics/src/vulkan_errors.h index 99f8ebbc..8d46932f 100644 --- a/graphics/src/vulkan_errors.h +++ b/graphics/src/vulkan_errors.h @@ -59,7 +59,6 @@ enum vulkan_error_t VULKAN_ERROR_UNKNOWN_DESCRIPTOR_TYPE, VULKAN_ERROR_DESCRIPTOR_SET_LAYOUT_CREATION_FAILED, VULKAN_ERROR_DESCRIPTOR_SET_CREATION_FAILED, - VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED, }; #endif diff --git a/graphics/src/vulkan_image.c b/graphics/src/vulkan_image.c index 75fabf02..ea112e02 100644 --- a/graphics/src/vulkan_image.c +++ b/graphics/src/vulkan_image.c @@ -4,7 +4,6 @@ #include "utilities/commons.h" #include "utilities/errors_common.h" -#include "utilities/file_utils.h" #include "utilities/localization.h" #include "utilities/logger.h" #include "vulkan/vulkan_core.h" @@ -17,18 +16,12 @@ #include #include -#include "stb/stb_image.h" +#include "stb_image.h" #define IMAGE_TAKEN 1U #define IMAGE_FREE 0U -/** - * @brief Create a sampler object for texture sampling - * - * @param[in/out] context Graphics context to create sampler in - * @return RSE_ERROR_NO_ERROR on success, error code otherwise - */ -rse_err_t create_sampler(struct graphics_context_t* context, VkSampler sampler) +rse_err_t sampler_create(struct graphics_context_t* context, VkSampler* sampler) { VkSamplerCreateInfo create_info = {0}; @@ -51,7 +44,7 @@ rse_err_t create_sampler(struct graphics_context_t* context, VkSampler sampler) create_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; create_info.unnormalizedCoordinates = VK_FALSE; - if (VK_SUCCESS != vkCreateSampler(context->device, &create_info, NULL, &sampler)) { + if (VK_SUCCESS != vkCreateSampler(context->device, &create_info, NULL, sampler)) { LOGF("Failed to create image view"); return 1; } @@ -446,7 +439,8 @@ void destroy_textures(struct graphics_context_t* context) { size_t i = 0U; - vkDestroySampler(context->device, context->sampler, NULL); + //FIXME: This is not working for now + // vkDestroySampler(context->device, context->sampler, NULL); for (i = 0U; i < RSE_MAX_IMAGE_COUNT; ++i) { if (context->texture_images[i].id_taken == IMAGE_TAKEN) { diff --git a/graphics/src/vulkan_image.h b/graphics/src/vulkan_image.h index 2ea2b7a8..d5d6153f 100644 --- a/graphics/src/vulkan_image.h +++ b/graphics/src/vulkan_image.h @@ -83,6 +83,12 @@ void destroy_color_resource(struct graphics_context_t* context); rse_err_t create_depth_resources(struct graphics_context_t* context); void destroy_depth_resource(struct graphics_context_t* context); -rse_err_t create_sampler(struct graphics_context_t* context, VkSampler sampler); +/** + * @brief Create a sampler object for texture sampling + * + * @param[in/out] context Graphics context to create sampler in + * @return RSE_ERROR_NO_ERROR on success, error code otherwise + */ +rse_err_t sampler_create(struct graphics_context_t* context, VkSampler* sampler); #endif /* TEXTURE_H */ diff --git a/graphics/src/vulkan_swapchain.c b/graphics/src/vulkan_swapchain.c index 3676c2fa..ab93bd89 100644 --- a/graphics/src/vulkan_swapchain.c +++ b/graphics/src/vulkan_swapchain.c @@ -7,7 +7,6 @@ #include "utilities/localization.h" #include "vulkan/vulkan_core.h" #include "vulkan_commons.h" -#include "vulkan_descriptors.h" #include "vulkan_errors.h" #include "vulkan_image.h" #include "vulkan_swapchain.h" @@ -132,7 +131,7 @@ static rse_err_t create_framebuffers(struct graphics_context_t* context) context->depth_image.image_view, context->swapchain_image_views[i]}; - VkFramebufferCreateInfo framebufferInfo = {}; + VkFramebufferCreateInfo framebufferInfo = {0}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = context->render_pass; framebufferInfo.attachmentCount = 3; diff --git a/red_scarf_engine/src/main.c b/red_scarf_engine/src/main.c index cbbbc0da..2bcbeaf4 100644 --- a/red_scarf_engine/src/main.c +++ b/red_scarf_engine/src/main.c @@ -1,22 +1,29 @@ #include "graphics/rse_graphics.h" -#include "utilities/task.h" #include "utilities/errors_common.h" +#include "utilities/localization.h" +#include "utilities/logger.h" +#include "SDL3/SDL_thread.h" int main(int argc, char** argv) { rse_err_t status = RSE_ERROR_NO_ERROR; - thread_t graphics_task; struct rse_graphics_context_t* context = NULL; + SDL_Thread* graphics_task = NULL; (void)argc; (void)argv; STATUS_CHECK(rse_graphics_init(&context)); rse_graphics_test_function(context); - create_task(&graphics_task, (thread_worker_t)rse_graphics_run, context); - task_join(&graphics_task); - task_exit(); + graphics_task = SDL_CreateThread(rse_graphics_run, "graphics_task", (void*) context); + + if (NULL == graphics_task) { + LOGE(_("Failed to create graphics task")); + exit(1); + } + + SDL_WaitThread(graphics_task, NULL); return 0; } diff --git a/utilities/CMakeLists.txt b/utilities/CMakeLists.txt index f9dcdb4d..ca9f1947 100644 --- a/utilities/CMakeLists.txt +++ b/utilities/CMakeLists.txt @@ -1,3 +1,5 @@ +find_package(Intl) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror") add_library(utilities SHARED) @@ -12,4 +14,4 @@ target_sources(utilities PRIVATE ) target_link_libraries(utilities PRIVATE - pthread) + Intl::Intl) diff --git a/utilities/errors_common.h b/utilities/errors_common.h index 0d09426d..3315d3c5 100644 --- a/utilities/errors_common.h +++ b/utilities/errors_common.h @@ -26,6 +26,8 @@ enum common_error_t RSE_ERROR_NULL_POINTER, RSE_ERROR_ALREADY_INITIALIZED, RSE_COMMON_ERROR_MALLLOC_FAILED, + RSE_ERROR_INVALID_PARAM, + RSE_ERROR_INTERNAL_ERROR, }; #define ERRORS_COMMON_H diff --git a/utilities/file_utils.h b/utilities/file_utils.h index e0998c3b..dc052002 100644 --- a/utilities/file_utils.h +++ b/utilities/file_utils.h @@ -2,6 +2,7 @@ #define FILE_UTILS_H #include +#include "utilities/commons.h" /** * @brief Reads file and puts its content into char buffer. If NULL is provided as buffer, than just bytes_count @@ -15,5 +16,7 @@ void read_file(const char* file_path, size_t* bytes_count, char* buffer); void write_to_file(const char* file_name, size_t bytes_count, char* buffer); +rse_err_t get_curr_path(char* path, size_t max_path_length); + #endif /* FILE_UTILS_H */ diff --git a/utilities/linked_list.h b/utilities/linked_list.h index 946369d0..c3e40fd7 100644 --- a/utilities/linked_list.h +++ b/utilities/linked_list.h @@ -30,21 +30,21 @@ } #define RSE_LINKED_LIST_PUSH_FRONT(list, value) \ - typeof(list) new_node = NULL; \ + __typeof__(list) new_node = NULL; \ rse_malloc(new_node, sizeof(*(list))); \ new_node->data = value; \ new_node->next = list; \ list = new_node #define RSE_LINKED_LIST_PUSH_BACK(list, value) \ - typeof(list) new_node = NULL; \ + __typeof__((list)) new_node = NULL; \ rse_malloc(new_node, sizeof(*(list))); \ new_node->data = value; \ new_node->next = NULL; \ if (list == NULL) { \ list = new_node; \ } else { \ - typeof(list) current = list; \ + __typeof__(list) current = list; \ while (current->next != NULL) { \ current = current->next; \ } \ @@ -53,7 +53,7 @@ #define RSE_LINKED_LIST_POP_FRONT(list) \ if (list != NULL) { \ - typeof(list) temp = list; \ + __typeof__(list) temp = list; \ list = list->next; \ rse_free(temp); \ } @@ -64,7 +64,7 @@ rse_free(list); \ list = NULL; \ } else { \ - typeof(list) *current = list; \ + __typeof__(list) *current = list; \ while (current->next->next != NULL) { \ current = current->next; \ } \ @@ -78,7 +78,7 @@ #define RSE_LINKED_LIST_BACK(list) \ if (list != NULL) { \ - typeof(list) *current = list; \ + __typeof__(list) *current = list; \ while (current->next != NULL) { \ current = current->next; \ } \ @@ -91,7 +91,7 @@ #define RSE_LINKED_LIST_SIZE(list) \ ({ \ int size = 0; \ - typeof(list) current = list; \ + __typeof__(list) current = list; \ while (current != NULL) { \ size++; \ current = current->next; \ @@ -101,17 +101,17 @@ #define RSE_LINKED_LIST_CLEAR(list) \ while (list != NULL) { \ - typeof(list) temp = list; \ + __typeof__(list) temp = list; \ list = list->next; \ rse_free(temp); \ } #define RSE_LINKED_LIST_FOREACH(list, i) \ - for (typeof(list) i = list; i != NULL; i = i->next) + for (__typeof__(list) i = list; i != NULL; i = i->next) #define RSE_LINKED_LIST_FOREACH_REVERSE(list, i) \ - for (typeof(list) i = list; i != NULL; i = i->next) + for (__typeof__(list) i = list; i != NULL; i = i->next) #define RSE_LINKED_LIST_TO_ARRAY(list, array) \ ({ \ diff --git a/utilities/src/file_utils.c b/utilities/src/file_utils.c index b0bb2f19..4cce4c61 100644 --- a/utilities/src/file_utils.c +++ b/utilities/src/file_utils.c @@ -2,16 +2,27 @@ #include #include +#include +#include "utilities/commons.h" +#include "utilities/errors_common.h" +#include "utilities/localization.h" +#include "utilities/logger.h" + +#ifdef __linux__ +#include +#include +#endif /* ifndef __linux */ + +#define MAX_PATH_LENGTH (4096U) void read_file(const char* file_name, size_t* bytes_count, char* buffer) { - errno_t err = 0; FILE* file = NULL; - err = fopen_s(&file, file_name, "rb"); + file = fopen(file_name, "rb"); - if (0 != err) { - perror("Failed to open file"); + if (NULL == file) { + LOGE(_("Failed to open file for read: %s\n"), file_name); return; } @@ -33,16 +44,71 @@ void read_file(const char* file_name, size_t* bytes_count, char* buffer) void write_to_file(const char* file_name, size_t bytes_count, char* buffer) { - errno_t err = 0; FILE* file = NULL; - err = fopen_s(&file, file_name, "wb"); + file = fopen(file_name, "wb"); - if (0 != err) { - perror("Failed to open file."); + if (NULL == file) { + LOGE(_("Failed to open file for write: %s\n"), file_name); return; } fwrite(buffer, bytes_count, 1, file); fclose(file); } + +rse_err_t get_curr_path(char* path, size_t path_size) +{ + char* last_sep = NULL; + char* tmp_path = NULL; + size_t binary_path_length = 0U; + size_t directory_path_length = 0U; + + if (NULL == path) { + LOGE(_("Failed to get path. Provided pointer is NULL\n")); + + return RSE_ERROR_NULL_POINTER; + } + + if (0 == path_size) { + LOGE(_("Max path length cannot be 0\n")); + + return RSE_ERROR_INVALID_PARAM; + } + + rse_memset(path, '\0', path_size); + rse_malloc(tmp_path, MAX_PATH_LENGTH); + +#ifdef __linux__ + binary_path_length = readlink("/proc/self/exe", tmp_path, MAX_PATH_LENGTH - 1); + if (binary_path_length == -1) { + LOGF(_("Failed to read current binary path\n")); + + return RSE_ERROR_NULL_POINTER; + } + + tmp_path[binary_path_length] = '\0'; +#endif /* ifdef __linux__ */ + + last_sep = strrchr(tmp_path, '/') + 1; + + if (NULL == last_sep) { + LOGE(_("Failed to get last separator in path\n")); + + return RSE_ERROR_INTERNAL_ERROR; + } + + directory_path_length = last_sep - tmp_path; + + if (directory_path_length > path_size) { + LOGE(_("Provided path buffer is too small\n")); + + return RSE_ERROR_INTERNAL_ERROR; + } + + strncpy(path, tmp_path, directory_path_length); + + free(tmp_path); + + return RSE_ERROR_NO_ERROR; +}