[WIP] Add descriptors and pipeline builder
This commit is contained in:
1 parent
173a82b9d1
commit
f8eb98ddf4
36 files changed
+612
-457
No files matched your search
+2
-1
@@ -4,7 +4,8 @@ project("RedScarfEngine"
|
|||||||
DESCRIPTION "Vulkan based 3D engine"
|
DESCRIPTION "Vulkan based 3D engine"
|
||||||
LANGUAGES C CXX)
|
LANGUAGES C CXX)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 23)
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
set(FREE_TYPE_DIR "${PROJECT_SOURCE_DIR}/third_party/freetype/")
|
set(FREE_TYPE_DIR "/usr/")
|
||||||
|
|
||||||
find_library(
|
find_library(
|
||||||
freetype
|
freetype
|
||||||
NAMES freetype
|
NAMES freetype
|
||||||
HINTS ${FREE_TYPE_DIR}/build/
|
HINTS ${FREE_TYPE_DIR}/lib/x86_64-linux-gnu
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
set(FreeType_INCLUDE_DIR "${FREE_TYPE_DIR}/include/")
|
set(FreeType_INCLUDE_DIR "${FREE_TYPE_DIR}/include/freetype2/")
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
set(STB_DIR "${PROJECT_SOURCE_DIR}/third_party/stb/")
|
set(STB_DIR "/usr/include")
|
||||||
|
|
||||||
set(stb_INCLUDE_DIR "${STB_DIR}/")
|
set(stb_INCLUDE_DIR "${STB_DIR}/")
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,7 +1,6 @@
|
|||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
find_package(vma REQUIRED)
|
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||||
find_package(glfw3 REQUIRED)
|
find_package(glfw3 REQUIRED)
|
||||||
find_package(stb REQUIRED)
|
|
||||||
find_package(FreeType REQUIRED)
|
find_package(FreeType REQUIRED)
|
||||||
|
|
||||||
find_package(Vulkan COMPONENTS glslc)
|
find_package(Vulkan COMPONENTS glslc)
|
||||||
@@ -19,7 +18,6 @@ function(compile_shader)
|
|||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${source}.${arg_FORMAT}
|
OUTPUT ${source}.${arg_FORMAT}
|
||||||
DEPENDS ${source}
|
DEPENDS ${source}
|
||||||
DEPFILE ${source}.d
|
|
||||||
COMMAND
|
COMMAND
|
||||||
${glslc_executable}
|
${glslc_executable}
|
||||||
-o ${source}.${arg_FORMAT}
|
-o ${source}.${arg_FORMAT}
|
||||||
@@ -57,21 +55,23 @@ target_sources(graphics PRIVATE
|
|||||||
src/vma_port.cpp
|
src/vma_port.cpp
|
||||||
src/window.c
|
src/window.c
|
||||||
src/vulkan_base.c
|
src/vulkan_base.c
|
||||||
src/vulkan_pipeline.c
|
|
||||||
src/vulkan_commands.c
|
src/vulkan_commands.c
|
||||||
src/vulkan_buffers.c
|
src/vulkan_buffers.c
|
||||||
src/vulkan_descriptors.c
|
|
||||||
src/rse_graphics.c
|
src/rse_graphics.c
|
||||||
src/math.c
|
src/math.c
|
||||||
src/mesh_controller.c
|
src/mesh_controller.c
|
||||||
src/vulkan_commons.c
|
src/vulkan_commons.c
|
||||||
src/vulkan_image.c
|
src/vulkan_image.c
|
||||||
|
src/vulkan_render_pass.c
|
||||||
|
src/vulkan_swapchain.c
|
||||||
src/text_renderer.c
|
src/text_renderer.c
|
||||||
|
src/pipeline_builder.c
|
||||||
|
src/descriptor_builder.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(graphics PRIVATE
|
target_link_libraries(graphics PUBLIC
|
||||||
utilities
|
utilities
|
||||||
${Vulkan_LIBRARIES}
|
${Vulkan_LIBRARIES}
|
||||||
${glfw}
|
glfw
|
||||||
${freetype}
|
${freetype}
|
||||||
)
|
)
|
||||||
@@ -12,7 +12,7 @@ struct rse_graphics_context_t;
|
|||||||
* @param context Graphics context handle. Must be NULL!
|
* @param context Graphics context handle. Must be NULL!
|
||||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||||
*/
|
*/
|
||||||
rse_err_t rse_graphics_init(struct rse_graphics_context_t* context);
|
rse_err_t rse_graphics_init(struct rse_graphics_context_t** context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Runs graphics engine. This has to be called after all objects are added to the scene
|
* @brief Runs graphics engine. This has to be called after all objects are added to the scene
|
||||||
|
|||||||
@@ -0,0 +1,228 @@
|
|||||||
|
/**
|
||||||
|
* @file descriptor_builder.c
|
||||||
|
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2025-03-14
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2025
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "descriptor_builder.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "src/graphics_context.h"
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
#include "utilities/errors_common.h"
|
||||||
|
#include "utilities/linked_list.h"
|
||||||
|
#include "utilities/localization.h"
|
||||||
|
#include "utilities/logger.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
#include "vulkan_errors.h"
|
||||||
|
|
||||||
|
RSE_LINKED_LIST_DEFINE(descriptor_set_layout_list_t,
|
||||||
|
VkDescriptorSetLayoutBinding);
|
||||||
|
|
||||||
|
struct descriptor_t
|
||||||
|
{
|
||||||
|
uint32_t binding;
|
||||||
|
VkDescriptorType type;
|
||||||
|
uint32_t descriptors_count;
|
||||||
|
VkShaderStageFlags shader_stages;
|
||||||
|
VkSampler immutable_sampler;
|
||||||
|
};
|
||||||
|
RSE_LINKED_LIST_DEFINE(descriptors_list_t, struct descriptor_t);
|
||||||
|
|
||||||
|
/* FIXME: When new descriptors are introduced to Vulkan, this enum has to be
|
||||||
|
* updated */
|
||||||
|
enum descriptor_type_id_t
|
||||||
|
{
|
||||||
|
DESCRIPTOR_TYPE_SAMPLER_ID,
|
||||||
|
DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID,
|
||||||
|
DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID,
|
||||||
|
DESCRIPTOR_TYPE_STORAGE_IMAGE_ID,
|
||||||
|
DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID,
|
||||||
|
DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID,
|
||||||
|
DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID,
|
||||||
|
DESCRIPTOR_TYPE_STORAGE_BUFFER_ID,
|
||||||
|
DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID,
|
||||||
|
DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID,
|
||||||
|
DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID,
|
||||||
|
DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID,
|
||||||
|
DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID,
|
||||||
|
DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID,
|
||||||
|
DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID,
|
||||||
|
DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID,
|
||||||
|
DESCRIPTOR_TYPE_MUTABLE_EXT_ID,
|
||||||
|
DESCRIPTOR_TYPE_ID_MAX_ENUM,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct descriptors_data_t
|
||||||
|
{
|
||||||
|
VkDescriptorPool pool;
|
||||||
|
VkDescriptorSet set;
|
||||||
|
struct descriptor_set_layout_list_t layouts_list;
|
||||||
|
};
|
||||||
|
|
||||||
|
rse_err_t descriptor_add(struct descriptors_list_t* descriptors_list,
|
||||||
|
uint32_t binding, VkDescriptorType type,
|
||||||
|
uint32_t descriptors_count,
|
||||||
|
VkShaderStageFlags shader_stages, VkSampler sampler)
|
||||||
|
{
|
||||||
|
struct descriptor_t descriptor = {.binding = binding,
|
||||||
|
.type = type,
|
||||||
|
.descriptors_count = descriptors_count,
|
||||||
|
.shader_stages = shader_stages,
|
||||||
|
.immutable_sampler = sampler};
|
||||||
|
|
||||||
|
RSE_LINKED_LIST_PUSH_BACK(descriptors_list, descriptor);
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t descriptors_build(struct graphics_context_t* context,
|
||||||
|
struct descriptors_list_t* descriptors)
|
||||||
|
{
|
||||||
|
VkDescriptorPoolCreateInfo pool_create_info = {};
|
||||||
|
VkDescriptorPoolCreateFlags pool_create_flags = 0U;
|
||||||
|
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
|
||||||
|
VkDescriptorPoolSize pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {};
|
||||||
|
VkDescriptorPoolSize requested_pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {};
|
||||||
|
uint32_t pool_max_sets = 0;
|
||||||
|
size_t pool_size_count = 0U;
|
||||||
|
size_t iterator = 0U;
|
||||||
|
|
||||||
|
if (NULL == context) {
|
||||||
|
LOGF(_("Provided NULL context\n"));
|
||||||
|
|
||||||
|
return RSE_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
RSE_LINKED_LIST_FOREACH(descriptors, descriptor)
|
||||||
|
{
|
||||||
|
switch (descriptor->data.type) {
|
||||||
|
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_SAMPLER_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_SAMPLER_ID].descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID].descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_IMAGE_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_IMAGE_ID].descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID].descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_ID].descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID]
|
||||||
|
.descriptorCount++;
|
||||||
|
break;
|
||||||
|
case VK_DESCRIPTOR_TYPE_MUTABLE_EXT:
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_MUTABLE_EXT_ID].type =
|
||||||
|
VK_DESCRIPTOR_TYPE_MUTABLE_EXT;
|
||||||
|
pool_sizes[DESCRIPTOR_TYPE_MUTABLE_EXT_ID].descriptorCount++;
|
||||||
|
default:
|
||||||
|
LOGF(_("Invalid descriptor type provided\n"));
|
||||||
|
return VULKAN_ERROR_UNKNOWN_DESCRIPTOR_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate pool based on layout */
|
||||||
|
/* create array of required descriptors */
|
||||||
|
for (iterator = 0U; iterator < DESCRIPTOR_TYPE_ID_MAX_ENUM; ++iterator) {
|
||||||
|
if (pool_sizes[iterator].descriptorCount > 0) {
|
||||||
|
requested_pool_sizes[pool_size_count].type =
|
||||||
|
pool_sizes[iterator].type;
|
||||||
|
requested_pool_sizes[pool_size_count].descriptorCount =
|
||||||
|
pool_sizes[iterator].descriptorCount;
|
||||||
|
pool_size_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
|
pool_create_info.pNext = NULL;
|
||||||
|
pool_create_info.flags = pool_create_flags;
|
||||||
|
pool_create_info.maxSets =
|
||||||
|
0; // FIXME: Calculate number of sets based on layout
|
||||||
|
pool_create_info.poolSizeCount = pool_size_count;
|
||||||
|
pool_create_info.pPoolSizes = requested_pool_sizes;
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* @file descriptor_builder.h
|
||||||
|
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2024-03-01
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DESCRIPTOR_BUILDER_H
|
||||||
|
#define DESCRIPTOR_BUILDER_H
|
||||||
|
|
||||||
|
struct descriptors_list_t;
|
||||||
|
|
||||||
|
#endif // !DESCRIPTOR_BUILDER_H
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#define MAX_DESCRIPTOR_SETS 16
|
#define MAX_DESCRIPTOR_SETS 16
|
||||||
#define MAX_PIPELINE_COUNT 16
|
#define MAX_PIPELINE_COUNT 16
|
||||||
|
#define MAX_DESCRIPTOR_POOLS_COUNT (16)
|
||||||
|
|
||||||
RSE_LINKED_LIST_DEFINE(shader_module_list_t, VkShaderModule);
|
RSE_LINKED_LIST_DEFINE(shader_module_list_t, VkShaderModule);
|
||||||
|
|
||||||
@@ -91,7 +92,6 @@ struct pipeline_internal_t
|
|||||||
size_t descriptor_set_layouts_count;
|
size_t descriptor_set_layouts_count;
|
||||||
VkPipeline pipelines[MAX_PIPELINE_COUNT];
|
VkPipeline pipelines[MAX_PIPELINE_COUNT];
|
||||||
VkPipelineLayout pipeline_layout;
|
VkPipelineLayout pipeline_layout;
|
||||||
VkDescriptorSetLayout descriptor_set_layouts[MAX_DESCRIPTOR_SETS];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct graphics_context_t
|
struct graphics_context_t
|
||||||
|
|||||||
+98
-338
@@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
#include "pipeline_builder.h"
|
#include "pipeline_builder.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "src/graphics_context.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
#include "utilities/file_utils.h"
|
#include "utilities/file_utils.h"
|
||||||
@@ -22,6 +26,40 @@
|
|||||||
|
|
||||||
#define MAX_BINDLESS_RESOURCES 1000
|
#define MAX_BINDLESS_RESOURCES 1000
|
||||||
|
|
||||||
|
RSE_LINKED_LIST_DEFINE(vertex_binding_list_t, VkVertexInputBindingDescription);
|
||||||
|
RSE_LINKED_LIST_DEFINE(shader_attribute_list_t,
|
||||||
|
VkVertexInputAttributeDescription);
|
||||||
|
RSE_LINKED_LIST_DEFINE(dynamic_state_list_t, VkDynamicState);
|
||||||
|
RSE_LINKED_LIST_DEFINE(pipeline_infos_list_t, VkGraphicsPipelineCreateInfo);
|
||||||
|
|
||||||
|
RSE_STACK_DEFINE(required_dynamic_states_t, VkDynamicState, 16U);
|
||||||
|
|
||||||
|
|
||||||
|
struct pipeline_t {
|
||||||
|
VkPipeline pipeline;
|
||||||
|
uint8_t id;
|
||||||
|
/* Shader stages */
|
||||||
|
size_t shader_stages_count;
|
||||||
|
VkPipelineShaderStageCreateInfo shader_stages[MAX_SHADER_STAGES];
|
||||||
|
/* Input assembly */
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo input_assembly;
|
||||||
|
/* Viewport state */
|
||||||
|
VkPipelineViewportStateCreateInfo viewport_state;
|
||||||
|
/* Rasterizer */
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterizer;
|
||||||
|
/* Multisampling */
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisampling;
|
||||||
|
/* Color blending */
|
||||||
|
VkPipelineColorBlendAttachmentState color_blend_attachment;
|
||||||
|
VkPipelineColorBlendStateCreateInfo color_blending;
|
||||||
|
/* Depth stencil */
|
||||||
|
VkPipelineDepthStencilStateCreateInfo depth_stencil;
|
||||||
|
struct vertex_binding_list_t* vertex_bindings;
|
||||||
|
struct shader_attribute_list_t* shader_attributes;
|
||||||
|
struct dynamic_state_list_t* dynamic_states;
|
||||||
|
struct required_dynamic_states_t required_dynamic_states;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates shader module
|
* @brief Creates shader module
|
||||||
*
|
*
|
||||||
@@ -42,8 +80,8 @@ static rse_err_t create_shader_module(struct graphics_context_t* context,
|
|||||||
|
|
||||||
RSE_LINKED_LIST_PUSH_FRONT(context->shader_modules, (VkShaderModule){0});
|
RSE_LINKED_LIST_PUSH_FRONT(context->shader_modules, (VkShaderModule){0});
|
||||||
|
|
||||||
if (VK_SUCCESS != vkCreateShaderModule(
|
if (VK_SUCCESS !=
|
||||||
context->device, &create_info, NULL,
|
vkCreateShaderModule(context->device, &create_info, NULL,
|
||||||
&RSE_LINKED_LIST_FRONT(context->shader_modules))) {
|
&RSE_LINKED_LIST_FRONT(context->shader_modules))) {
|
||||||
LOGF(_("Failed to create a shader\n"));
|
LOGF(_("Failed to create a shader\n"));
|
||||||
return VULKAN_ERROR_SHADER_CREATION_FAILED;
|
return VULKAN_ERROR_SHADER_CREATION_FAILED;
|
||||||
@@ -124,7 +162,7 @@ static rse_err_t pipeline_add_multisampling(struct pipeline_t* pipeline)
|
|||||||
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
pipeline->multisampling.pNext = NULL;
|
pipeline->multisampling.pNext = NULL;
|
||||||
pipeline->multisampling.flags = 0U;
|
pipeline->multisampling.flags = 0U;
|
||||||
pipeline->multisampling.rasterizationSamples = VK_SAMPLE_COUNT_16_BIT;
|
pipeline->multisampling.rasterizationSamples = VK_SAMPLE_COUNT_8_BIT;
|
||||||
pipeline->multisampling.sampleShadingEnable = VK_FALSE;
|
pipeline->multisampling.sampleShadingEnable = VK_FALSE;
|
||||||
pipeline->multisampling.minSampleShading = 1.0f;
|
pipeline->multisampling.minSampleShading = 1.0f;
|
||||||
pipeline->multisampling.pSampleMask = NULL;
|
pipeline->multisampling.pSampleMask = NULL;
|
||||||
@@ -212,104 +250,6 @@ static rse_err_t create_pipeline_layout(struct graphics_context_t* context)
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create a Render Pass
|
|
||||||
*
|
|
||||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
|
|
||||||
* VULKAN_ERROR_RENDERPASS_CREATION_FAILED
|
|
||||||
*/
|
|
||||||
static rse_err_t create_render_pass(struct graphics_context_t* context)
|
|
||||||
{
|
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
|
||||||
VkAttachmentDescription attachments[3] = {};
|
|
||||||
VkAttachmentDescription color_attachment = {};
|
|
||||||
VkAttachmentReference color_attachment_ref = {};
|
|
||||||
VkAttachmentDescription color_attachment_resolve = {};
|
|
||||||
VkAttachmentReference color_attachment_resolve_ref = {};
|
|
||||||
VkSubpassDescription subpass = {};
|
|
||||||
VkRenderPassCreateInfo renderpass_info = {};
|
|
||||||
VkAttachmentDescription depth_attachment = {};
|
|
||||||
VkAttachmentReference depth_attachment_ref = {};
|
|
||||||
VkSubpassDependency dependency = {};
|
|
||||||
|
|
||||||
STATUS_CHECK(find_depth_format(context, &depth_attachment.format));
|
|
||||||
|
|
||||||
depth_attachment.samples = VK_SAMPLE_COUNT_16_BIT;
|
|
||||||
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
||||||
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
||||||
depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
depth_attachment.finalLayout =
|
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
depth_attachment_ref.attachment = 1;
|
|
||||||
depth_attachment_ref.layout =
|
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
color_attachment.flags = 0U;
|
|
||||||
color_attachment.format = IMAGE_FORMAT;
|
|
||||||
color_attachment.samples = VK_SAMPLE_COUNT_16_BIT;
|
|
||||||
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
|
||||||
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
|
||||||
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
||||||
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
color_attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
color_attachment_ref.attachment = 0;
|
|
||||||
color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
color_attachment_resolve.format = IMAGE_FORMAT;
|
|
||||||
color_attachment_resolve.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
color_attachment_resolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
||||||
color_attachment_resolve.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
color_attachment_resolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
|
||||||
color_attachment_resolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
|
||||||
color_attachment_resolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
color_attachment_resolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
||||||
|
|
||||||
color_attachment_resolve_ref.attachment = 2;
|
|
||||||
color_attachment_resolve_ref.layout =
|
|
||||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
|
||||||
|
|
||||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
|
||||||
subpass.colorAttachmentCount = 1;
|
|
||||||
subpass.pColorAttachments = &color_attachment_ref;
|
|
||||||
subpass.pDepthStencilAttachment = &depth_attachment_ref;
|
|
||||||
subpass.pResolveAttachments = &color_attachment_resolve_ref;
|
|
||||||
|
|
||||||
attachments[0] = color_attachment;
|
|
||||||
attachments[1] = depth_attachment;
|
|
||||||
attachments[2] = color_attachment_resolve;
|
|
||||||
|
|
||||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
|
||||||
dependency.dstSubpass = 0;
|
|
||||||
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
|
||||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
|
||||||
dependency.srcAccessMask = 0;
|
|
||||||
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
|
||||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
|
||||||
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
|
||||||
|
|
||||||
renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
|
||||||
renderpass_info.attachmentCount = 3;
|
|
||||||
renderpass_info.pAttachments = attachments;
|
|
||||||
renderpass_info.subpassCount = 1;
|
|
||||||
renderpass_info.pSubpasses = &subpass;
|
|
||||||
renderpass_info.dependencyCount = 1;
|
|
||||||
renderpass_info.pDependencies = &dependency;
|
|
||||||
|
|
||||||
if (VK_SUCCESS != vkCreateRenderPass(context->device, &renderpass_info,
|
|
||||||
NULL, &context->render_pass)) {
|
|
||||||
LOGF(_("Failed to create render pass\n"));
|
|
||||||
return VULKAN_ERROR_RENDERPASS_CREATION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RSE_ERROR_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clean up pipeline builder. This function should be called after all
|
* @brief Clean up pipeline builder. This function should be called after all
|
||||||
* pipelines are built and no more pipelines are needed. It frees all resources
|
* pipelines are built and no more pipelines are needed. It frees all resources
|
||||||
@@ -339,6 +279,10 @@ static void pipeline_builder_cleanup(struct pipeline_infos_list_t* pipelines)
|
|||||||
dynamic_states =
|
dynamic_states =
|
||||||
(VkDynamicState*)pipeline_info->pDynamicState->pDynamicStates;
|
(VkDynamicState*)pipeline_info->pDynamicState->pDynamicStates;
|
||||||
|
|
||||||
|
rse_free((VkPipelineVertexInputStateCreateInfo*)
|
||||||
|
pipeline_info->pVertexInputState);
|
||||||
|
rse_free((VkPipelineDynamicStateCreateInfo*)
|
||||||
|
pipeline_info->pDynamicState);
|
||||||
rse_free(vertex_bindings);
|
rse_free(vertex_bindings);
|
||||||
rse_free(shader_attributes);
|
rse_free(shader_attributes);
|
||||||
rse_free(dynamic_states);
|
rse_free(dynamic_states);
|
||||||
@@ -351,140 +295,6 @@ static void pipeline_builder_cleanup(struct pipeline_infos_list_t* pipelines)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @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, struct binding_info_t* binding_infos, size_t binding_count)
|
|
||||||
{
|
|
||||||
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 pipeline_add_dynamic_state(struct pipeline_t* pipeline,
|
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline,
|
||||||
VkDynamicState dynamic_state)
|
VkDynamicState dynamic_state)
|
||||||
{
|
{
|
||||||
@@ -498,19 +308,21 @@ rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline,
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t pipeline_builder_init(struct pipeline_t* pipeline)
|
rse_err_t pipeline_builder_init(struct pipeline_t** pipeline)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
struct pipeline_t* pipeline_ptr = NULL;
|
||||||
|
|
||||||
if (pipeline != NULL) {
|
if (*pipeline != NULL) {
|
||||||
LOGF(
|
LOGF(
|
||||||
_("Pipeline is not NULL. This function will initialize everything "
|
_("Pipeline is not NULL. This function will initialize everything "
|
||||||
"for you, no need for manual allocation\n"));
|
"for you, no need for manual allocation\n"));
|
||||||
return VULKAN_ERROR_PIPELINE_ALREADY_INITIALIZED;
|
return VULKAN_ERROR_PIPELINE_ALREADY_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_malloc(pipeline, sizeof(struct pipeline_t));
|
rse_malloc(pipeline_ptr, sizeof(struct pipeline_t));
|
||||||
rse_memset(pipeline, 0, sizeof(struct pipeline_t));
|
rse_memset(pipeline_ptr, 0, sizeof(struct pipeline_t));
|
||||||
|
*pipeline = pipeline_ptr;
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -608,95 +420,31 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline,
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t pipeline_add_descriptor_layout(struct graphics_context_t* context,
|
rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||||
struct binding_info_t* binding_infos,
|
struct pipeline_infos_list_t* pipelines_infos_list)
|
||||||
size_t binding_count,
|
|
||||||
size_t* descriptor_set_index)
|
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayoutCreateInfo layout_info = {};
|
assert(NULL != context);
|
||||||
VkDescriptorSetLayoutBinding* bindings = NULL;
|
assert(NULL != pipelines_infos_list);
|
||||||
VkDescriptorSetLayoutBindingFlagsCreateInfoEXT extended_info = {0};
|
|
||||||
VkDescriptorBindingFlags bindless_flags =
|
|
||||||
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT |
|
|
||||||
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT |
|
|
||||||
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT;
|
|
||||||
|
|
||||||
if (binding_count == 0) {
|
size_t i = 0U;
|
||||||
LOGF(_("No bindings in descriptor set layout\n"));
|
|
||||||
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_NO_BINDINGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context->pipelines_data.descriptor_set_layouts_count + 1 >
|
|
||||||
MAX_DESCRIPTOR_SETS) {
|
|
||||||
LOGF(_("Too many descriptor sets\n"));
|
|
||||||
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_TOO_MANY;
|
|
||||||
}
|
|
||||||
|
|
||||||
rse_malloc(bindings, sizeof(VkDescriptorSetLayoutBinding) * binding_count);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < binding_count; i++) {
|
|
||||||
bindings[i].binding = binding_infos[i].binding;
|
|
||||||
bindings[i].descriptorType = binding_infos[i].descriptor_type;
|
|
||||||
bindings[i].descriptorCount = 1;
|
|
||||||
bindings[i].stageFlags = binding_infos[i].stage_flags;
|
|
||||||
bindings[i].pImmutableSamplers = NULL;
|
|
||||||
|
|
||||||
if (bindings[i].descriptorType ==
|
|
||||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
|
|
||||||
bindings[i].pImmutableSamplers = NULL;
|
|
||||||
bindings[i].descriptorCount = MAX_BINDLESS_RESOURCES;
|
|
||||||
|
|
||||||
extended_info.sType =
|
|
||||||
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
|
|
||||||
extended_info.bindingCount++;
|
|
||||||
extended_info.pBindingFlags = &bindless_flags;
|
|
||||||
|
|
||||||
layout_info.pNext = &extended_info;
|
|
||||||
layout_info.flags =
|
|
||||||
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
||||||
layout_info.bindingCount = (uint32_t)binding_count;
|
|
||||||
layout_info.pBindings = bindings;
|
|
||||||
|
|
||||||
if (vkCreateDescriptorSetLayout(
|
|
||||||
context->device, &layout_info, NULL,
|
|
||||||
&context->pipelines_data.descriptor_set_layouts
|
|
||||||
[context->pipelines_data.descriptor_set_layouts_count]) !=
|
|
||||||
VK_SUCCESS) {
|
|
||||||
LOGF(_("Failed to create descriptor set layout\n"));
|
|
||||||
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*descriptor_set_index =
|
|
||||||
context->pipelines_data.descriptor_set_layouts_count;
|
|
||||||
context->pipelines_data.descriptor_set_layouts_count++;
|
|
||||||
|
|
||||||
rse_free(bindings);
|
|
||||||
|
|
||||||
return RSE_ERROR_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
rse_err_t build_pipelines(struct graphics_context_t* context,
|
|
||||||
struct pipeline_infos_list_t* pipelines)
|
|
||||||
{
|
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
size_t pipelines_count = RSE_LINKED_LIST_SIZE(pipelines);
|
size_t pipelines_count = RSE_LINKED_LIST_SIZE(pipelines_infos_list);
|
||||||
VkGraphicsPipelineCreateInfo* pipeline_infos = NULL;
|
VkGraphicsPipelineCreateInfo* pipeline_infos = NULL;
|
||||||
|
|
||||||
context->pipelines_data.pipelines_count = pipelines_count;
|
context->pipelines_data.pipelines_count = pipelines_count;
|
||||||
|
|
||||||
create_pipeline_layout(context);
|
STATUS_CHECK(create_pipeline_layout(context));
|
||||||
create_render_pass(context);
|
|
||||||
create_descriptor_pool(context, NULL, 0);
|
|
||||||
|
|
||||||
rse_malloc(pipeline_infos,
|
rse_malloc(pipeline_infos,
|
||||||
sizeof(VkGraphicsPipelineCreateInfo) * pipelines_count);
|
sizeof(VkGraphicsPipelineCreateInfo) * pipelines_count);
|
||||||
|
|
||||||
RSE_LINKED_LIST_TO_ARRAY(pipelines, pipeline_infos);
|
RSE_LINKED_LIST_TO_ARRAY(pipelines_infos_list, pipeline_infos);
|
||||||
|
|
||||||
|
/* FIXME: layout is created to late. Maybe move it somewhere else so we
|
||||||
|
* don't need this loop? */
|
||||||
|
for (i = 0; i < pipelines_count; ++i) {
|
||||||
|
pipeline_infos[i].layout = context->pipelines_data.pipeline_layout;
|
||||||
|
}
|
||||||
|
|
||||||
if (VK_SUCCESS !=
|
if (VK_SUCCESS !=
|
||||||
vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE,
|
vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE,
|
||||||
@@ -707,14 +455,14 @@ rse_err_t build_pipelines(struct graphics_context_t* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rse_free(pipeline_infos);
|
rse_free(pipeline_infos);
|
||||||
pipeline_builder_cleanup(pipelines);
|
pipeline_builder_cleanup(pipelines_infos_list);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t add_pipeline(const struct graphics_context_t* context,
|
rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||||
struct pipeline_t* pipeline,
|
struct pipeline_t* pipeline,
|
||||||
struct pipeline_infos_list_t* pipelines)
|
struct pipeline_infos_list_t** pipelines_infos)
|
||||||
{
|
{
|
||||||
/* Check for send and required dynamic states */
|
/* Check for send and required dynamic states */
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
@@ -722,14 +470,17 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
|||||||
|
|
||||||
size_t vertex_bindings_count = 0U;
|
size_t vertex_bindings_count = 0U;
|
||||||
VkVertexInputBindingDescription* vertex_bindings = NULL;
|
VkVertexInputBindingDescription* vertex_bindings = NULL;
|
||||||
|
VkPipelineVertexInputStateCreateInfo* vertex_bindings_ci = NULL;
|
||||||
|
|
||||||
size_t shader_attributes_count = 0U;
|
size_t shader_attributes_count = 0U;
|
||||||
VkVertexInputAttributeDescription* shader_attributes = NULL;
|
VkVertexInputAttributeDescription* shader_attributes = NULL;
|
||||||
|
|
||||||
size_t dynamic_states_count = 0U;
|
size_t dynamic_states_count = 0U;
|
||||||
VkDynamicState* dynamic_states = NULL;
|
VkDynamicState* dynamic_states = NULL;
|
||||||
|
VkPipelineDynamicStateCreateInfo* dynamic_states_ci = NULL;
|
||||||
|
|
||||||
uint8_t dynamic_state_found = 0;
|
uint8_t dynamic_state_found = 0;
|
||||||
|
|
||||||
while (RSE_STACK_IS_EMPTY(pipeline->required_dynamic_states) == 0) {
|
while (RSE_STACK_IS_EMPTY(pipeline->required_dynamic_states) == 0) {
|
||||||
dynamic_state_found = 0;
|
dynamic_state_found = 0;
|
||||||
VkDynamicState dynamic_state =
|
VkDynamicState dynamic_state =
|
||||||
@@ -794,15 +545,20 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
|||||||
pipeline_info.flags = 0U;
|
pipeline_info.flags = 0U;
|
||||||
pipeline_info.stageCount = pipeline->shader_stages_count;
|
pipeline_info.stageCount = pipeline->shader_stages_count;
|
||||||
pipeline_info.pStages = pipeline->shader_stages;
|
pipeline_info.pStages = pipeline->shader_stages;
|
||||||
pipeline_info.pVertexInputState = &(VkPipelineVertexInputStateCreateInfo){
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
rse_malloc(vertex_bindings_ci,
|
||||||
.pNext = NULL,
|
sizeof(VkPipelineVertexInputStateCreateInfo));
|
||||||
.flags = 0U,
|
vertex_bindings_ci->sType =
|
||||||
.vertexBindingDescriptionCount = vertex_bindings_count,
|
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
.pVertexBindingDescriptions = vertex_bindings,
|
vertex_bindings_ci->pNext = NULL;
|
||||||
.vertexAttributeDescriptionCount = shader_attributes_count,
|
vertex_bindings_ci->flags = 0U;
|
||||||
.pVertexAttributeDescriptions = shader_attributes,
|
vertex_bindings_ci->vertexBindingDescriptionCount = vertex_bindings_count;
|
||||||
};
|
vertex_bindings_ci->pVertexBindingDescriptions = vertex_bindings;
|
||||||
|
vertex_bindings_ci->vertexAttributeDescriptionCount =
|
||||||
|
shader_attributes_count;
|
||||||
|
vertex_bindings_ci->pVertexAttributeDescriptions = shader_attributes;
|
||||||
|
pipeline_info.pVertexInputState = vertex_bindings_ci;
|
||||||
|
|
||||||
pipeline_info.pInputAssemblyState = &pipeline->input_assembly;
|
pipeline_info.pInputAssemblyState = &pipeline->input_assembly;
|
||||||
pipeline_info.pTessellationState = NULL;
|
pipeline_info.pTessellationState = NULL;
|
||||||
pipeline_info.pViewportState = &pipeline->viewport_state;
|
pipeline_info.pViewportState = &pipeline->viewport_state;
|
||||||
@@ -810,19 +566,23 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
|||||||
pipeline_info.pMultisampleState = &pipeline->multisampling;
|
pipeline_info.pMultisampleState = &pipeline->multisampling;
|
||||||
pipeline_info.pDepthStencilState = &pipeline->depth_stencil;
|
pipeline_info.pDepthStencilState = &pipeline->depth_stencil;
|
||||||
pipeline_info.pColorBlendState = &pipeline->color_blending;
|
pipeline_info.pColorBlendState = &pipeline->color_blending;
|
||||||
pipeline_info.pDynamicState = &(VkPipelineDynamicStateCreateInfo){
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
rse_malloc(dynamic_states_ci, sizeof(VkPipelineDynamicStateCreateInfo));
|
||||||
.pNext = NULL,
|
dynamic_states_ci->sType =
|
||||||
.flags = 0U,
|
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
.dynamicStateCount = dynamic_states_count,
|
dynamic_states_ci->pNext = NULL;
|
||||||
.pDynamicStates = dynamic_states,
|
dynamic_states_ci->flags = 0U;
|
||||||
};
|
dynamic_states_ci->dynamicStateCount = dynamic_states_count;
|
||||||
|
dynamic_states_ci->pDynamicStates = dynamic_states;
|
||||||
|
pipeline_info.pDynamicState = dynamic_states_ci;
|
||||||
|
|
||||||
pipeline_info.layout = context->pipelines_data.pipeline_layout;
|
pipeline_info.layout = context->pipelines_data.pipeline_layout;
|
||||||
pipeline_info.renderPass = context->render_pass;
|
pipeline_info.renderPass = context->render_pass;
|
||||||
pipeline_info.subpass = 0;
|
pipeline_info.subpass = 0;
|
||||||
pipeline_info.basePipelineHandle =
|
pipeline_info.basePipelineHandle =
|
||||||
VK_NULL_HANDLE; // TODO: Add possiblity do derive from another pipeline
|
VK_NULL_HANDLE; // TODO: Add possiblity do derive from another pipeline
|
||||||
pipeline_info.basePipelineIndex = -1;
|
pipeline_info.basePipelineIndex = -1;
|
||||||
|
RSE_LINKED_LIST_PUSH_BACK(*pipelines_infos, pipeline_info);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -831,7 +591,7 @@ void destroy_pipelines(struct graphics_context_t* context)
|
|||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t shader_modules_count = RSE_LINKED_LIST_SIZE(context->shader_modules);
|
size_t shader_modules_count = RSE_LINKED_LIST_SIZE(context->shader_modules);
|
||||||
vkDestroyRenderPass(context->device, context->render_pass, NULL);
|
|
||||||
for (i = 0; i < context->pipelines_data.pipelines_count; i++) {
|
for (i = 0; i < context->pipelines_data.pipelines_count; i++) {
|
||||||
if (context->pipelines_data.pipelines[i] != VK_NULL_HANDLE) {
|
if (context->pipelines_data.pipelines[i] != VK_NULL_HANDLE) {
|
||||||
vkDestroyPipeline(context->device,
|
vkDestroyPipeline(context->device,
|
||||||
@@ -851,8 +611,8 @@ void destroy_pipelines(struct graphics_context_t* context)
|
|||||||
for (i = 0; i < shader_modules_count; i++) {
|
for (i = 0; i < shader_modules_count; i++) {
|
||||||
if (RSE_LINKED_LIST_FRONT(context->shader_modules) != VK_NULL_HANDLE) {
|
if (RSE_LINKED_LIST_FRONT(context->shader_modules) != VK_NULL_HANDLE) {
|
||||||
vkDestroyShaderModule(
|
vkDestroyShaderModule(
|
||||||
context->device,
|
context->device, RSE_LINKED_LIST_FRONT(context->shader_modules),
|
||||||
RSE_LINKED_LIST_FRONT(context->shader_modules), NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
RSE_LINKED_LIST_POP_FRONT(context->shader_modules);
|
RSE_LINKED_LIST_POP_FRONT(context->shader_modules);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#define PIPELINE_BUILDER_H
|
#define PIPELINE_BUILDER_H
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
#include "graphics_context.h"
|
#include "graphics_context.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/linked_list.h"
|
#include "utilities/linked_list.h"
|
||||||
@@ -20,45 +21,8 @@
|
|||||||
|
|
||||||
#define MAX_SHADER_STAGES 12U
|
#define MAX_SHADER_STAGES 12U
|
||||||
|
|
||||||
RSE_LINKED_LIST_DEFINE(vertex_bindinlist_t, VkVertexInputBindingDescription);
|
struct pipeline_t;
|
||||||
RSE_LINKED_LIST_DEFINE(shader_attribute_list_t,
|
struct pipeline_infos_list_t;
|
||||||
VkVertexInputAttributeDescription);
|
|
||||||
RSE_LINKED_LIST_DEFINE(dynamic_state_list_t, VkDynamicState);
|
|
||||||
RSE_LINKED_LIST_DEFINE(pipeline_infos_list_t, VkGraphicsPipelineCreateInfo);
|
|
||||||
|
|
||||||
RSE_STACK_DEFINE(required_dynamic_states_t, VkDynamicState, 16U);
|
|
||||||
|
|
||||||
|
|
||||||
struct binding_info_t {
|
|
||||||
uint32_t binding;
|
|
||||||
VkDescriptorType descriptor_type;
|
|
||||||
VkShaderStageFlags stage_flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct pipeline_t {
|
|
||||||
VkPipeline pipeline;
|
|
||||||
uint8_t id;
|
|
||||||
/* Shader stages */
|
|
||||||
size_t shader_stages_count;
|
|
||||||
VkPipelineShaderStageCreateInfo shader_stages[MAX_SHADER_STAGES];
|
|
||||||
/* Input assembly */
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo input_assembly;
|
|
||||||
/* Viewport state */
|
|
||||||
VkPipelineViewportStateCreateInfo viewport_state;
|
|
||||||
/* Rasterizer */
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizer;
|
|
||||||
/* Multisampling */
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisampling;
|
|
||||||
/* Color blending */
|
|
||||||
VkPipelineColorBlendAttachmentState color_blend_attachment;
|
|
||||||
VkPipelineColorBlendStateCreateInfo color_blending;
|
|
||||||
/* Depth stencil */
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depth_stencil;
|
|
||||||
struct vertex_bindinlist_t* vertex_bindings;
|
|
||||||
struct shader_attribute_list_t* shader_attributes;
|
|
||||||
struct dynamic_state_list_t* dynamic_states;
|
|
||||||
struct required_dynamic_states_t required_dynamic_states;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize pipeline builder
|
* @brief Initialize pipeline builder
|
||||||
@@ -66,7 +30,7 @@ struct pipeline_t {
|
|||||||
* @param[out] pipeline Pipeline to initialize. Must be NULL
|
* @param[out] pipeline Pipeline to initialize. Must be NULL
|
||||||
* @return RSE_SUCCESS on success, error code otherwise
|
* @return RSE_SUCCESS on success, error code otherwise
|
||||||
*/
|
*/
|
||||||
rse_err_t pipeline_builder_init(struct pipeline_t* pipeline);
|
rse_err_t pipeline_builder_init(struct pipeline_t** pipeline);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add shader stages to pipeline
|
* @brief Add shader stages to pipeline
|
||||||
@@ -115,6 +79,18 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline, const
|
|||||||
*/
|
*/
|
||||||
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, const VkDynamicState dynamic_state);
|
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, const VkDynamicState dynamic_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add descriptor pool
|
||||||
|
*
|
||||||
|
* @param[in] context Graphics context handle
|
||||||
|
* @param[in] pipeline Pipeline to add descriptor pool to
|
||||||
|
* @param[in] descriptor_type Type of descriptors to be stored in this pool.
|
||||||
|
* @return RSE_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
rse_err_t pipeline_add_descriptor_pool(struct graphics_context_t* context,
|
||||||
|
struct pipeline_t* pipeline,
|
||||||
|
enum VkDescriptorType descriptor_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add required dynamic state to pipeline
|
* @brief Add required dynamic state to pipeline
|
||||||
*
|
*
|
||||||
@@ -136,7 +112,7 @@ rse_err_t pipeline_add_descriptor_layout(struct graphics_context_t* context,
|
|||||||
* @param[in] pipeline Pipelines list to build
|
* @param[in] pipeline Pipelines list to build
|
||||||
* @return RSE_SUCCESS on success, error code otherwise
|
* @return RSE_SUCCESS on success, error code otherwise
|
||||||
*/
|
*/
|
||||||
rse_err_t build_pipelines(struct graphics_context_t* context,
|
rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||||
struct pipeline_infos_list_t* pipelines);
|
struct pipeline_infos_list_t* pipelines);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -144,10 +120,10 @@ rse_err_t build_pipelines(struct graphics_context_t* context,
|
|||||||
*
|
*
|
||||||
* @param[in] context Graphics context handle
|
* @param[in] context Graphics context handle
|
||||||
* @param[in] pipeline Pipeline to add
|
* @param[in] pipeline Pipeline to add
|
||||||
* @param[out] pipelines List of pipelines
|
* @param[out] pipeline_info List of pipelines infos, where new info should be added
|
||||||
* @return RSE_SUCCESS on success, error code otherwise
|
* @return RSE_SUCCESS on success, error code otherwise
|
||||||
*/
|
*/
|
||||||
rse_err_t add_pipeline(const struct graphics_context_t* context, struct pipeline_t* pipeline, struct pipeline_infos_list_t* pipelines);
|
rse_err_t add_pipeline(const struct graphics_context_t* context, struct pipeline_t* pipeline, struct pipeline_infos_list_t** pipelines);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy all pipelines
|
* @brief Destroy all pipelines
|
||||||
|
|||||||
+24
-17
@@ -17,20 +17,23 @@ struct rse_graphics_context_t {
|
|||||||
struct graphics_context_t* context;
|
struct graphics_context_t* context;
|
||||||
};
|
};
|
||||||
|
|
||||||
rse_err_t rse_graphics_init(struct rse_graphics_context_t* context)
|
rse_err_t rse_graphics_init(struct rse_graphics_context_t** context)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
if (context != NULL) {
|
struct rse_graphics_context_t* ctx_ptr = NULL;
|
||||||
|
|
||||||
|
if (*context != NULL) {
|
||||||
LOGF(_("Graphics already initialized!\n"));
|
LOGF(_("Graphics already initialized!\n"));
|
||||||
return RSE_ERROR_ALREADY_INITIALIZED;
|
return RSE_ERROR_ALREADY_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_malloc(context, sizeof(struct rse_graphics_context_t));
|
rse_malloc(*context, sizeof(struct rse_graphics_context_t));
|
||||||
rse_malloc(context->context, sizeof(struct graphics_context_t));
|
ctx_ptr = *context;
|
||||||
rse_memset(context->context, 0, sizeof(struct graphics_context_t));
|
rse_malloc(ctx_ptr->context, sizeof(struct graphics_context_t));
|
||||||
|
rse_memset(ctx_ptr->context, 0, sizeof(struct graphics_context_t));
|
||||||
|
|
||||||
STATUS_CHECK(window_init(context->context->window_handle, &context->context->is_framebuffer_resized));
|
STATUS_CHECK(window_init(&ctx_ptr->context->window_handle, &ctx_ptr->context->is_framebuffer_resized));
|
||||||
STATUS_CHECK(init_vulkan(context->context));
|
STATUS_CHECK(init_vulkan(ctx_ptr->context));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -94,19 +97,21 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
// print_text("Hello World!", (struct vec3_t){-1.0f, 0.0f, 0.9f}, 0.3f);
|
// print_text("Hello World!", (struct vec3_t){-1.0f, 0.0f, 0.9f}, 0.3f);
|
||||||
|
|
||||||
/* Initialize pipeline */
|
/* Initialize pipeline */
|
||||||
pipeline_builder_init(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/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);
|
pipeline_add_shader_stage(context, pipeline, "../graphics/shaders/solid_objects.frag.num", 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, 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);
|
||||||
|
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, pos));
|
pipeline_add_vertex_input_attribute(pipeline, 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, pos));
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, color));
|
pipeline_add_vertex_input_attribute(pipeline, 0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, color));
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(struct vertex_t, tex_coords));
|
pipeline_add_vertex_input_attribute(pipeline, 0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(struct vertex_t, tex_coords));
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 3, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct instance_data_t, pos));
|
pipeline_add_vertex_input_attribute(pipeline, 1, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct instance_data_t, pos));
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 4, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct instance_data_t, rot));
|
pipeline_add_vertex_input_attribute(pipeline, 1, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct instance_data_t, rot));
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 5, 1, VK_FORMAT_R32_SFLOAT, offsetof(struct instance_data_t, scale));
|
pipeline_add_vertex_input_attribute(pipeline, 1, 5, VK_FORMAT_R32_SFLOAT, offsetof(struct instance_data_t, scale));
|
||||||
pipeline_add_vertex_input_attribute(pipeline, 6, 1, VK_FORMAT_R32_SFLOAT, offsetof(struct instance_data_t, texture_id));
|
pipeline_add_vertex_input_attribute(pipeline, 1, 6, VK_FORMAT_R32_UINT, offsetof(struct instance_data_t, texture_id));
|
||||||
|
|
||||||
pipeline_add_dynamic_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT);
|
pipeline_add_dynamic_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT);
|
||||||
pipeline_add_dynamic_state(pipeline, VK_DYNAMIC_STATE_SCISSOR);
|
pipeline_add_dynamic_state(pipeline, VK_DYNAMIC_STATE_SCISSOR);
|
||||||
@@ -119,10 +124,13 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
binding_infos[1].descriptor_type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
binding_infos[1].descriptor_type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
binding_infos[1].stage_flags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
binding_infos[1].stage_flags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
|
pipeline_add_descriptor_pool(context, pipeline, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||||
|
pipeline_add_descriptor_pool(context, pipeline, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||||
|
|
||||||
pipeline_add_descriptor_layout(context, &binding_infos[0], 1, &ubo_index);
|
pipeline_add_descriptor_layout(context, &binding_infos[0], 1, &ubo_index);
|
||||||
pipeline_add_descriptor_layout(context, &binding_infos[1], 1, &sampler_index);
|
pipeline_add_descriptor_layout(context, &binding_infos[1], 1, &sampler_index);
|
||||||
|
|
||||||
add_pipeline(context, pipeline, pipeline_infos);
|
add_pipeline(context, pipeline, &pipeline_infos);
|
||||||
|
|
||||||
build_pipelines(context, pipeline_infos);
|
build_pipelines(context, pipeline_infos);
|
||||||
|
|
||||||
@@ -135,8 +143,7 @@ rse_err_t rse_graphics_run(struct rse_graphics_context_t* rse_context)
|
|||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
struct graphics_context_t* context = rse_context->context;
|
struct graphics_context_t* context = rse_context->context;
|
||||||
|
|
||||||
STATUS_CHECK(init_vulkan(context));
|
STATUS_CHECK(run_vulkan(context));
|
||||||
|
|
||||||
STATUS_CHECK(window_loop(context));
|
STATUS_CHECK(window_loop(context));
|
||||||
|
|
||||||
deinit_vulkan(context);
|
deinit_vulkan(context);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include "freetype/fttypes.h"
|
#include "freetype/fttypes.h"
|
||||||
#include "locale_fonts.h"
|
|
||||||
#include "font_errors.h"
|
#include "font_errors.h"
|
||||||
#include "src/mesh_controller.h"
|
#include "src/mesh_controller.h"
|
||||||
#include "src/math.h"
|
#include "src/math.h"
|
||||||
@@ -11,6 +10,7 @@
|
|||||||
#include "utilities/logger.h"
|
#include "utilities/logger.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
|
#include "utilities/localization.h"
|
||||||
#include "vulkan_image.h"
|
#include "vulkan_image.h"
|
||||||
|
|
||||||
#include "vulkan/vulkan_core.h"
|
#include "vulkan/vulkan_core.h"
|
||||||
@@ -52,7 +52,7 @@ rse_err_t fonts_initialize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rse_err_t fonts_load_from_file(const char* file_path)
|
rse_err_t fonts_load_from_file(struct graphics_context_t* context, const char* file_path)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
@@ -110,9 +110,9 @@ rse_err_t fonts_load_from_file(const char* file_path)
|
|||||||
{g_fonts_data[iter].bearing_x, g_fonts_data[iter].height, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}
|
{g_fonts_data[iter].bearing_x, g_fonts_data[iter].height, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}
|
||||||
};
|
};
|
||||||
|
|
||||||
g_fonts_data[iter].mesh_id = create_mesh(font_vertices, font_indices, 8, 6);
|
g_fonts_data[iter].mesh_id = create_mesh(context, font_vertices, font_indices, 8, 6);
|
||||||
|
|
||||||
STATUS_CHECK(load_texture_from_bitmat(face->glyph->bitmap.buffer,
|
STATUS_CHECK(load_texture_from_bitmat(context, face->glyph->bitmap.buffer,
|
||||||
face->glyph->bitmap.width,
|
face->glyph->bitmap.width,
|
||||||
face->glyph->bitmap.rows,
|
face->glyph->bitmap.rows,
|
||||||
&g_fonts_data[iter].texture_id, VK_FORMAT_R8_SRGB));
|
&g_fonts_data[iter].texture_id, VK_FORMAT_R8_SRGB));
|
||||||
@@ -121,7 +121,7 @@ rse_err_t fonts_load_from_file(const char* file_path)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t print_text(const char* text, struct vec3_t position, float font_size)
|
rse_err_t print_text(struct graphics_context_t* context, const char* text, struct vec3_t position, float font_size)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
size_t iter = 0U;
|
size_t iter = 0U;
|
||||||
@@ -140,7 +140,7 @@ rse_err_t print_text(const char* text, struct vec3_t position, float font_size)
|
|||||||
|
|
||||||
x_pos = position.x + advance - (g_fonts_data[charactet_code].bearing_x * scale);
|
x_pos = position.x + advance - (g_fonts_data[charactet_code].bearing_x * scale);
|
||||||
y_pos = position.y - (g_fonts_data[charactet_code].bearing_y * scale);
|
y_pos = position.y - (g_fonts_data[charactet_code].bearing_y * scale);
|
||||||
create_mesh_instance(g_fonts_data[charactet_code].mesh_id, (struct instance_data_t){
|
create_mesh_instance(context, g_fonts_data[charactet_code].mesh_id, (struct instance_data_t){
|
||||||
{x_pos, y_pos, 0.0f},
|
{x_pos, y_pos, 0.0f},
|
||||||
{0.0f, 0.0f, math_deg_to_radians(0.0f)},
|
{0.0f, 0.0f, math_deg_to_radians(0.0f)},
|
||||||
FONT_SCALING * font_size,
|
FONT_SCALING * font_size,
|
||||||
|
|||||||
@@ -15,10 +15,11 @@
|
|||||||
#define TEXT_RENDERER_H
|
#define TEXT_RENDERER_H
|
||||||
|
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
|
#include "graphics_context.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
|
||||||
rse_err_t fonts_initialize(void);
|
rse_err_t fonts_initialize(void);
|
||||||
rse_err_t fonts_load_from_file(const char* file_path);
|
rse_err_t fonts_load_from_file(struct graphics_context_t* context, const char* file_path);
|
||||||
rse_err_t print_text(const char* text, struct vec3_t position, float font_size);
|
rse_err_t print_text(struct graphics_context_t* context, const char* text, struct vec3_t position, float font_size);
|
||||||
|
|
||||||
#endif // !TEXT_RENDERER_H_
|
#endif // !TEXT_RENDERER_H_
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @file vulkanBase.cpp
|
* @file vulkanBase.cp
|
||||||
* @author Piotr Krygier (everyonecancode@gmail.com)
|
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||||
* @brief Base configuration for Vulkan API
|
* @brief Base configuration for Vulkan API
|
||||||
* @version 0.1
|
* @version 0.1
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "vk_mem_alloc.h"
|
#include "vk_mem_alloc.h"
|
||||||
// #pragma GCC diagnostic pop
|
// #pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
#include "utilities/logger.h"
|
#include "utilities/logger.h"
|
||||||
#include "vulkan/vulkan_core.h"
|
#include "vulkan/vulkan_core.h"
|
||||||
@@ -35,8 +36,10 @@
|
|||||||
#include "vulkan_commons.h"
|
#include "vulkan_commons.h"
|
||||||
#include "vulkan_commands.h"
|
#include "vulkan_commands.h"
|
||||||
#include "vulkan_buffers.h"
|
#include "vulkan_buffers.h"
|
||||||
#include "vulkan_descriptors.h"
|
|
||||||
#include "vulkan_image.h"
|
#include "vulkan_image.h"
|
||||||
|
#include "vulkan_render_pass.h"
|
||||||
|
#include "vulkan_swapchain.h"
|
||||||
|
#include "pipeline_builder.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -558,9 +561,11 @@ rse_err_t init_vulkan(struct graphics_context_t* context)
|
|||||||
STATUS_CHECK(pick_physical_device(context->instance, &context->physical_device));
|
STATUS_CHECK(pick_physical_device(context->instance, &context->physical_device));
|
||||||
STATUS_CHECK(create_device(context));
|
STATUS_CHECK(create_device(context));
|
||||||
STATUS_CHECK(create_memory_allocator(context));
|
STATUS_CHECK(create_memory_allocator(context));
|
||||||
|
STATUS_CHECK(create_render_pass(context));
|
||||||
STATUS_CHECK(init_commands(context));
|
STATUS_CHECK(init_commands(context));
|
||||||
STATUS_CHECK(create_buffers(context));
|
STATUS_CHECK(create_buffers(context));
|
||||||
STATUS_CHECK(init_vulkan_images(context));
|
STATUS_CHECK(init_vulkan_images(context));
|
||||||
|
STATUS_CHECK(create_swapchain_and_framebuffers(context));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -569,7 +574,6 @@ rse_err_t run_vulkan(struct graphics_context_t* context)
|
|||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
STATUS_CHECK(create_descriptors(context));
|
|
||||||
STATUS_CHECK(create_sync_objects(context));
|
STATUS_CHECK(create_sync_objects(context));
|
||||||
|
|
||||||
init_time();
|
init_time();
|
||||||
@@ -596,7 +600,7 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
VK_NULL_HANDLE, &image_index);
|
VK_NULL_HANDLE, &image_index);
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
recreate_swapchain();
|
recreate_swapchain(context);
|
||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
||||||
LOGF(_("Failed to acquire swapchain image\n"));
|
LOGF(_("Failed to acquire swapchain image\n"));
|
||||||
@@ -646,7 +650,7 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || context->is_framebuffer_resized) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || context->is_framebuffer_resized) {
|
||||||
context->is_framebuffer_resized = false;
|
context->is_framebuffer_resized = false;
|
||||||
recreate_swapchain();
|
recreate_swapchain(context);
|
||||||
} else if (result != VK_SUCCESS) {
|
} else if (result != VK_SUCCESS) {
|
||||||
LOGF(_("Failed to submit draw command buffer!\n"));
|
LOGF(_("Failed to submit draw command buffer!\n"));
|
||||||
return VULKAN_ERROR_DRAW_FAILED;
|
return VULKAN_ERROR_DRAW_FAILED;
|
||||||
@@ -659,8 +663,6 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
|
|
||||||
void deinit_vulkan(struct graphics_context_t* context)
|
void deinit_vulkan(struct graphics_context_t* context)
|
||||||
{
|
{
|
||||||
cleanup_swapchain();
|
|
||||||
destroy_descriptors();
|
|
||||||
destroy_buffers(context);
|
destroy_buffers(context);
|
||||||
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
|
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
|
||||||
vkDestroySemaphore(context->device, context->image_available_semaphores[i], NULL);
|
vkDestroySemaphore(context->device, context->image_available_semaphores[i], NULL);
|
||||||
@@ -668,11 +670,13 @@ void deinit_vulkan(struct graphics_context_t* context)
|
|||||||
vkDestroyFence(context->device, context->in_flight_fences[i], NULL);
|
vkDestroyFence(context->device, context->in_flight_fences[i], NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_textures();
|
destroy_textures(context);
|
||||||
|
|
||||||
destroy_commands(context);
|
destroy_commands(context);
|
||||||
|
|
||||||
destroy_pipeline();
|
destroy_render_pass(context);
|
||||||
|
cleanup_swapchain(context);
|
||||||
|
destroy_pipelines(context);
|
||||||
|
|
||||||
vmaDestroyAllocator(context->allocator);
|
vmaDestroyAllocator(context->allocator);
|
||||||
vkDestroyDevice(context->device, NULL);
|
vkDestroyDevice(context->device, NULL);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "src/graphics_context.h"
|
#include "src/graphics_context.h"
|
||||||
#include "src/vulkan_commons.h"
|
#include "src/vulkan_commons.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
|
#include "utilities/linked_list.h"
|
||||||
#include "vulkan_errors.h"
|
#include "vulkan_errors.h"
|
||||||
#include "utilities/logger.h"
|
#include "utilities/logger.h"
|
||||||
#include "utilities/localization.h"
|
#include "utilities/localization.h"
|
||||||
@@ -321,8 +322,7 @@ 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)
|
rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t image_index)
|
||||||
{
|
{
|
||||||
VkCommandBuffer command_buffer = context->command_buffers[context->current_frame];
|
VkCommandBuffer command_buffer = context->command_buffers[context->current_frame];
|
||||||
VkDescriptorSet descriptor_sets[] = {context->descriptor_sets[context->current_frame],
|
VkDescriptorSet* descriptor_sets = NULL;
|
||||||
context->descriptor_sets_bindless};
|
|
||||||
VkCommandBufferBeginInfo begin_info = {};
|
VkCommandBufferBeginInfo begin_info = {};
|
||||||
VkRenderPassBeginInfo render_pass_info = {};
|
VkRenderPassBeginInfo render_pass_info = {};
|
||||||
VkViewport viewport = {};
|
VkViewport viewport = {};
|
||||||
@@ -331,6 +331,9 @@ rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t ima
|
|||||||
VkClearValue clear_values[2] = {}; //For color and depth stencil
|
VkClearValue clear_values[2] = {}; //For color and depth stencil
|
||||||
size_t i = 0U;
|
size_t i = 0U;
|
||||||
|
|
||||||
|
|
||||||
|
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[0] = 0.0f;
|
||||||
clear_values[0].color.float32[1] = 0.0f;
|
clear_values[0].color.float32[1] = 0.0f;
|
||||||
clear_values[0].color.float32[2] = 0.0f;
|
clear_values[0].color.float32[2] = 0.0f;
|
||||||
@@ -357,7 +360,8 @@ rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t ima
|
|||||||
render_pass_info.pClearValues = clear_values;
|
render_pass_info.pClearValues = clear_values;
|
||||||
|
|
||||||
vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->graphics_pipeline);
|
/* TODO: Iterate over pipelines, do NOT hardocde 0 here */
|
||||||
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipelines[0]);
|
||||||
|
|
||||||
viewport.x = 0.0f;
|
viewport.x = 0.0f;
|
||||||
viewport.y = 0.0f;
|
viewport.y = 0.0f;
|
||||||
@@ -374,7 +378,7 @@ rse_err_t record_command_buffer(struct graphics_context_t* context, uint32_t ima
|
|||||||
|
|
||||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, &context->vertex_buffer.buffer, offsets);
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, &context->vertex_buffer.buffer, offsets);
|
||||||
vkCmdBindIndexBuffer(command_buffer, context->index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(command_buffer, context->index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||||
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipeline_layout, 0, 2,
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipeline_layout, 0, 2,
|
||||||
descriptor_sets, 0, NULL);
|
descriptor_sets, 0, NULL);
|
||||||
|
|
||||||
for (i = 0; i < MAX_MESH_NUMBER; ++i) {
|
for (i = 0; i < MAX_MESH_NUMBER; ++i) {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ enum vulkan_error_t
|
|||||||
VULKAN_ERROR_PIPELINE_MISSING_SHADER_MODULES,
|
VULKAN_ERROR_PIPELINE_MISSING_SHADER_MODULES,
|
||||||
VULKAN_ERROR_DRAW_FAILED,
|
VULKAN_ERROR_DRAW_FAILED,
|
||||||
VULKAN_ERROR_PIPELINE_ALREADY_INITIALIZED,
|
VULKAN_ERROR_PIPELINE_ALREADY_INITIALIZED,
|
||||||
|
VULKAN_ERROR_UNKNOWN_DESCRIPTOR_TYPE,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "src/vulkan_pipeline.h"
|
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
#include "utilities/file_utils.h"
|
#include "utilities/file_utils.h"
|
||||||
@@ -18,8 +17,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "stb_image.h"
|
#include "stb/stb_image.h"
|
||||||
#include "vma/vk_mem_alloc.h"
|
|
||||||
|
|
||||||
#define IMAGE_TAKEN 1U
|
#define IMAGE_TAKEN 1U
|
||||||
#define IMAGE_FREE 0U
|
#define IMAGE_FREE 0U
|
||||||
@@ -190,7 +188,7 @@ rse_err_t create_color_resource(struct graphics_context_t* context)
|
|||||||
create_image(context, &context->color_image,
|
create_image(context, &context->color_image,
|
||||||
physical_device_surface_capabilities.currentExtent.width,
|
physical_device_surface_capabilities.currentExtent.width,
|
||||||
physical_device_surface_capabilities.currentExtent.height,
|
physical_device_surface_capabilities.currentExtent.height,
|
||||||
color_format, VK_SAMPLE_COUNT_16_BIT,
|
color_format, VK_SAMPLE_COUNT_8_BIT,
|
||||||
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
|
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
|
||||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
0U));
|
0U));
|
||||||
@@ -215,7 +213,7 @@ rse_err_t create_depth_resources(struct graphics_context_t* context)
|
|||||||
create_image(context, &context->depth_image,
|
create_image(context, &context->depth_image,
|
||||||
physical_device_surface_capabilities.currentExtent.width,
|
physical_device_surface_capabilities.currentExtent.width,
|
||||||
physical_device_surface_capabilities.currentExtent.height,
|
physical_device_surface_capabilities.currentExtent.height,
|
||||||
depth_format, VK_SAMPLE_COUNT_16_BIT,
|
depth_format, VK_SAMPLE_COUNT_8_BIT,
|
||||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0U));
|
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0U));
|
||||||
STATUS_CHECK(create_image_view(context, &context->depth_image, depth_format,
|
STATUS_CHECK(create_image_view(context, &context->depth_image, depth_format,
|
||||||
VK_IMAGE_ASPECT_DEPTH_BIT));
|
VK_IMAGE_ASPECT_DEPTH_BIT));
|
||||||
@@ -349,7 +347,7 @@ static rse_err_t create_textured_image(struct graphics_context_t* context,
|
|||||||
|
|
||||||
STATUS_CHECK(create_image(
|
STATUS_CHECK(create_image(
|
||||||
context, free_texture_image, width, height, format,
|
context, free_texture_image, width, height, format,
|
||||||
VK_SAMPLE_COUNT_1_BIT,
|
VK_SAMPLE_COUNT_8_BIT,
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT));
|
VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* @file vulkan_render_pass.c
|
||||||
|
* @author Piotr Krygier (piotrkrygier@everyonecancode.xyz)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 20-02-2025
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2025
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vulkan_render_pass.h"
|
||||||
|
|
||||||
|
#include "vulkan_image.h"
|
||||||
|
#include "vulkan_errors.h"
|
||||||
|
#include "utilities/errors_common.h"
|
||||||
|
#include "utilities/logger.h"
|
||||||
|
#include "utilities/localization.h"
|
||||||
|
|
||||||
|
rse_err_t create_render_pass(struct graphics_context_t* context)
|
||||||
|
{
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
VkAttachmentDescription attachments[3] = {};
|
||||||
|
VkAttachmentDescription color_attachment = {};
|
||||||
|
VkAttachmentReference color_attachment_ref = {};
|
||||||
|
VkAttachmentDescription color_attachment_resolve = {};
|
||||||
|
VkAttachmentReference color_attachment_resolve_ref = {};
|
||||||
|
VkSubpassDescription subpass = {};
|
||||||
|
VkRenderPassCreateInfo renderpass_info = {};
|
||||||
|
VkAttachmentDescription depth_attachment = {};
|
||||||
|
VkAttachmentReference depth_attachment_ref = {};
|
||||||
|
VkSubpassDependency dependency = {};
|
||||||
|
|
||||||
|
STATUS_CHECK(find_depth_format(context, &depth_attachment.format));
|
||||||
|
|
||||||
|
depth_attachment.samples = VK_SAMPLE_COUNT_8_BIT;
|
||||||
|
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
|
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
depth_attachment.finalLayout =
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
depth_attachment_ref.attachment = 1;
|
||||||
|
depth_attachment_ref.layout =
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
color_attachment.flags = 0U;
|
||||||
|
color_attachment.format = IMAGE_FORMAT;
|
||||||
|
color_attachment.samples = VK_SAMPLE_COUNT_8_BIT;
|
||||||
|
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
|
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
|
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
color_attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
color_attachment_ref.attachment = 0;
|
||||||
|
color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
color_attachment_resolve.format = IMAGE_FORMAT;
|
||||||
|
color_attachment_resolve.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
color_attachment_resolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
color_attachment_resolve.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
color_attachment_resolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||||
|
color_attachment_resolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||||
|
color_attachment_resolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
color_attachment_resolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
|
|
||||||
|
color_attachment_resolve_ref.attachment = 2;
|
||||||
|
color_attachment_resolve_ref.layout =
|
||||||
|
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
|
||||||
|
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
subpass.colorAttachmentCount = 1;
|
||||||
|
subpass.pColorAttachments = &color_attachment_ref;
|
||||||
|
subpass.pDepthStencilAttachment = &depth_attachment_ref;
|
||||||
|
subpass.pResolveAttachments = &color_attachment_resolve_ref;
|
||||||
|
|
||||||
|
attachments[0] = color_attachment;
|
||||||
|
attachments[1] = depth_attachment;
|
||||||
|
attachments[2] = color_attachment_resolve;
|
||||||
|
|
||||||
|
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||||
|
dependency.dstSubpass = 0;
|
||||||
|
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
|
dependency.srcAccessMask = 0;
|
||||||
|
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
|
||||||
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
|
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||||
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
|
|
||||||
|
renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
|
renderpass_info.attachmentCount = 3;
|
||||||
|
renderpass_info.pAttachments = attachments;
|
||||||
|
renderpass_info.subpassCount = 1;
|
||||||
|
renderpass_info.pSubpasses = &subpass;
|
||||||
|
renderpass_info.dependencyCount = 1;
|
||||||
|
renderpass_info.pDependencies = &dependency;
|
||||||
|
|
||||||
|
if (VK_SUCCESS != vkCreateRenderPass(context->device, &renderpass_info,
|
||||||
|
NULL, &context->render_pass)) {
|
||||||
|
LOGF(_("Failed to create render pass\n"));
|
||||||
|
return VULKAN_ERROR_RENDERPASS_CREATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_render_pass(struct graphics_context_t* context)
|
||||||
|
{
|
||||||
|
vkDestroyRenderPass(context->device, context->render_pass, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* @file vulkan_render_pass.h
|
||||||
|
* @author Piotr Krygier (piotrkrygier@everyonecancode.xyz)
|
||||||
|
* @brief
|
||||||
|
* @version 0.1
|
||||||
|
* @date 20-02-2025
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2025
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VULKAN_RENDER_PASS_H_
|
||||||
|
#define VULKAN_RENDER_PASS_H_
|
||||||
|
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
#include "graphics_context.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a render pass
|
||||||
|
*
|
||||||
|
* @param context Graphics context
|
||||||
|
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||||
|
*/
|
||||||
|
rse_err_t create_render_pass(struct graphics_context_t* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy render pass
|
||||||
|
*
|
||||||
|
* @param context Graphics context
|
||||||
|
*/
|
||||||
|
void destroy_render_pass(struct graphics_context_t* context);
|
||||||
|
|
||||||
|
#endif /* VULKAN_RENDER_PASS_H_ */
|
||||||
@@ -16,4 +16,12 @@ void cleanup_swapchain(struct graphics_context_t* context);
|
|||||||
*/
|
*/
|
||||||
void recreate_swapchain(struct graphics_context_t* context);
|
void recreate_swapchain(struct graphics_context_t* context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a swapchain and framebuffers object
|
||||||
|
*
|
||||||
|
* @param context graphical context
|
||||||
|
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||||
|
*/
|
||||||
|
rse_err_t create_swapchain_and_framebuffers(struct graphics_context_t* context);
|
||||||
|
|
||||||
#endif /* VULKAN_SWAPCHAIN_H */
|
#endif /* VULKAN_SWAPCHAIN_H */
|
||||||
@@ -61,7 +61,7 @@ static void framebuffer_resized_callback(GLFWwindow* window, int width, int heig
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rse_err_t window_init(GLFWwindow* window_handle, bool* is_framebuffer_resized)
|
rse_err_t window_init(GLFWwindow** window_handle, bool* is_framebuffer_resized)
|
||||||
{
|
{
|
||||||
/* Initiliaze GLFW AP */
|
/* Initiliaze GLFW AP */
|
||||||
if (GLFW_TRUE != glfwInit())
|
if (GLFW_TRUE != glfwInit())
|
||||||
@@ -83,16 +83,16 @@ rse_err_t window_init(GLFWwindow* window_handle, bool* is_framebuffer_resized)
|
|||||||
/* Create window */
|
/* Create window */
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
|
||||||
window_handle = glfwCreateWindow(640, 480, "RedScarfEngine", NULL, NULL);
|
*window_handle = glfwCreateWindow(640, 480, "RedScarfEngine", NULL, NULL);
|
||||||
|
|
||||||
if (NULL == window_handle) {
|
if (NULL == *window_handle) {
|
||||||
LOGF(_("Window context creation failed\n"));
|
LOGF(_("Window context creation failed\n"));
|
||||||
return WINDOW_ERROR_WINDOW_NOT_CREATED;
|
return WINDOW_ERROR_WINDOW_NOT_CREATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwSetKeyCallback(window_handle, key_callback);
|
glfwSetKeyCallback(*window_handle, key_callback);
|
||||||
glfwSetFramebufferSizeCallback(window_handle, framebuffer_resized_callback);
|
glfwSetFramebufferSizeCallback(*window_handle, framebuffer_resized_callback);
|
||||||
glfwSetWindowUserPointer(window_handle, is_framebuffer_resized);
|
glfwSetWindowUserPointer(*window_handle, is_framebuffer_resized);
|
||||||
|
|
||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
* WINDOW_WINDOW_NOT_CREATED
|
* WINDOW_WINDOW_NOT_CREATED
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
rse_err_t window_init(GLFWwindow* window_handle, bool* is_framebuffer_resized);
|
rse_err_t window_init(GLFWwindow** window_handle, bool* is_framebuffer_resized);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Main window loop
|
* @brief Main window loop
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
#include "graphics/graphics.h"
|
|
||||||
#include "graphics/rse_graphics.h"
|
#include "graphics/rse_graphics.h"
|
||||||
#include "utilities/task.h"
|
#include "utilities/task.h"
|
||||||
|
#include "utilities/errors_common.h"
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
thread_t graphics_task;
|
thread_t graphics_task;
|
||||||
struct rse_graphics_context_t* context = NULL;
|
struct rse_graphics_context_t* context = NULL;
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
rse_graphics_init(context);
|
STATUS_CHECK(rse_graphics_init(&context));
|
||||||
rse_graphics_test_function(context);
|
rse_graphics_test_function(context);
|
||||||
create_task(&graphics_task, (thread_worker_t)rse_graphics_run, context);
|
create_task(&graphics_task, (thread_worker_t)rse_graphics_run, context);
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
enum common_error_t
|
enum common_error_t
|
||||||
{
|
{
|
||||||
RSE_ERROR_NO_ERROR = RSE_COMMON_MODULE_ID,
|
RSE_ERROR_NO_ERROR = RSE_COMMON_MODULE_ID,
|
||||||
|
RSE_ERROR_NULL_POINTER,
|
||||||
RSE_ERROR_ALREADY_INITIALIZED,
|
RSE_ERROR_ALREADY_INITIALIZED,
|
||||||
RSE_COMMON_ERROR_MALLLOC_FAILED,
|
RSE_COMMON_ERROR_MALLLOC_FAILED,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define RSE_LINKED_LIST_IS_EMPTY(list) \
|
#define RSE_LINKED_LIST_IS_EMPTY(list) \
|
||||||
list == NULL
|
(list == NULL)
|
||||||
|
|
||||||
#define RSE_LINKED_LIST_SIZE(list) \
|
#define RSE_LINKED_LIST_SIZE(list) \
|
||||||
({ \
|
({ \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "file_utils.h"
|
#include "utilities/file_utils.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "logger.h"
|
#include "utilities/logger.h"
|
||||||
#include "stdarg.h"
|
#include "stdarg.h"
|
||||||
|
|
||||||
const char* log_levels[] = {
|
const char* log_levels[] = {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "task.h"
|
#include "utilities/task.h"
|
||||||
|
|
||||||
uint8_t create_task(thread_t* thread_id, thread_worker_t callback, void* args)
|
uint8_t create_task(thread_t* thread_id, thread_worker_t callback, void* args)
|
||||||
{
|
{
|
||||||
|
|||||||
+5
-5
@@ -28,18 +28,18 @@
|
|||||||
stack.data[stack.top]
|
stack.data[stack.top]
|
||||||
|
|
||||||
#define RSE_STACK_IS_EMPTY(stack) \
|
#define RSE_STACK_IS_EMPTY(stack) \
|
||||||
stack.top == -1
|
(stack.top == -1)
|
||||||
|
|
||||||
#define RSE_STACK_IS_FULL(stack, size) \
|
#define RSE_STACK_IS_FULL(stack, size) \
|
||||||
stack.top == size - 1
|
(stack.top == size - 1)
|
||||||
|
|
||||||
#define RSE_STACK_INIT(stack) \
|
#define RSE_STACK_INIT(stack) \
|
||||||
stack.top = -1
|
(stack.top = -1)
|
||||||
|
|
||||||
#define RSE_STACK_SIZE(stack) \
|
#define RSE_STACK_SIZE(stack) \
|
||||||
stack.top + 1
|
(stack.top + 1)
|
||||||
|
|
||||||
#define RSE_STACK_CLEAR(stack) \
|
#define RSE_STACK_CLEAR(stack) \
|
||||||
stack.top = -1
|
(stack.top = -1)
|
||||||
|
|
||||||
#endif // STACK_H
|
#endif // STACK_H
|
||||||
Reference in new issue
Block a user