Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbccf7f0ba | |||
| ca1477b500 | |||
| ceb9e365de | |||
| 4c706982f1 | |||
| c531f5fb55 | |||
| 99fb36d9fd | |||
| 984a56a8e8 | |||
| dd70f5e5b0 | |||
| c6825caa69 | |||
| bbbe69d73c | |||
| 7d6156be01 | |||
| 415d4394c2 | |||
| de597ebc5d | |||
| ff527767b9 | |||
| b8fc36910f | |||
| b8509a9a68 |
+4
-2
@@ -52,5 +52,7 @@ CMakeFiles/
|
|||||||
.clangd/
|
.clangd/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
||||||
# Environment preparation scripts
|
# Ignore subproject path except config files
|
||||||
setup-env.sh
|
subprojects/*
|
||||||
|
!subprojects/packagefiles/
|
||||||
|
!subprojects/*.wrap
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -0,0 +1,18 @@
|
|||||||
|
rse_events_sources = [
|
||||||
|
'src/events_manager.c'
|
||||||
|
]
|
||||||
|
|
||||||
|
sdl3_dep = dependency('sdl3',
|
||||||
|
version : '>=3.4.0')
|
||||||
|
|
||||||
|
rse_events_lib = shared_library(
|
||||||
|
'rse_events',
|
||||||
|
rse_events_sources,
|
||||||
|
include_directories : [
|
||||||
|
'../'
|
||||||
|
],
|
||||||
|
dependencies : [sdl3_dep,
|
||||||
|
],
|
||||||
|
link_with: rse_utilities_lib,
|
||||||
|
install : true
|
||||||
|
)
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @file events_manager.h
|
||||||
|
* @author Piotr Krygier (piotrkrygier@everyonencancode.xyz)
|
||||||
|
* @brief Events manager for Red Scarf Engine
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-03-02
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RSE_EVENTS_MANAGER_H_
|
||||||
|
#define RSE_EVENTS_MANAGER_H_
|
||||||
|
|
||||||
|
#include "src/events_context.h"
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
|
||||||
|
rse_err_t rse_events_init(struct events_context_t* events_context);
|
||||||
|
|
||||||
|
rse_err_t rse_events_set_event_handler(struct events_context_t* events_context,
|
||||||
|
enum EVENT_HANDLER event_type,
|
||||||
|
rse_event_handler_t event_handler);
|
||||||
|
|
||||||
|
rse_err_t rse_events_main_loop(struct events_context_t* context);
|
||||||
|
|
||||||
|
#endif /* RSE_EVENTS_MANAGER_H_ */
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* @file events_context.h
|
||||||
|
* @author Piotr Krygier (piotrkrygier@everyonencancode.xyz)
|
||||||
|
* @brief Events context for Red Scarf Engine
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-03-02
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_CONTEXT_H_
|
||||||
|
#define EVENT_CONTEXT_H_
|
||||||
|
|
||||||
|
#include "SDL3/SDL_mouse.h"
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
|
||||||
|
enum EVENT_HANDLER {
|
||||||
|
EVENT_HANDLER_QUIT,
|
||||||
|
EVENT_HANDLER_MOUSE,
|
||||||
|
EVENT_HANDLER_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EVENT_SHOULD_STOP_ENGINE {
|
||||||
|
EVENT_SHOULD_STOP_ENGINE_FALSE,
|
||||||
|
EVENT_SHOULD_STOP_ENGINE_TRUE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mouse_event_data_t
|
||||||
|
{
|
||||||
|
float x_pos;
|
||||||
|
float y_pos;
|
||||||
|
SDL_MouseButtonFlags mouse_buttons;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef rse_err_t (*rse_event_handler_t)(void*);
|
||||||
|
|
||||||
|
struct events_context_t
|
||||||
|
{
|
||||||
|
enum EVENT_SHOULD_STOP_ENGINE should_stop;
|
||||||
|
rse_event_handler_t event_handlers[EVENT_HANDLER_LAST];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* EVENT_CONTEXT_H_ */
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/**
|
||||||
|
* @file events_manager.c
|
||||||
|
* @author Piotr Krygier (piotrkrygier@everyonencancode.xyz)
|
||||||
|
* @brief Events manager for Red Scarf Engine
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-03-02
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL3/SDL_events.h"
|
||||||
|
#include "SDL3/SDL_log.h"
|
||||||
|
#include "SDL3/SDL_mouse.h"
|
||||||
|
#include "events_context.h"
|
||||||
|
#include "rse_events_manager.h"
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
#include "utilities/errors_common.h"
|
||||||
|
|
||||||
|
static rse_err_t default_event(void* args)
|
||||||
|
{
|
||||||
|
(void)args;
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rse_err_t run_custom_event_handler(struct events_context_t* context,
|
||||||
|
enum EVENT_HANDLER event_handler,
|
||||||
|
void* args)
|
||||||
|
{
|
||||||
|
return context->event_handlers[event_handler](args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rse_err_t quit_event(struct events_context_t* context)
|
||||||
|
{
|
||||||
|
context->should_stop = EVENT_SHOULD_STOP_ENGINE_TRUE;
|
||||||
|
|
||||||
|
return run_custom_event_handler(context, EVENT_HANDLER_QUIT, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static rse_err_t mouse_event(struct events_context_t* context)
|
||||||
|
{
|
||||||
|
struct mouse_event_data_t mouse_data = {0};
|
||||||
|
|
||||||
|
mouse_data.mouse_buttons = SDL_GetMouseState(&mouse_data.x_pos, &mouse_data.y_pos);
|
||||||
|
|
||||||
|
return run_custom_event_handler(context, EVENT_HANDLER_MOUSE, (void*)&mouse_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t rse_events_init(struct events_context_t* events_context)
|
||||||
|
{
|
||||||
|
size_t i = 0U;
|
||||||
|
|
||||||
|
for (i = 0U; i < EVENT_HANDLER_LAST; ++i) {
|
||||||
|
events_context->event_handlers[i] = default_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t rse_events_set_event_handler(struct events_context_t* events_context,
|
||||||
|
enum EVENT_HANDLER event_type,
|
||||||
|
rse_event_handler_t event_handler)
|
||||||
|
{
|
||||||
|
if (event_type >= EVENT_HANDLER_LAST) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Invalid event type selected");
|
||||||
|
|
||||||
|
return RSE_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event_handler == NULL) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL event handler");
|
||||||
|
|
||||||
|
return RSE_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
events_context->event_handlers[event_type] = event_handler;
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t rse_events_main_loop(struct events_context_t* context)
|
||||||
|
{
|
||||||
|
SDL_Event event;
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_EVENT_QUIT:
|
||||||
|
STATUS_CHECK(quit_event(context));
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||||
|
STATUS_CHECK(mouse_event(context));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
+30
-21
@@ -9,41 +9,50 @@ rse_graphics_sources = [
|
|||||||
'src/vulkan_base.c',
|
'src/vulkan_base.c',
|
||||||
'src/vulkan_buffers.c',
|
'src/vulkan_buffers.c',
|
||||||
'src/vulkan_commands.c',
|
'src/vulkan_commands.c',
|
||||||
'src/vulkan_commons.c',
|
|
||||||
'src/vulkan_image.c',
|
'src/vulkan_image.c',
|
||||||
'src/vulkan_render_pass.c',
|
'src/vulkan_render_pass.c',
|
||||||
'src/vulkan_swapchain.c',
|
'src/vulkan_swapchain.c',
|
||||||
'src/window.c',
|
'src/window.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
vulkan_dep = dependency('vulkan',
|
vulkan_headers_dep = dependency('VulkanHeaders')
|
||||||
version : '>=1.4.335')
|
|
||||||
|
|
||||||
sdl3_dep = dependency('sdl3',
|
vulkan_dep = dependency('Vulkan')
|
||||||
version : '>=3.4.0')
|
|
||||||
|
|
||||||
freetype_dep = dependency('freetype2',
|
sdl3_dep = dependency('sdl3', version: '>=3.4.0')
|
||||||
version : '>=22.1.16')
|
|
||||||
glm_dep = dependency('glm',
|
freetype_dep = dependency('freetype2', version: '>=22.1.16')
|
||||||
version : '>=1.0.3',
|
glm_dep = dependency('cglm', version: '>=0.9.6', method: 'cmake')
|
||||||
method : 'cmake')
|
|
||||||
vma_dep = dependency('VulkanMemoryAllocator',
|
vma_dep = dependency('VulkanMemoryAllocator', version: '>=3.3.0')
|
||||||
version : '>=3.3.0',
|
|
||||||
modules : ['GPUOpen::VulkanMemoryAllocator'])
|
stb = dependency('stb',
|
||||||
|
fallback: ['stb', 'stb_dep'])
|
||||||
|
|
||||||
rse_graphics_lib = shared_library(
|
rse_graphics_lib = shared_library(
|
||||||
'rse_graphics',
|
'rse_graphics',
|
||||||
rse_graphics_sources,
|
rse_graphics_sources,
|
||||||
include_directories : [
|
include_directories: ['../'],
|
||||||
'../'
|
dependencies: [
|
||||||
],
|
vulkan_headers_dep,
|
||||||
dependencies : [vulkan_dep,
|
vulkan_dep,
|
||||||
vma_dep,
|
vma_dep,
|
||||||
sdl3_dep,
|
sdl3_dep,
|
||||||
freetype_dep,
|
freetype_dep,
|
||||||
glm_dep,
|
glm_dep,
|
||||||
stb_dep,
|
stb
|
||||||
],
|
],
|
||||||
link_with: rse_utilities_lib,
|
link_with: rse_utilities_lib,
|
||||||
install : true
|
install: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rse_graphics_lib_dep = declare_dependency(
|
||||||
|
link_with: rse_graphics_lib,
|
||||||
|
dependencies: [
|
||||||
|
vulkan_headers_dep,
|
||||||
|
vulkan_dep,
|
||||||
|
vma_dep,
|
||||||
|
glm_dep
|
||||||
|
],
|
||||||
|
include_directories: include_directories('.')
|
||||||
|
)
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
#ifndef RSE_GRAPHICS_H
|
#ifndef RSE_GRAPHICS_H
|
||||||
#define RSE_GRAPHICS_H
|
#define RSE_GRAPHICS_H
|
||||||
|
|
||||||
|
#include "src/graphics_context.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
|
|
||||||
struct rse_graphics_context_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes graphics backend. This has to be called before any new mesh, texture or any other object is
|
* @brief Initializes graphics backend. This has to be called before any new mesh, texture or any other object is
|
||||||
* added
|
* added
|
||||||
@@ -12,20 +11,24 @@ 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 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
|
||||||
*
|
*
|
||||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||||
*/
|
*/
|
||||||
int rse_graphics_run(void* arg);
|
rse_err_t rse_graphics_run(struct graphics_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
|
rse_err_t rse_graphics_main_loop(struct graphics_context_t* context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom function for testing engine. TODO: Remove it whe releasing
|
* @brief Custom function for testing engine. TODO: Remove it whe releasing
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* context);
|
rse_err_t rse_graphics_test_function(struct graphics_context_t* context);
|
||||||
|
|
||||||
|
void rse_graphics_deinit(struct graphics_context_t* context);
|
||||||
|
|
||||||
#endif /* RSE_GRAPHICS_H */
|
#endif /* RSE_GRAPHICS_H */
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(binding = 0) uniform UniformBufferObject {
|
layout(push_constant) uniform pc {
|
||||||
mat4 model;
|
mat4 model;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 proj;
|
mat4 proj;
|
||||||
} ubo;
|
} ubo;
|
||||||
|
|
||||||
#define MAX_INSTANCES 1024
|
|
||||||
|
|
||||||
struct InstanceData
|
struct InstanceData
|
||||||
{
|
{
|
||||||
vec3 pos;
|
vec3 pos;
|
||||||
@@ -16,8 +14,8 @@ struct InstanceData
|
|||||||
uint texture_id;
|
uint texture_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 1) uniform InstanceUniformBuffer {
|
layout(set=0, binding = 0, std430) readonly buffer InstanceBuffer {
|
||||||
InstanceData instances[MAX_INSTANCES];
|
InstanceData instances[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) in vec3 inPosition;
|
layout(location = 0) in vec3 inPosition;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#version 450
|
#version 450
|
||||||
#extension GL_EXT_nonuniform_qualifier : enable
|
#extension GL_EXT_nonuniform_qualifier : enable
|
||||||
|
|
||||||
layout(set = 0, binding = 2) uniform sampler2D texSampler[];
|
layout(set = 0, binding = 1) uniform sampler2D texSampler[];
|
||||||
|
|
||||||
layout(location = 0) in vec3 fragColor;
|
layout(location = 0) in vec3 fragColor;
|
||||||
layout(location = 1) in vec2 fragTexCoord;
|
layout(location = 1) in vec2 fragTexCoord;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "utilities/entity.h"
|
#include "utilities/entity.h"
|
||||||
#include "utilities/vector.h"
|
#include "utilities/vector.h"
|
||||||
#include "vma/vk_mem_alloc.h"
|
#include "vk_mem_alloc.h"
|
||||||
#include "vulkan/vulkan_core.h"
|
#include "vulkan/vulkan_core.h"
|
||||||
#include "vulkan_commons.h"
|
#include "vulkan_commons.h"
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
#define MAX_VERTEX_BINDINGS_COUNT (32U)
|
#define MAX_VERTEX_BINDINGS_COUNT (32U)
|
||||||
#define MAX_SHADER_ATTRIBUTES_COUNT (32U)
|
#define MAX_SHADER_ATTRIBUTES_COUNT (32U)
|
||||||
#define MAX_DYNAMIC_STATES_COUNT (32U)
|
#define MAX_DYNAMIC_STATES_COUNT (32U)
|
||||||
|
#define MAX_PUSH_CONSTANTS_COUNT (32U)
|
||||||
|
|
||||||
#define DESCRIPTOR_MAX_SETS (32U)
|
#define DESCRIPTOR_MAX_SETS (32U)
|
||||||
#define DESCRIPTOR_TYPE_ID_MAX_ENUM (21U)
|
#define DESCRIPTOR_TYPE_ID_MAX_ENUM (21U)
|
||||||
@@ -126,6 +127,12 @@ struct required_dynamic_states_t {
|
|||||||
VkDynamicState dynamic_states[MAX_DYNAMIC_STATES_COUNT];
|
VkDynamicState dynamic_states[MAX_DYNAMIC_STATES_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct push_constant_ranges_t
|
||||||
|
{
|
||||||
|
size_t push_constant_ranges_count;
|
||||||
|
VkPushConstantRange push_constant_ranges[MAX_PUSH_CONSTANTS_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
struct pipeline_infos_t
|
struct pipeline_infos_t
|
||||||
{
|
{
|
||||||
size_t pipeline_create_infos_count;
|
size_t pipeline_create_infos_count;
|
||||||
@@ -159,6 +166,7 @@ struct pipeline_t
|
|||||||
VkVertexInputAttributeDescription shader_attributes[MAX_SHADER_ATTRIBUTES_COUNT];
|
VkVertexInputAttributeDescription shader_attributes[MAX_SHADER_ATTRIBUTES_COUNT];
|
||||||
size_t dynamic_states_count;
|
size_t dynamic_states_count;
|
||||||
VkDynamicState dynamic_states[MAX_DYNAMIC_STATES_COUNT];
|
VkDynamicState dynamic_states[MAX_DYNAMIC_STATES_COUNT];
|
||||||
|
struct push_constant_ranges_t push_constant_ranges;
|
||||||
struct required_dynamic_states_t required_dynamic_states;
|
struct required_dynamic_states_t required_dynamic_states;
|
||||||
struct descriptor_set_handle_t* descriptor_sets;
|
struct descriptor_set_handle_t* descriptor_sets;
|
||||||
};
|
};
|
||||||
@@ -273,6 +281,7 @@ struct graphics_context_t
|
|||||||
uint32_t current_frame;
|
uint32_t current_frame;
|
||||||
uint32_t swapchain_images_count;
|
uint32_t swapchain_images_count;
|
||||||
SDL_Window* window_handle;
|
SDL_Window* window_handle;
|
||||||
|
struct mvp_data_t mvp_data;
|
||||||
struct renderer_data_t renderer_data;
|
struct renderer_data_t renderer_data;
|
||||||
struct debug_overlay_t debug_overlay;
|
struct debug_overlay_t debug_overlay;
|
||||||
struct vulkan_handles vulkan_handles;
|
struct vulkan_handles vulkan_handles;
|
||||||
|
|||||||
@@ -10,14 +10,18 @@
|
|||||||
*/
|
*/
|
||||||
#include <SDL3/SDL_log.h>
|
#include <SDL3/SDL_log.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "src/graphics_context.h"
|
#include "src/graphics_context.h"
|
||||||
#include "src/vulkan_commons.h"
|
#include "src/vulkan_commons.h"
|
||||||
|
#include "utilities/cgltf.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/entity.h"
|
#include "utilities/entity.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
|
#include "utilities/file_utils.h"
|
||||||
#include "vulkan_buffers.h"
|
#include "vulkan_buffers.h"
|
||||||
|
#include "vulkan_image.h"
|
||||||
|
|
||||||
rse_err_t mesh_create(struct graphics_context_t* context,
|
rse_err_t mesh_create(struct graphics_context_t* context,
|
||||||
struct vertex_t* vertices,
|
struct vertex_t* vertices,
|
||||||
@@ -46,6 +50,152 @@ rse_err_t mesh_create(struct graphics_context_t* context,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id, rse_id_t* texture_id)
|
||||||
|
{
|
||||||
|
struct vertex_t* vertices = NULL;
|
||||||
|
uint16_t* indices = NULL;
|
||||||
|
size_t indices_count = 0U;
|
||||||
|
size_t mesh_index = 0U;
|
||||||
|
size_t primitive_index = 0U;
|
||||||
|
size_t attribute_index = 0U;
|
||||||
|
cgltf_mesh* mesh = NULL;
|
||||||
|
cgltf_primitive* primitive = NULL;
|
||||||
|
cgltf_attribute* attribute = NULL;
|
||||||
|
size_t* position_data_offset = NULL;
|
||||||
|
size_t* color_data_offset = NULL;
|
||||||
|
size_t* texture_coord_data_offset = NULL;
|
||||||
|
size_t* indices_data_offset = NULL;
|
||||||
|
size_t* texture_data_offset = NULL;
|
||||||
|
int* texture_data_size = NULL;
|
||||||
|
unsigned char *texture_pixel_buffer = NULL;
|
||||||
|
size_t data_count = 0U;
|
||||||
|
size_t data_index = 0U;
|
||||||
|
size_t tmp_offset = 0U;
|
||||||
|
uint8_t* bin = NULL;
|
||||||
|
|
||||||
|
(void)context;
|
||||||
|
(void)mesh_id;
|
||||||
|
|
||||||
|
cgltf_data* data = NULL;
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
|
STATUS_CHECK(file_load_gltf(file_name, &data));
|
||||||
|
|
||||||
|
for (mesh_index = 0U; mesh_index < data->meshes_count; ++mesh_index) {
|
||||||
|
mesh = &data->meshes[mesh_index];
|
||||||
|
|
||||||
|
for (primitive_index = 0U; primitive_index < mesh->primitives_count; ++primitive_index) {
|
||||||
|
primitive = &mesh->primitives[primitive_index];
|
||||||
|
|
||||||
|
if (primitive->indices == NULL) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU,
|
||||||
|
"No indices for mesh found. Currently only indexed drawing is supported");
|
||||||
|
return RSE_ERROR_INVALID_PARAM;
|
||||||
|
} else {
|
||||||
|
rse_malloc(indices_data_offset, sizeof(size_t));
|
||||||
|
*indices_data_offset = primitive->indices->buffer_view->offset;
|
||||||
|
indices_count = primitive->indices->count;
|
||||||
|
rse_malloc(indices, (sizeof(uint16_t) * indices_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primitive->material != NULL) {
|
||||||
|
if (primitive->material->has_pbr_metallic_roughness) {
|
||||||
|
rse_malloc(texture_data_offset, sizeof(size_t));
|
||||||
|
rse_malloc(texture_data_size, sizeof(int));
|
||||||
|
*texture_data_offset = primitive->material->pbr_metallic_roughness.base_color_texture.texture->image->buffer_view->offset;
|
||||||
|
*texture_data_size = primitive->material->pbr_metallic_roughness.base_color_texture.texture->image->buffer_view->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (attribute_index = 0; attribute_index < primitive->attributes_count; ++attribute_index) {
|
||||||
|
attribute = &primitive->attributes[attribute_index];
|
||||||
|
|
||||||
|
tmp_offset = attribute->data->buffer_view->offset;
|
||||||
|
|
||||||
|
switch (attribute->type) {
|
||||||
|
case cgltf_attribute_type_position:
|
||||||
|
rse_malloc(position_data_offset, sizeof(size_t));
|
||||||
|
*position_data_offset = tmp_offset;
|
||||||
|
data_count = attribute->data->count;
|
||||||
|
break;
|
||||||
|
case cgltf_attribute_type_color:
|
||||||
|
rse_malloc(color_data_offset, sizeof(size_t));
|
||||||
|
*color_data_offset = tmp_offset;
|
||||||
|
break;
|
||||||
|
case cgltf_attribute_type_texcoord:
|
||||||
|
rse_malloc(texture_coord_data_offset, sizeof(size_t));
|
||||||
|
*texture_coord_data_offset = tmp_offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position_data_offset == NULL) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to retrieve position data for mesh %s", file_name);
|
||||||
|
status = RSE_ERROR_INVALID_PARAM;
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_count == 0) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failure: data count for mesh is 0");
|
||||||
|
status = RSE_ERROR_INVALID_PARAM;
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_malloc(vertices, sizeof(struct vertex_t) * data_count);
|
||||||
|
bin = (uint8_t*)data->bin;
|
||||||
|
|
||||||
|
for (data_index = 0U; data_index < data_count; ++data_index) {
|
||||||
|
rse_memcpy(vertices[data_index].pos,
|
||||||
|
(bin + *position_data_offset + (sizeof(vec3) * data_index)),
|
||||||
|
sizeof(vec3));
|
||||||
|
if (color_data_offset != NULL) {
|
||||||
|
rse_memcpy(vertices[data_index].color,
|
||||||
|
(bin + *color_data_offset + (sizeof(vec3) * data_index)),
|
||||||
|
sizeof(vec3));
|
||||||
|
} else {
|
||||||
|
vertices[data_index].color[0] = 1.0;
|
||||||
|
vertices[data_index].color[1] = 1.0;
|
||||||
|
vertices[data_index].color[2] = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_coord_data_offset != NULL) {
|
||||||
|
rse_memcpy(vertices[data_index].tex_coords,
|
||||||
|
(bin + *texture_coord_data_offset + (sizeof(vec2) * data_index)),
|
||||||
|
sizeof(vec2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture_data_offset != NULL) {
|
||||||
|
rse_malloc(texture_pixel_buffer, *texture_data_size);
|
||||||
|
rse_memcpy(texture_pixel_buffer, (bin + *texture_data_offset), *texture_data_size);
|
||||||
|
STATUS_CHECK(texture_load_from_buffer(context, texture_pixel_buffer, *texture_data_size, texture_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_memcpy(indices, (bin + *indices_data_offset), (sizeof(uint16_t) * indices_count));
|
||||||
|
|
||||||
|
STATUS_CHECK(mesh_create(context, vertices, indices, data_count, indices_count, mesh_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
rse_free(position_data_offset);
|
||||||
|
rse_free(color_data_offset);
|
||||||
|
rse_free(texture_coord_data_offset);
|
||||||
|
rse_free(indices_data_offset);
|
||||||
|
rse_free(texture_data_size);
|
||||||
|
rse_free(texture_data_offset);
|
||||||
|
rse_free(texture_pixel_buffer);
|
||||||
|
rse_free(vertices);
|
||||||
|
rse_free(indices);
|
||||||
|
cgltf_free(data);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
rse_err_t mesh_create_instance(struct graphics_context_t* context,
|
rse_err_t mesh_create_instance(struct graphics_context_t* context,
|
||||||
entity_t entity,
|
entity_t entity,
|
||||||
struct instance_data_t instance_data)
|
struct instance_data_t instance_data)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ rse_err_t mesh_create(struct graphics_context_t* context, struct vertex_t* verti
|
|||||||
rse_err_t mesh_create_instance(struct graphics_context_t* context, entity_t entity,
|
rse_err_t mesh_create_instance(struct graphics_context_t* context, entity_t entity,
|
||||||
struct instance_data_t instance_data);
|
struct instance_data_t instance_data);
|
||||||
|
|
||||||
|
rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id, rse_id_t* texture_id);
|
||||||
/**
|
/**
|
||||||
* @brief Get the vertex count for mesh with mesh_id ID
|
* @brief Get the vertex count for mesh with mesh_id ID
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#include "utilities/commons.h"
|
||||||
|
|
||||||
|
rse_err_t object_load_gltf(const char* file_path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ rse_err_t shader_create_module(struct graphics_context_t* context,
|
|||||||
const char* shader_path,
|
const char* shader_path,
|
||||||
const VkShaderStageFlagBits shader_stage)
|
const VkShaderStageFlagBits shader_stage)
|
||||||
{
|
{
|
||||||
char* buffer;
|
unsigned char* buffer;
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
VkShaderModuleCreateInfo create_info = {0};
|
VkShaderModuleCreateInfo create_info = {0};
|
||||||
|
|
||||||
@@ -44,9 +44,9 @@ rse_err_t shader_create_module(struct graphics_context_t* context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read shader file */
|
/* Read shader file */
|
||||||
file_read(shader_path, &buffer_size, NULL);
|
file_read_bytes(shader_path, &buffer_size, NULL);
|
||||||
rse_malloc(buffer, buffer_size);
|
rse_malloc(buffer, buffer_size);
|
||||||
file_read(shader_path, &buffer_size, buffer);
|
file_read_bytes(shader_path, &buffer_size, buffer);
|
||||||
|
|
||||||
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
create_info.pNext = NULL;
|
create_info.pNext = NULL;
|
||||||
@@ -205,8 +205,8 @@ rse_err_t pipeline_add_descriptor_sets(struct graphics_context_t* context,
|
|||||||
create_info.flags = 0U;
|
create_info.flags = 0U;
|
||||||
create_info.setLayoutCount = 1; // FIXME: Make sure we can enable more than one layout
|
create_info.setLayoutCount = 1; // FIXME: Make sure we can enable more than one layout
|
||||||
create_info.pSetLayouts = &context->descriptor_data.set_layouts[descriptor_set_id];
|
create_info.pSetLayouts = &context->descriptor_data.set_layouts[descriptor_set_id];
|
||||||
create_info.pushConstantRangeCount = 0U;
|
create_info.pushConstantRangeCount = pipeline->push_constant_ranges.push_constant_ranges_count;
|
||||||
create_info.pPushConstantRanges = NULL;
|
create_info.pPushConstantRanges = pipeline->push_constant_ranges.push_constant_ranges;
|
||||||
|
|
||||||
if (VK_SUCCESS !=
|
if (VK_SUCCESS !=
|
||||||
vkCreatePipelineLayout(context->vulkan_handles.device, &create_info, NULL, &pipeline->pipeline_layout)) {
|
vkCreatePipelineLayout(context->vulkan_handles.device, &create_info, NULL, &pipeline->pipeline_layout)) {
|
||||||
@@ -341,6 +341,23 @@ 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_push_constants(struct pipeline_t* pipeline,
|
||||||
|
VkShaderStageFlagBits shader_stage,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
pipeline->push_constant_ranges.push_constant_ranges[pipeline->push_constant_ranges.push_constant_ranges_count]
|
||||||
|
.stageFlags = shader_stage;
|
||||||
|
pipeline->push_constant_ranges.push_constant_ranges[pipeline->push_constant_ranges.push_constant_ranges_count]
|
||||||
|
.offset = offset;
|
||||||
|
pipeline->push_constant_ranges.push_constant_ranges[pipeline->push_constant_ranges.push_constant_ranges_count]
|
||||||
|
.size = size;
|
||||||
|
|
||||||
|
pipeline->push_constant_ranges.push_constant_ranges_count++;
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_t* pipelines_infos_list)
|
rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_t* pipelines_infos_list)
|
||||||
{
|
{
|
||||||
assert(NULL != context);
|
assert(NULL != context);
|
||||||
|
|||||||
@@ -92,6 +92,18 @@ rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, const VkDynami
|
|||||||
rse_err_t pipeline_add_descriptor_sets(struct graphics_context_t* context,
|
rse_err_t pipeline_add_descriptor_sets(struct graphics_context_t* context,
|
||||||
struct pipeline_t* pipeline,
|
struct pipeline_t* pipeline,
|
||||||
uint32_t descriptor_set_id);
|
uint32_t descriptor_set_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add push constants to pipeline
|
||||||
|
*
|
||||||
|
* @return RSE_ERROR_NO_ERROR on success
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
rse_err_t pipeline_add_push_constants(struct pipeline_t* pipeline,
|
||||||
|
VkShaderStageFlagBits shader_stage,
|
||||||
|
uint32_t offset,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Build pipeline from added components. This function should be called after adding all necessary components.
|
* @brief Build pipeline from added components. This function should be called after adding all necessary components.
|
||||||
* After call, pipeline is ready to be used and all added components are cleared, ready for next pipeline to be built.
|
* After call, pipeline is ready to be used and all added components are cleared, ready for next pipeline to be built.
|
||||||
|
|||||||
+146
-105
@@ -5,9 +5,7 @@
|
|||||||
#include <SDL3/SDL_render.h>
|
#include <SDL3/SDL_render.h>
|
||||||
#include <cglm/util.h>
|
#include <cglm/util.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include "descriptor_builder.h"
|
#include "descriptor_builder.h"
|
||||||
@@ -19,6 +17,7 @@
|
|||||||
#include "src/vulkan_buffers.h"
|
#include "src/vulkan_buffers.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
|
#include "utilities/time_utils.h"
|
||||||
#include "vulkan_base.h"
|
#include "vulkan_base.h"
|
||||||
#include "vulkan_commons.h"
|
#include "vulkan_commons.h"
|
||||||
#include "vulkan_image.h"
|
#include "vulkan_image.h"
|
||||||
@@ -29,15 +28,65 @@ struct rse_graphics_context_t
|
|||||||
struct graphics_context_t* context;
|
struct graphics_context_t* context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void model_view_projection_update(struct graphics_context_t* context)
|
||||||
|
{
|
||||||
|
vec3 eye = {0};
|
||||||
|
vec3 center = {0};
|
||||||
|
vec3 up = {0};
|
||||||
|
vec3 rotation_vec = {0.0f, 1.0f, 0.0f};
|
||||||
|
float fovy;
|
||||||
|
float z_near;
|
||||||
|
float z_far;
|
||||||
|
static float rotation = 0.0;
|
||||||
|
|
||||||
|
eye[2] = -4.0f;
|
||||||
|
|
||||||
|
up[1] = 1.0f;
|
||||||
|
|
||||||
|
fovy = glm_rad(45.0f);
|
||||||
|
z_near = 0.1f;
|
||||||
|
z_far = 20.0f;
|
||||||
|
|
||||||
|
glm_mat4_identity(context->mvp_data.model);
|
||||||
|
|
||||||
|
glm_rotate(context->mvp_data.model, rotation, rotation_vec);
|
||||||
|
glm_lookat(eye, center, up, context->mvp_data.view);
|
||||||
|
glm_perspective(
|
||||||
|
fovy,
|
||||||
|
context->swapchain_data.swapchain_extent.width / (float)context->swapchain_data.swapchain_extent.height,
|
||||||
|
z_near,
|
||||||
|
z_far,
|
||||||
|
context->mvp_data.proj);
|
||||||
|
|
||||||
|
rotation += time_get_dt() * glm_rad(120.0);
|
||||||
|
}
|
||||||
|
|
||||||
static rse_err_t render_static_mesh(struct graphics_context_t* context, uint32_t renderer_id)
|
static rse_err_t render_static_mesh(struct graphics_context_t* context, uint32_t renderer_id)
|
||||||
{
|
{
|
||||||
VkCommandBuffer command_buffer = context->vulkan_handles.command_buffers[context->current_frame];
|
VkCommandBuffer command_buffer = context->vulkan_handles.command_buffers[context->current_frame];
|
||||||
VkDeviceSize offsets[] = {0};
|
VkDeviceSize offsets[] = {0};
|
||||||
|
uint32_t mvp_offset = 0;
|
||||||
|
uint32_t mvp_size = sizeof(struct mvp_data_t);
|
||||||
|
|
||||||
(void)renderer_id;
|
(void)renderer_id;
|
||||||
|
|
||||||
|
vkCmdPushConstants(command_buffer,
|
||||||
|
context->pipelines_data.pipeline_layouts[0],
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
mvp_offset,
|
||||||
|
mvp_size,
|
||||||
|
&context->mvp_data);
|
||||||
|
model_view_projection_update(context);
|
||||||
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipelines[0]);
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, context->pipelines_data.pipelines[0]);
|
||||||
vkCmdBindIndexBuffer(command_buffer, context->render_targets[RENDER_TARGET_3D].index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(command_buffer,
|
||||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, &context->render_targets[RENDER_TARGET_3D].vertex_buffer.buffer, offsets);
|
context->render_targets[RENDER_TARGET_3D].index_buffer.buffer,
|
||||||
|
0,
|
||||||
|
VK_INDEX_TYPE_UINT16);
|
||||||
|
vkCmdBindVertexBuffers(command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&context->render_targets[RENDER_TARGET_3D].vertex_buffer.buffer,
|
||||||
|
offsets);
|
||||||
/* FIXME: Currently we can only bind one descriptor set */
|
/* FIXME: Currently we can only bind one descriptor set */
|
||||||
vkCmdBindDescriptorSets(command_buffer,
|
vkCmdBindDescriptorSets(command_buffer,
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
@@ -57,100 +106,62 @@ static rse_err_t render_static_mesh(struct graphics_context_t* context, uint32_t
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void model_view_projection_update(struct graphics_context_t* context, const struct vulkan_buffer_t* buffer)
|
rse_err_t rse_graphics_init(struct graphics_context_t* context)
|
||||||
{
|
|
||||||
struct uniform_buffer_object_t ubo = {0};
|
|
||||||
vec3 eye = {0};
|
|
||||||
vec3 center = {0};
|
|
||||||
vec3 up = {0};
|
|
||||||
vec3 rotation_vec = {1.0f, 0.0f, 0.0f};
|
|
||||||
float fovy;
|
|
||||||
float z_near;
|
|
||||||
float z_far;
|
|
||||||
|
|
||||||
eye[2] = -5.0f;
|
|
||||||
|
|
||||||
up[1] = 1.0f;
|
|
||||||
|
|
||||||
fovy = glm_rad(45.0f);
|
|
||||||
z_near = 0.1f;
|
|
||||||
z_far = 20.0f;
|
|
||||||
|
|
||||||
glm_mat4_identity(ubo.model);
|
|
||||||
|
|
||||||
glm_rotate(ubo.model, glm_rad(0.0f), rotation_vec);
|
|
||||||
glm_lookat(eye, center, up, ubo.view);
|
|
||||||
glm_perspective(
|
|
||||||
fovy,
|
|
||||||
context->swapchain_data.swapchain_extent.width / (float)context->swapchain_data.swapchain_extent.height,
|
|
||||||
z_near,
|
|
||||||
z_far,
|
|
||||||
ubo.proj);
|
|
||||||
memcpy(buffer->allocation_info.pMappedData, &ubo, sizeof(ubo));
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
struct rse_graphics_context_t* ctx_ptr = NULL;
|
|
||||||
|
|
||||||
if (*context != NULL) {
|
STATUS_CHECK(window_init(&context->window_handle, &context->is_framebuffer_resized));
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Graphics already initialized!");
|
STATUS_CHECK(vulkan_init(context));
|
||||||
return RSE_ERROR_ALREADY_INITIALIZED;
|
|
||||||
}
|
|
||||||
|
|
||||||
rse_malloc(*context, sizeof(struct rse_graphics_context_t));
|
|
||||||
ctx_ptr = *context;
|
|
||||||
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(&ctx_ptr->context->window_handle, &ctx_ptr->context->is_framebuffer_resized));
|
|
||||||
STATUS_CHECK(vulkan_init(ctx_ptr->context));
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
#define TEXTURES_COUNT (3U)
|
||||||
|
rse_err_t rse_graphics_test_function(struct graphics_context_t* 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;
|
rse_id_t textures[TEXTURES_COUNT] = {0};
|
||||||
rse_id_t textures[2] = {0};
|
|
||||||
struct pipeline_t pipeline;
|
struct pipeline_t pipeline;
|
||||||
rse_id_t descriptor_set_handle = 0;
|
rse_id_t descriptor_set_handle = 0;
|
||||||
struct descriptor_set_layout_bindings_t layout_bindings = {0};
|
struct descriptor_set_layout_bindings_t layout_bindings = {0};
|
||||||
struct pipeline_infos_t pipeline_infos = {0};
|
struct pipeline_infos_t pipeline_infos = {0};
|
||||||
struct vulkan_buffer_t model_view_projection_buffer = {0};
|
rse_id_t mesh_id_1 = 0;
|
||||||
rse_id_t mesh_id_1, mesh_id_2 = 0;
|
rse_id_t mesh_id_2 = 0;
|
||||||
rse_id_t font_id = 0;
|
rse_id_t avocado_id = 0;
|
||||||
|
// rse_id_t font_id = 0;
|
||||||
rse_id_t static_mesh_renderer = 0U;
|
rse_id_t static_mesh_renderer = 0U;
|
||||||
rse_id_t vertex_shader_id, fragment_shader_id;
|
rse_id_t vertex_shader_id, fragment_shader_id;
|
||||||
|
|
||||||
texture_load_from_file(context, "../../test_image.jpg", &textures[0]);
|
STATUS_CHECK(texture_load_from_file(context, "../../test_image.jpg", &textures[0]));
|
||||||
texture_load_from_file(context, "../../test_image_2.jpg", &textures[1]);
|
STATUS_CHECK(texture_load_from_file(context, "../../test_image_2.jpg", &textures[1]));
|
||||||
|
|
||||||
STATUS_CHECK(fonts_init());
|
// STATUS_CHECK(fonts_init());
|
||||||
STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id));
|
// STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id));
|
||||||
STATUS_CHECK(fonts_set_font_size(context, font_id, 16));
|
// STATUS_CHECK(fonts_set_font_size(context, font_id, 16));
|
||||||
|
|
||||||
// FIXME: Temporary array of vertices, for testing purposes
|
// FIXME: Temporary array of vertices, for testing purposes
|
||||||
struct vertex_t vertices[] = {{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
|
struct vertex_t vertices[] = {
|
||||||
|
{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
|
||||||
|
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
|
||||||
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
||||||
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
||||||
{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}};
|
};
|
||||||
|
|
||||||
struct vertex_t vertices2[] = {{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
|
struct vertex_t vertices_2[] = {
|
||||||
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
{{-0.7f, -0.7f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
|
||||||
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
{{-0.7f, 0.7f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}},
|
||||||
{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}};
|
{{0.1f, 0.7f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
||||||
|
{{0.1f, -0.7f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: Temporary array of vertices, for testing purposes
|
// FIXME: Temporary array of vertices, for testing purposes
|
||||||
uint16_t indices[] = {0, 1, 2, 2, 3, 0};
|
uint16_t indices[] = {0, 1, 2, 2, 3, 0, 0, 3, 2, 2, 1, 0};
|
||||||
|
|
||||||
mesh_create(context, vertices, indices, 4, 6, &mesh_id_1);
|
STATUS_CHECK(mesh_create(context, vertices, indices, 4, 12, &mesh_id_1));
|
||||||
if (RSE_ERROR_NO_ERROR !=
|
if (RSE_ERROR_NO_ERROR !=
|
||||||
mesh_create_instance(context,
|
mesh_create_instance(context,
|
||||||
mesh_id_1,
|
mesh_id_1,
|
||||||
(struct instance_data_t){{0.0f, 0.0f, 2.4f}, {0.0f, 0.0f, 0.0}, 1.0f, textures[1]})) {
|
(struct instance_data_t){{0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0}, 0.5f, textures[0]})) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,50 +169,60 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
mesh_create_instance(
|
mesh_create_instance(
|
||||||
context,
|
context,
|
||||||
mesh_id_1,
|
mesh_id_1,
|
||||||
(struct instance_data_t){{-0.5f, 0.0f, -1.0f}, {0.0f, 0.0f, glm_rad(10.0f)}, 1.0f, textures[0]})) {
|
(struct instance_data_t){{-0.5f, 0.0f, -1.0f}, {0.0f, 0.0f, glm_rad(10.0f)}, 0.5f, textures[1]})) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh_create(context, vertices2, indices, 4, 6, &mesh_id_2);
|
STATUS_CHECK(mesh_create(context, vertices_2, indices, 4, 6, &mesh_id_2));
|
||||||
|
|
||||||
if (RSE_ERROR_NO_ERROR !=
|
if (RSE_ERROR_NO_ERROR !=
|
||||||
mesh_create_instance(
|
mesh_create_instance(
|
||||||
context,
|
context,
|
||||||
mesh_id_2,
|
mesh_id_2,
|
||||||
(struct instance_data_t){{1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, glm_rad(0.0f)}, 1.0f, textures[0]})) {
|
(struct instance_data_t){{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, glm_rad(0.0f)}, 0.5f, textures[1]})) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_create_uniform(context, &model_view_projection_buffer, sizeof(struct uniform_buffer_object_t));
|
mesh_create_from_file(context, "../../Avocado.glb", &avocado_id, &textures[2]);
|
||||||
model_view_projection_update(context, &model_view_projection_buffer);
|
if (RSE_ERROR_NO_ERROR !=
|
||||||
buffers_update(context);
|
mesh_create_instance(
|
||||||
|
context,
|
||||||
|
avocado_id,
|
||||||
|
(struct instance_data_t){{0.0f, 0.2f, 0.0f}, {0.0f, 0.0f, glm_rad(180.0f)}, 10.0f, textures[2]})) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
sampler_create(context, &context->vulkan_handles.sampler);
|
STATUS_CHECK(buffers_update(context));
|
||||||
|
|
||||||
descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2);
|
STATUS_CHECK(sampler_create(context, &context->vulkan_handles.sampler));
|
||||||
descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2);
|
|
||||||
descriptor_pool_initialize(context);
|
STATUS_CHECK(descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1));
|
||||||
|
STATUS_CHECK(descriptor_pool_add_type(context, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, TEXTURES_COUNT));
|
||||||
|
STATUS_CHECK(descriptor_pool_initialize(context));
|
||||||
|
|
||||||
/* Normal rendering */
|
/* Normal rendering */
|
||||||
descriptor_create_new_set(context, &descriptor_set_handle);
|
STATUS_CHECK(descriptor_create_new_set(context, &descriptor_set_handle));
|
||||||
descriptor_add_layout(&layout_bindings, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
|
STATUS_CHECK(
|
||||||
descriptor_add_layout(&layout_bindings, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT);
|
descriptor_add_layout(&layout_bindings, 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT));
|
||||||
descriptor_add_layout(&layout_bindings, 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2, VK_SHADER_STAGE_FRAGMENT_BIT);
|
STATUS_CHECK(descriptor_add_layout(&layout_bindings,
|
||||||
descriptor_set_finish(context, &layout_bindings, descriptor_set_handle);
|
1,
|
||||||
descriptor_build_sets(context);
|
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
|
TEXTURES_COUNT,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT));
|
||||||
|
STATUS_CHECK(descriptor_set_finish(context, &layout_bindings, descriptor_set_handle));
|
||||||
|
STATUS_CHECK(descriptor_build_sets(context));
|
||||||
|
|
||||||
descriptor_attach_buffer(context,
|
STATUS_CHECK(descriptor_attach_buffer(context,
|
||||||
descriptor_set_handle,
|
|
||||||
&model_view_projection_buffer,
|
|
||||||
0,
|
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
|
||||||
descriptor_attach_buffer(context,
|
|
||||||
descriptor_set_handle,
|
descriptor_set_handle,
|
||||||
&context->render_targets[RENDER_TARGET_3D].instance_buffer,
|
&context->render_targets[RENDER_TARGET_3D].instance_buffer,
|
||||||
1,
|
0,
|
||||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER));
|
||||||
|
|
||||||
descriptor_attach_images(context, descriptor_set_handle, textures, 2, context->vulkan_handles.sampler, 2);
|
STATUS_CHECK(descriptor_attach_images(context,
|
||||||
|
descriptor_set_handle,
|
||||||
|
textures,
|
||||||
|
TEXTURES_COUNT,
|
||||||
|
context->vulkan_handles.sampler,
|
||||||
|
1));
|
||||||
|
|
||||||
/* Initialize pipeline */
|
/* Initialize pipeline */
|
||||||
pipeline_builder_init(&pipeline);
|
pipeline_builder_init(&pipeline);
|
||||||
@@ -215,12 +236,18 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
|
|
||||||
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, 0, 1, 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, 0, 2, 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_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);
|
||||||
|
|
||||||
|
pipeline_add_push_constants(&pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct mvp_data_t));
|
||||||
pipeline_add_descriptor_sets(context, &pipeline, descriptor_set_handle);
|
pipeline_add_descriptor_sets(context, &pipeline, descriptor_set_handle);
|
||||||
|
|
||||||
pipeline_add(context, &pipeline, &pipeline_infos);
|
pipeline_add(context, &pipeline, &pipeline_infos);
|
||||||
|
|
||||||
pipelines_build(context, &pipeline_infos);
|
pipelines_build(context, &pipeline_infos);
|
||||||
@@ -232,21 +259,35 @@ rse_err_t rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rse_graphics_run(void* arg)
|
rse_err_t rse_graphics_run(struct graphics_context_t* context)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
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(vulkan_run(context));
|
STATUS_CHECK(vulkan_run(context));
|
||||||
STATUS_CHECK(window_loop(context));
|
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t rse_graphics_main_loop(struct graphics_context_t* context)
|
||||||
|
{
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
|
STATUS_CHECK(vulkan_draw_frame(context));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rse_err_t rse_graphics_load_model(struct graphics_context_t* context, const char* model_path, rse_id_t* model_id)
|
||||||
|
// {
|
||||||
|
// rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
//
|
||||||
|
// return status;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void rse_graphics_deinit(struct graphics_context_t* context)
|
||||||
|
{
|
||||||
vulkan_deinit(context);
|
vulkan_deinit(context);
|
||||||
|
|
||||||
window_terminate(context->window_handle);
|
window_terminate(context->window_handle);
|
||||||
rse_free(context->debug_overlay.pixels);
|
rse_free(context->debug_overlay.pixels);
|
||||||
rse_free(context);
|
|
||||||
rse_free(rse_context);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#pragma GCC diagnostic ignored "-Wswitch"
|
#pragma GCC diagnostic ignored "-Wswitch"
|
||||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||||
#endif
|
#endif
|
||||||
#include "vma/vk_mem_alloc.h"
|
#include "vk_mem_alloc.h"
|
||||||
#ifdef __unix__
|
#ifdef __unix__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+83
-51
@@ -15,25 +15,23 @@
|
|||||||
#include <SDL3/SDL_log.h>
|
#include <SDL3/SDL_log.h>
|
||||||
#include <SDL3/SDL_main.h>
|
#include <SDL3/SDL_main.h>
|
||||||
#include <SDL3/SDL_vulkan.h>
|
#include <SDL3/SDL_vulkan.h>
|
||||||
#include <vma/vk_mem_alloc.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
|
#include "pipeline_builder.h"
|
||||||
#include "src/descriptor_builder.h"
|
#include "src/descriptor_builder.h"
|
||||||
#include "src/graphics_context.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 "vulkan/vulkan_core.h"
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
#include "vulkan_commons.h"
|
|
||||||
#include "vulkan_commands.h"
|
|
||||||
#include "vulkan_buffers.h"
|
#include "vulkan_buffers.h"
|
||||||
|
#include "vulkan_commands.h"
|
||||||
|
#include "vulkan_commons.h"
|
||||||
#include "vulkan_image.h"
|
#include "vulkan_image.h"
|
||||||
#include "vulkan_render_pass.h"
|
#include "vulkan_render_pass.h"
|
||||||
#include "vulkan_swapchain.h"
|
#include "vulkan_swapchain.h"
|
||||||
#include "pipeline_builder.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define APPLICATION_NAME "RedScarfEngine PoC"
|
#define APPLICATION_NAME "RedScarfEngine PoC"
|
||||||
#define ENGINE_NAME "RedScarf Engine"
|
#define ENGINE_NAME "RedScarf Engine"
|
||||||
@@ -49,7 +47,8 @@
|
|||||||
*/
|
*/
|
||||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
|
||||||
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
VkDebugUtilsMessageTypeFlagsEXT message_type,
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data)
|
const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
|
||||||
|
void* user_data)
|
||||||
{
|
{
|
||||||
(void)message_severity;
|
(void)message_severity;
|
||||||
(void)message_type;
|
(void)message_type;
|
||||||
@@ -80,7 +79,8 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverity
|
|||||||
* @param debug_messenger Debug messanger handle
|
* @param debug_messenger Debug messanger handle
|
||||||
* @return VkResult VK_SUCCESS on success
|
* @return VkResult VK_SUCCESS on success
|
||||||
*/
|
*/
|
||||||
static VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* create_info,
|
static VkResult CreateDebugUtilsMessengerEXT(VkInstance instance,
|
||||||
|
const VkDebugUtilsMessengerCreateInfoEXT* create_info,
|
||||||
const VkAllocationCallbacks* allocator,
|
const VkAllocationCallbacks* allocator,
|
||||||
VkDebugUtilsMessengerEXT* debug_messenger)
|
VkDebugUtilsMessengerEXT* debug_messenger)
|
||||||
{
|
{
|
||||||
@@ -108,10 +108,9 @@ static rse_err_t setup_debug_messenger(VkInstance instance, VkDebugUtilsMessenge
|
|||||||
|
|
||||||
create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
create_info.pNext = NULL;
|
create_info.pNext = NULL;
|
||||||
create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
create_info.messageSeverity =
|
||||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
||||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
|
||||||
create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||||
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||||
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
@@ -134,7 +133,8 @@ static rse_err_t setup_debug_messenger(VkInstance instance, VkDebugUtilsMessenge
|
|||||||
* @param debug_messenger Debug messanger handle
|
* @param debug_messenger Debug messanger handle
|
||||||
* @param allocator Memory allocator
|
* @param allocator Memory allocator
|
||||||
*/
|
*/
|
||||||
static void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debug_messenger,
|
static void DestroyDebugUtilsMessengerEXT(VkInstance instance,
|
||||||
|
VkDebugUtilsMessengerEXT debug_messenger,
|
||||||
const VkAllocationCallbacks* allocator)
|
const VkAllocationCallbacks* allocator)
|
||||||
{
|
{
|
||||||
PFN_vkDestroyDebugUtilsMessengerEXT func =
|
PFN_vkDestroyDebugUtilsMessengerEXT func =
|
||||||
@@ -211,14 +211,14 @@ static rse_err_t create_instance(VkInstance* instance)
|
|||||||
|
|
||||||
/* Check if selected layers are supported*/
|
/* Check if selected layers are supported*/
|
||||||
for (i = 0; i < enabled_instance_layers_count; ++i) {
|
for (i = 0; i < enabled_instance_layers_count; ++i) {
|
||||||
for(j = 0; i < layersCount; ++j) {
|
for (j = 0; j < layersCount; ++j) {
|
||||||
if(strcmp(layer_properties[j].layerName, enabled_instance_layers_names[i]) == 0) {
|
if (strcmp(layer_properties[j].layerName, enabled_instance_layers_names[i]) == 0) {
|
||||||
supported = 1;
|
supported = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(supported == 0) {
|
if (supported == 0) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Selected layer is not supported: %s", layer_properties[j].layerName);
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Selected layer is not supported: %s", enabled_instance_layers_names[i]);
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
supported = 0;
|
supported = 0;
|
||||||
@@ -226,14 +226,16 @@ static rse_err_t create_instance(VkInstance* instance)
|
|||||||
|
|
||||||
/* Check if selected extensions are supported*/
|
/* Check if selected extensions are supported*/
|
||||||
for (i = 0; i < enabled_instance_extensions_count; ++i) {
|
for (i = 0; i < enabled_instance_extensions_count; ++i) {
|
||||||
for(j = 0; j < extensionCount; ++j) {
|
for (j = 0; j < extensionCount; ++j) {
|
||||||
if(strcmp(extensions_properties[j].extensionName, enabled_instance_extensions_names[i]) == 0) {
|
if (strcmp(extensions_properties[j].extensionName, enabled_instance_extensions_names[i]) == 0) {
|
||||||
supported = 1;
|
supported = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(supported == 0) {
|
if (supported == 0) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Selected extension is not supported: %s", extensions_properties[j].extensionName);
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU,
|
||||||
|
"Selected extension is not supported: %s",
|
||||||
|
extensions_properties[j].extensionName);
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
supported = 0;
|
supported = 0;
|
||||||
@@ -293,7 +295,8 @@ static rse_err_t pick_physical_device(VkInstance instance, VkPhysicalDevice* phy
|
|||||||
{
|
{
|
||||||
uint32_t physical_device_count = 0U;
|
uint32_t physical_device_count = 0U;
|
||||||
VkPhysicalDevice* physical_devices = NULL;
|
VkPhysicalDevice* physical_devices = NULL;
|
||||||
VkPhysicalDeviceProperties device_properties = {0};;
|
VkPhysicalDeviceProperties device_properties = {0};
|
||||||
|
;
|
||||||
VkPhysicalDeviceFeatures device_features = {0};
|
VkPhysicalDeviceFeatures device_features = {0};
|
||||||
|
|
||||||
/* Get number of existing physical devices */
|
/* Get number of existing physical devices */
|
||||||
@@ -378,9 +381,12 @@ static rse_err_t create_device(struct graphics_context_t* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get information about supported queue families */
|
/* Get information about supported queue families */
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(context->vulkan_handles.physical_device, &queue_families_property_count, NULL);
|
vkGetPhysicalDeviceQueueFamilyProperties(context->vulkan_handles.physical_device,
|
||||||
|
&queue_families_property_count,
|
||||||
|
NULL);
|
||||||
rse_malloc(queue_family_properties, sizeof(VkQueueFamilyProperties) * queue_families_property_count);
|
rse_malloc(queue_family_properties, sizeof(VkQueueFamilyProperties) * queue_families_property_count);
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(context->vulkan_handles.physical_device, &queue_families_property_count,
|
vkGetPhysicalDeviceQueueFamilyProperties(context->vulkan_handles.physical_device,
|
||||||
|
&queue_families_property_count,
|
||||||
queue_family_properties);
|
queue_family_properties);
|
||||||
|
|
||||||
/* Get queue families that support graphics operations AND have most
|
/* Get queue families that support graphics operations AND have most
|
||||||
@@ -401,7 +407,10 @@ static rse_err_t create_device(struct graphics_context_t* context)
|
|||||||
|
|
||||||
/* Check for family with surface support */
|
/* Check for family with surface support */
|
||||||
VkBool32 presentSupport = VK_FALSE;
|
VkBool32 presentSupport = VK_FALSE;
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(context->vulkan_handles.physical_device, familyIdx, context->vulkan_handles.surface, &presentSupport);
|
vkGetPhysicalDeviceSurfaceSupportKHR(context->vulkan_handles.physical_device,
|
||||||
|
familyIdx,
|
||||||
|
context->vulkan_handles.surface,
|
||||||
|
&presentSupport);
|
||||||
if (presentSupport) {
|
if (presentSupport) {
|
||||||
presentation_familiy_idx = familyIdx;
|
presentation_familiy_idx = familyIdx;
|
||||||
presentation_familiy_found = true;
|
presentation_familiy_found = true;
|
||||||
@@ -426,16 +435,17 @@ static rse_err_t create_device(struct graphics_context_t* context)
|
|||||||
context->queue_family_indices[QUEUE_FAMILY_INDEX_GRAPHICS] = graphics_family_idx;
|
context->queue_family_indices[QUEUE_FAMILY_INDEX_GRAPHICS] = graphics_family_idx;
|
||||||
context->queue_family_indices[QUEUE_FAMILY_INDEX_PRESENTATION] = presentation_familiy_idx;
|
context->queue_family_indices[QUEUE_FAMILY_INDEX_PRESENTATION] = presentation_familiy_idx;
|
||||||
|
|
||||||
rse_malloc(graphics_familiy_queue_priorities, sizeof(float) * queue_family_properties[graphics_family_idx].queueCount);
|
rse_malloc(graphics_familiy_queue_priorities,
|
||||||
|
sizeof(float) * queue_family_properties[graphics_family_idx].queueCount);
|
||||||
|
|
||||||
for (size_t i = 0; i < queue_family_properties[graphics_family_idx].queueCount; i++) {
|
for (size_t i = 0; i < queue_family_properties[graphics_family_idx].queueCount; i++) {
|
||||||
graphics_familiy_queue_priorities[i] = 1.0f;
|
graphics_familiy_queue_priorities[i] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_malloc(presentation_familiy_queue_priorities, sizeof(float) * queue_family_properties[presentation_familiy_idx].queueCount);
|
rse_malloc(presentation_familiy_queue_priorities,
|
||||||
|
sizeof(float) * queue_family_properties[presentation_familiy_idx].queueCount);
|
||||||
for (size_t i = 0; i < queue_family_properties[presentation_familiy_idx].queueCount; i++) {
|
for (size_t i = 0; i < queue_family_properties[presentation_familiy_idx].queueCount; i++) {
|
||||||
presentation_familiy_queue_priorities[i] =
|
presentation_familiy_queue_priorities[i] = 1.0f;
|
||||||
1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device_queue_createinfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
device_queue_createinfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
@@ -463,13 +473,19 @@ static rse_err_t create_device(struct graphics_context_t* context)
|
|||||||
device_create_info.ppEnabledExtensionNames = enabled_device_extensions_names;
|
device_create_info.ppEnabledExtensionNames = enabled_device_extensions_names;
|
||||||
device_create_info.pEnabledFeatures = NULL;
|
device_create_info.pEnabledFeatures = NULL;
|
||||||
|
|
||||||
if (VK_SUCCESS != vkCreateDevice(context->vulkan_handles.physical_device, &device_create_info, NULL, &context->vulkan_handles.device)) {
|
if (VK_SUCCESS != vkCreateDevice(context->vulkan_handles.physical_device,
|
||||||
|
&device_create_info,
|
||||||
|
NULL,
|
||||||
|
&context->vulkan_handles.device)) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create logical device");
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create logical device");
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
vkGetDeviceQueue(context->vulkan_handles.device, graphics_family_idx, 0, &context->vulkan_handles.graphics_queue);
|
vkGetDeviceQueue(context->vulkan_handles.device, graphics_family_idx, 0, &context->vulkan_handles.graphics_queue);
|
||||||
vkGetDeviceQueue(context->vulkan_handles.device, presentation_familiy_idx, 0, &context->vulkan_handles.present_queue);
|
vkGetDeviceQueue(context->vulkan_handles.device,
|
||||||
|
presentation_familiy_idx,
|
||||||
|
0,
|
||||||
|
&context->vulkan_handles.present_queue);
|
||||||
|
|
||||||
rse_free(presentation_familiy_queue_priorities);
|
rse_free(presentation_familiy_queue_priorities);
|
||||||
rse_free(graphics_familiy_queue_priorities);
|
rse_free(graphics_familiy_queue_priorities);
|
||||||
@@ -505,7 +521,6 @@ static rse_err_t create_memory_allocator(struct graphics_context_t* context)
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a Sync Objects
|
* @brief Create a Sync Objects
|
||||||
*
|
*
|
||||||
@@ -522,9 +537,18 @@ static rse_err_t create_sync_objects(struct graphics_context_t* context)
|
|||||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
|
||||||
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
|
for (size_t i = 0; i < SWAP_BUFFER_COUNT; ++i) {
|
||||||
if (VK_SUCCESS != vkCreateSemaphore(context->vulkan_handles.device, &semaphore_info, NULL, &context->vulkan_handles.image_available_semaphores[i]) ||
|
if (VK_SUCCESS != vkCreateSemaphore(context->vulkan_handles.device,
|
||||||
VK_SUCCESS != vkCreateSemaphore(context->vulkan_handles.device, &semaphore_info, NULL, &context->vulkan_handles.render_finished_semaphores[i]) ||
|
&semaphore_info,
|
||||||
VK_SUCCESS != vkCreateFence(context->vulkan_handles.device, &fenceInfo, NULL, &context->vulkan_handles.in_flight_fences[i])) {
|
NULL,
|
||||||
|
&context->vulkan_handles.image_available_semaphores[i]) ||
|
||||||
|
VK_SUCCESS != vkCreateSemaphore(context->vulkan_handles.device,
|
||||||
|
&semaphore_info,
|
||||||
|
NULL,
|
||||||
|
&context->vulkan_handles.render_finished_semaphores[i]) ||
|
||||||
|
VK_SUCCESS != vkCreateFence(context->vulkan_handles.device,
|
||||||
|
&fenceInfo,
|
||||||
|
NULL,
|
||||||
|
&context->vulkan_handles.in_flight_fences[i])) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create sync objects.");
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create sync objects.");
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
@@ -533,14 +557,14 @@ static rse_err_t create_sync_objects(struct graphics_context_t* context)
|
|||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rse_err_t vulkan_init(struct graphics_context_t* context)
|
rse_err_t vulkan_init(struct graphics_context_t* context)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
STATUS_CHECK(create_instance(&context->vulkan_handles.instance));
|
STATUS_CHECK(create_instance(&context->vulkan_handles.instance));
|
||||||
STATUS_CHECK(setup_debug_messenger(context->vulkan_handles.instance, &context->vulkan_handles.debug_messenger));
|
STATUS_CHECK(setup_debug_messenger(context->vulkan_handles.instance, &context->vulkan_handles.debug_messenger));
|
||||||
STATUS_CHECK(create_surface(context->vulkan_handles.instance, context->window_handle, &context->vulkan_handles.surface));
|
STATUS_CHECK(
|
||||||
|
create_surface(context->vulkan_handles.instance, context->window_handle, &context->vulkan_handles.surface));
|
||||||
STATUS_CHECK(pick_physical_device(context->vulkan_handles.instance, &context->vulkan_handles.physical_device));
|
STATUS_CHECK(pick_physical_device(context->vulkan_handles.instance, &context->vulkan_handles.physical_device));
|
||||||
STATUS_CHECK(create_device(context));
|
STATUS_CHECK(create_device(context));
|
||||||
STATUS_CHECK(create_memory_allocator(context));
|
STATUS_CHECK(create_memory_allocator(context));
|
||||||
@@ -559,12 +583,10 @@ rse_err_t vulkan_run(struct graphics_context_t* context)
|
|||||||
|
|
||||||
STATUS_CHECK(create_sync_objects(context));
|
STATUS_CHECK(create_sync_objects(context));
|
||||||
|
|
||||||
init_time();
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t draw_frame(struct graphics_context_t* context)
|
rse_err_t vulkan_draw_frame(struct graphics_context_t* context)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
uint32_t image_index = 0U;
|
uint32_t image_index = 0U;
|
||||||
@@ -576,14 +598,20 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
VkPresentInfoKHR present_info = {0};
|
VkPresentInfoKHR present_info = {0};
|
||||||
VkSwapchainKHR swap_chains[1];
|
VkSwapchainKHR swap_chains[1];
|
||||||
|
|
||||||
vkWaitForFences(context->vulkan_handles.device, 1, &context->vulkan_handles.in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX);
|
vkWaitForFences(context->vulkan_handles.device,
|
||||||
|
1,
|
||||||
|
&context->vulkan_handles.in_flight_fences[context->current_frame],
|
||||||
|
VK_TRUE,
|
||||||
|
UINT64_MAX);
|
||||||
|
|
||||||
STATUS_CHECK(buffers_update(context));
|
STATUS_CHECK(buffers_update(context));
|
||||||
|
|
||||||
update_time();
|
result = vkAcquireNextImageKHR(context->vulkan_handles.device,
|
||||||
|
context->swapchain_data.swapchain,
|
||||||
result = vkAcquireNextImageKHR(context->vulkan_handles.device, context->swapchain_data.swapchain, UINT64_MAX, context->vulkan_handles.image_available_semaphores[context->current_frame],
|
UINT64_MAX,
|
||||||
VK_NULL_HANDLE, &image_index);
|
context->vulkan_handles.image_available_semaphores[context->current_frame],
|
||||||
|
VK_NULL_HANDLE,
|
||||||
|
&image_index);
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
recreate_swapchain(context);
|
recreate_swapchain(context);
|
||||||
@@ -612,11 +640,14 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
submit_info.commandBufferCount = 1;
|
submit_info.commandBufferCount = 1;
|
||||||
submit_info.pCommandBuffers = &context->vulkan_handles.command_buffers[context->current_frame];
|
submit_info.pCommandBuffers = &context->vulkan_handles.command_buffers[context->current_frame];
|
||||||
|
|
||||||
signal_semaphores[0] = context->vulkan_handles.render_finished_semaphores[context->current_frame];
|
signal_semaphores[0] = context->vulkan_handles.render_finished_semaphores[image_index];
|
||||||
submit_info.signalSemaphoreCount = 1;
|
submit_info.signalSemaphoreCount = 1;
|
||||||
submit_info.pSignalSemaphores = signal_semaphores;
|
submit_info.pSignalSemaphores = signal_semaphores;
|
||||||
|
|
||||||
if (vkQueueSubmit(context->vulkan_handles.graphics_queue, 1, &submit_info, context->vulkan_handles.in_flight_fences[context->current_frame]) != VK_SUCCESS) {
|
if (vkQueueSubmit(context->vulkan_handles.graphics_queue,
|
||||||
|
1,
|
||||||
|
&submit_info,
|
||||||
|
context->vulkan_handles.in_flight_fences[context->current_frame]) != VK_SUCCESS) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to submit draw command buffer!");
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to submit draw command buffer!");
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
@@ -624,7 +655,7 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
|
|
||||||
present_info.waitSemaphoreCount = 1;
|
present_info.waitSemaphoreCount = 1;
|
||||||
present_info.pWaitSemaphores = &context->vulkan_handles.render_finished_semaphores[context->current_frame];
|
present_info.pWaitSemaphores = &context->vulkan_handles.render_finished_semaphores[image_index];
|
||||||
|
|
||||||
swap_chains[0] = context->swapchain_data.swapchain;
|
swap_chains[0] = context->swapchain_data.swapchain;
|
||||||
present_info.swapchainCount = 1;
|
present_info.swapchainCount = 1;
|
||||||
@@ -649,6 +680,7 @@ rse_err_t draw_frame(struct graphics_context_t* context)
|
|||||||
|
|
||||||
void vulkan_deinit(struct graphics_context_t* context)
|
void vulkan_deinit(struct graphics_context_t* context)
|
||||||
{
|
{
|
||||||
|
vkDeviceWaitIdle(context->vulkan_handles.device);
|
||||||
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->vulkan_handles.device, context->vulkan_handles.image_available_semaphores[i], NULL);
|
vkDestroySemaphore(context->vulkan_handles.device, context->vulkan_handles.image_available_semaphores[i], NULL);
|
||||||
|
|||||||
@@ -46,6 +46,6 @@ void vulkan_deinit(struct graphics_context_t* context);
|
|||||||
* @param context Graphics context
|
* @param context Graphics context
|
||||||
* @return rse_err_t
|
* @return rse_err_t
|
||||||
*/
|
*/
|
||||||
rse_err_t draw_frame(struct graphics_context_t* context);
|
rse_err_t vulkan_draw_frame(struct graphics_context_t* context);
|
||||||
|
|
||||||
#endif /* GRAPHICS_VULKANBASE_H */
|
#endif /* GRAPHICS_VULKANBASE_H */
|
||||||
|
|||||||
@@ -119,7 +119,12 @@ static rse_err_t create_instance_buffers(struct graphics_context_t* context)
|
|||||||
buffer_size = sizeof(struct instance_data_t) * MAX_INSTANCE_NUMBER;
|
buffer_size = sizeof(struct instance_data_t) * MAX_INSTANCE_NUMBER;
|
||||||
|
|
||||||
STATUS_CHECK(
|
STATUS_CHECK(
|
||||||
buffer_create_uniform(context, &context->render_targets[RENDER_TARGET_3D].instance_buffer, buffer_size));
|
create_buffer(context,
|
||||||
|
buffer_size,
|
||||||
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||||
|
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT,
|
||||||
|
&context->render_targets[RENDER_TARGET_3D].instance_buffer));
|
||||||
/* TODO: Move creation to somewhere else? */
|
/* TODO: Move creation to somewhere else? */
|
||||||
STATUS_CHECK(create_buffer(context,
|
STATUS_CHECK(create_buffer(context,
|
||||||
CMD_BUFFER_SIZE,
|
CMD_BUFFER_SIZE,
|
||||||
@@ -205,8 +210,11 @@ rse_err_t add_vertices(struct graphics_context_t* context,
|
|||||||
size_t vertices_count,
|
size_t vertices_count,
|
||||||
const struct vertex_t* vertices,
|
const struct vertex_t* vertices,
|
||||||
size_t indices_count,
|
size_t indices_count,
|
||||||
const uint16_t* indices)
|
uint16_t* indices)
|
||||||
{
|
{
|
||||||
|
// static uint16_t last_index = 0U;
|
||||||
|
// uint16_t max_index = 0U;
|
||||||
|
// size_t idx = 0U;
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
struct vulkan_buffer_t staging_buffer;
|
struct vulkan_buffer_t staging_buffer;
|
||||||
size_t vertices_size = sizeof(vertices[0]) * vertices_count;
|
size_t vertices_size = sizeof(vertices[0]) * vertices_count;
|
||||||
@@ -230,6 +238,7 @@ rse_err_t add_vertices(struct graphics_context_t* context,
|
|||||||
copy_buffer(context, staging_buffer.buffer, vertex_buffer->buffer, vertices_size, vertex_buffer->allocated_size);
|
copy_buffer(context, staging_buffer.buffer, vertex_buffer->buffer, vertices_size, vertex_buffer->allocated_size);
|
||||||
vertex_buffer->allocated_size += vertices_size;
|
vertex_buffer->allocated_size += vertices_size;
|
||||||
|
|
||||||
|
|
||||||
/* Fill staging buffer with index data */
|
/* Fill staging buffer with index data */
|
||||||
memcpy(staging_buffer.allocation_info.pMappedData, indices, 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);
|
||||||
@@ -269,6 +278,7 @@ rse_err_t buffers_update(struct graphics_context_t* context)
|
|||||||
sizeof(VkDrawIndexedIndirectCommand) * context->mesh_data.mesh_count;
|
sizeof(VkDrawIndexedIndirectCommand) * context->mesh_data.mesh_count;
|
||||||
struct vulkan_buffer_t staging_buffer;
|
struct vulkan_buffer_t staging_buffer;
|
||||||
struct mesh_t* mesh = NULL;
|
struct mesh_t* mesh = NULL;
|
||||||
|
uint32_t indices_count = 0U;
|
||||||
|
|
||||||
rse_malloc(draw_indirect_commands_buffer, draw_indirect_commands_buffer_size);
|
rse_malloc(draw_indirect_commands_buffer, draw_indirect_commands_buffer_size);
|
||||||
for (iter = 0U; iter < context->mesh_data.mesh_count; ++iter) {
|
for (iter = 0U; iter < context->mesh_data.mesh_count; ++iter) {
|
||||||
@@ -290,13 +300,14 @@ rse_err_t buffers_update(struct graphics_context_t* context)
|
|||||||
draw_indirect_command->firstInstance = 0;
|
draw_indirect_command->firstInstance = 0;
|
||||||
draw_indirect_command->vertexOffset = 0;
|
draw_indirect_command->vertexOffset = 0;
|
||||||
} else {
|
} else {
|
||||||
draw_indirect_command->firstIndex = context->mesh_data.mesh_bucket[iter - 1].index_count;
|
draw_indirect_command->firstIndex = indices_count;
|
||||||
draw_indirect_command->firstInstance = draw_indirect_commands_buffer[iter - 1].firstInstance +
|
draw_indirect_command->firstInstance = draw_indirect_commands_buffer[iter - 1].firstInstance +
|
||||||
draw_indirect_commands_buffer[iter - 1].instanceCount;
|
draw_indirect_commands_buffer[iter - 1].instanceCount;
|
||||||
draw_indirect_command->vertexOffset = (context->mesh_data.mesh_bucket[iter - 1].vertex_count);
|
draw_indirect_command->vertexOffset = (context->mesh_data.mesh_bucket[iter - 1].vertex_count + draw_indirect_commands_buffer[iter-1].vertexOffset);
|
||||||
}
|
}
|
||||||
draw_indirect_command->indexCount = mesh->index_count;
|
draw_indirect_command->indexCount = mesh->index_count;
|
||||||
draw_indirect_command->instanceCount = mesh->instances_count;
|
draw_indirect_command->instanceCount = mesh->instances_count;
|
||||||
|
indices_count += mesh->index_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy Draw indirect commands into buffer */
|
/* Copy Draw indirect commands into buffer */
|
||||||
@@ -435,10 +446,12 @@ void destroy_buffers(struct graphics_context_t* context)
|
|||||||
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].vertex_buffer);
|
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].vertex_buffer);
|
||||||
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].index_buffer);
|
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].index_buffer);
|
||||||
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].draw_indirect_command_buffer);
|
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].draw_indirect_command_buffer);
|
||||||
|
destroy_buffer(context, &context->render_targets[RENDER_TARGET_3D].instance_buffer);
|
||||||
|
|
||||||
for (iter = 0U; iter < context->uniform_buffers.vulkan_buffers_count; ++iter)
|
for (iter = 0U; iter < context->uniform_buffers.vulkan_buffers_count; ++iter) {
|
||||||
{
|
vmaDestroyBuffer(context->vulkan_handles.allocator,
|
||||||
vmaDestroyBuffer(context->vulkan_handles.allocator, context->uniform_buffers.vulkan_buffers[iter].buffer, context->uniform_buffers.vulkan_buffers[iter].allocation);
|
context->uniform_buffers.vulkan_buffers[iter].buffer,
|
||||||
|
context->uniform_buffers.vulkan_buffers[iter].allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
context->uniform_buffers.vulkan_buffers_count = 0;
|
context->uniform_buffers.vulkan_buffers_count = 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define VULKAN_BUFFERS_H
|
#define VULKAN_BUFFERS_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vma/vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
|
||||||
#include "graphics_context.h"
|
#include "graphics_context.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
@@ -36,7 +36,7 @@ rse_err_t buffer_create_uniform(struct graphics_context_t* context, struct vulka
|
|||||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||||
*/
|
*/
|
||||||
rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, size_t vertices_count,
|
rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, size_t vertices_count,
|
||||||
const struct vertex_t* vertices, size_t indices_count, const uint16_t* indices);
|
const struct vertex_t* vertices, size_t indices_count, uint16_t* indices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add instance data to vulkan buffers
|
* @brief Add instance data to vulkan buffers
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#ifndef VULKAN_COMMANDS_H
|
#ifndef VULKAN_COMMANDS_H
|
||||||
#define VULKAN_COMMANDS_H
|
#define VULKAN_COMMANDS_H
|
||||||
|
|
||||||
#include <vma/vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
#include "vulkan_commons.h"
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
time_t g_last_frame_time;
|
|
||||||
time_t g_this_frame_time;
|
|
||||||
float g_float_delta_time;
|
|
||||||
|
|
||||||
void init_time(void)
|
|
||||||
{
|
|
||||||
time(&g_last_frame_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_time(void)
|
|
||||||
{
|
|
||||||
g_last_frame_time = g_this_frame_time;
|
|
||||||
time(&g_this_frame_time);
|
|
||||||
g_float_delta_time = (float)difftime(g_this_frame_time, g_last_frame_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
float get_time_diff(void)
|
|
||||||
{
|
|
||||||
return g_float_delta_time;
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include <cglm/types.h>
|
#include <cglm/types.h>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <vma/vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
#include <cglm/cglm.h>
|
#include <cglm/cglm.h>
|
||||||
|
|
||||||
#include <stdalign.h>
|
#include <stdalign.h>
|
||||||
@@ -44,7 +44,7 @@ struct vulkan_buffer_t
|
|||||||
VmaAllocationInfo allocation_info;
|
VmaAllocationInfo allocation_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uniform_buffer_object_t
|
struct mvp_data_t
|
||||||
{
|
{
|
||||||
alignas(16) mat4 model;
|
alignas(16) mat4 model;
|
||||||
alignas(16) mat4 view;
|
alignas(16) mat4 view;
|
||||||
@@ -58,8 +58,4 @@ struct instance_data_t {
|
|||||||
alignas(4) uint32_t texture_id;
|
alignas(4) uint32_t texture_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_time(void);
|
|
||||||
void update_time(void);
|
|
||||||
float get_time_diff(void);
|
|
||||||
|
|
||||||
#endif /* VULKAN_GLOBAL_H */
|
#endif /* VULKAN_GLOBAL_H */
|
||||||
|
|||||||
+66
-21
@@ -3,6 +3,7 @@
|
|||||||
#include <SDL3/SDL_log.h>
|
#include <SDL3/SDL_log.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "SDL3/SDL_video.h"
|
||||||
#include "src/graphics_context.h"
|
#include "src/graphics_context.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
@@ -15,6 +16,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
#define IMAGE_TAKEN 1U
|
#define IMAGE_TAKEN 1U
|
||||||
#define IMAGE_FREE 0U
|
#define IMAGE_FREE 0U
|
||||||
|
|
||||||
@@ -168,16 +172,14 @@ rse_err_t create_color_resource(struct graphics_context_t* context)
|
|||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
VkFormat color_format = IMAGE_FORMAT;
|
VkFormat color_format = IMAGE_FORMAT;
|
||||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
VkExtent2D extent = {0};
|
||||||
|
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->vulkan_handles.physical_device,
|
STATUS_CHECK(image_get_extent(context, &extent));
|
||||||
context->vulkan_handles.surface,
|
|
||||||
&physical_device_surface_capabilities);
|
|
||||||
|
|
||||||
STATUS_CHECK(create_image(context,
|
STATUS_CHECK(create_image(context,
|
||||||
&context->color_image,
|
&context->color_image,
|
||||||
physical_device_surface_capabilities.currentExtent.width,
|
extent.width,
|
||||||
physical_device_surface_capabilities.currentExtent.height,
|
extent.height,
|
||||||
color_format,
|
color_format,
|
||||||
VK_SAMPLE_COUNT_8_BIT,
|
VK_SAMPLE_COUNT_8_BIT,
|
||||||
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
@@ -191,17 +193,16 @@ rse_err_t create_depth_resources(struct graphics_context_t* context)
|
|||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
VkFormat depth_format = {0};
|
VkFormat depth_format = {0};
|
||||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
VkExtent2D extent = {0};
|
||||||
|
|
||||||
|
STATUS_CHECK(image_get_extent(context, &extent));
|
||||||
|
|
||||||
STATUS_CHECK(find_depth_format(context, &depth_format));
|
STATUS_CHECK(find_depth_format(context, &depth_format));
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->vulkan_handles.physical_device,
|
|
||||||
context->vulkan_handles.surface,
|
|
||||||
&physical_device_surface_capabilities);
|
|
||||||
|
|
||||||
STATUS_CHECK(create_image(context,
|
STATUS_CHECK(create_image(context,
|
||||||
&context->depth_image,
|
&context->depth_image,
|
||||||
physical_device_surface_capabilities.currentExtent.width,
|
extent.width,
|
||||||
physical_device_surface_capabilities.currentExtent.height,
|
extent.height,
|
||||||
depth_format,
|
depth_format,
|
||||||
VK_SAMPLE_COUNT_8_BIT,
|
VK_SAMPLE_COUNT_8_BIT,
|
||||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||||
@@ -407,6 +408,33 @@ rse_err_t init_vulkan_images(struct graphics_context_t* context)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rse_err_t image_get_extent(struct graphics_context_t* context, VkExtent2D* extent)
|
||||||
|
{
|
||||||
|
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
||||||
|
int w = 0;
|
||||||
|
int h = 0;
|
||||||
|
|
||||||
|
if (extent == NULL) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Provided extent pointer is NULL");
|
||||||
|
|
||||||
|
return RSE_ERROR_NULL_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->vulkan_handles.physical_device,
|
||||||
|
context->vulkan_handles.surface,
|
||||||
|
&physical_device_surface_capabilities);
|
||||||
|
|
||||||
|
if (physical_device_surface_capabilities.currentExtent.width != UINT32_MAX) {
|
||||||
|
*extent = physical_device_surface_capabilities.currentExtent;
|
||||||
|
} else {
|
||||||
|
SDL_GetWindowSize(context->window_handle, &w, &h);
|
||||||
|
extent->width = w;
|
||||||
|
extent->height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
rse_err_t texture_update_image(struct graphics_context_t* context,
|
rse_err_t texture_update_image(struct graphics_context_t* context,
|
||||||
const unsigned char* pixels,
|
const unsigned char* pixels,
|
||||||
int width,
|
int width,
|
||||||
@@ -490,20 +518,19 @@ rse_err_t load_texture_from_bitmat(struct graphics_context_t* context,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t texture_load_from_file(struct graphics_context_t* context, const char* file_path, rse_id_t* texture_id)
|
rse_err_t texture_load_from_buffer(struct graphics_context_t* context, const unsigned char* data_buffer, size_t buffer_size, rse_id_t* texture_id)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
size_t buffer_size = 0U;
|
int channels = 0;
|
||||||
unsigned char* pixel_buffer = NULL;
|
unsigned char* pixel_buffer = NULL;
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
STATUS_CHECK(file_load_pixels(file_path, NULL, &buffer_size, &width, &height));
|
pixel_buffer = stbi_load_from_memory(data_buffer, (int)buffer_size, &width, &height, &channels, STBI_rgb_alpha);
|
||||||
rse_malloc(pixel_buffer, buffer_size);
|
if (pixel_buffer == NULL) {
|
||||||
if (file_load_pixels(file_path, pixel_buffer, &buffer_size, &width, &height) != RSE_ERROR_NO_ERROR) {
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to load image");
|
||||||
status = RSE_ERROR_INTERNAL_ERROR;
|
|
||||||
|
|
||||||
goto mem_free;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_texture_from_bitmat(context, pixel_buffer, width, height, texture_id, VK_FORMAT_R8G8B8A8_SRGB) != RSE_ERROR_NO_ERROR) {
|
if (load_texture_from_bitmat(context, pixel_buffer, width, height, texture_id, VK_FORMAT_R8G8B8A8_SRGB) != RSE_ERROR_NO_ERROR) {
|
||||||
@@ -513,8 +540,26 @@ rse_err_t texture_load_from_file(struct graphics_context_t* context, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
mem_free:
|
mem_free:
|
||||||
|
stbi_image_free(pixel_buffer);
|
||||||
|
|
||||||
rse_free(pixel_buffer);
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t texture_load_from_file(struct graphics_context_t* context, const char* file_path, rse_id_t* texture_id)
|
||||||
|
{
|
||||||
|
size_t buffer_size = 0U;
|
||||||
|
unsigned char* data_buffer = NULL;
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
|
||||||
|
STATUS_CHECK(file_read_bytes(file_path, &buffer_size, NULL));
|
||||||
|
rse_malloc(data_buffer, buffer_size);
|
||||||
|
STATUS_CHECK(file_read_bytes(file_path, &buffer_size, data_buffer));
|
||||||
|
|
||||||
|
if (texture_load_from_buffer(context, data_buffer, buffer_size, texture_id) != RSE_ERROR_NO_ERROR) {
|
||||||
|
status = RSE_ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_free(data_buffer);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
*/
|
*/
|
||||||
rse_err_t init_vulkan_images(struct graphics_context_t* context);
|
rse_err_t init_vulkan_images(struct graphics_context_t* context);
|
||||||
|
|
||||||
|
rse_err_t image_get_extent(struct graphics_context_t* context, VkExtent2D* extent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Loads image from file, for later to be used as a texture
|
* @brief Loads image from file, for later to be used as a texture
|
||||||
*
|
*
|
||||||
@@ -40,6 +42,7 @@ rse_err_t init_vulkan_images(struct graphics_context_t* context);
|
|||||||
rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, const unsigned char* pixel_buffer, int width,
|
rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, const unsigned char* pixel_buffer, int width,
|
||||||
int height, rse_id_t* texture_id, VkFormat color_format);
|
int height, rse_id_t* texture_id, VkFormat color_format);
|
||||||
|
|
||||||
|
rse_err_t texture_load_from_buffer(struct graphics_context_t* context, const unsigned char* data_buffer, size_t buffer_size, rse_id_t* texture_id);
|
||||||
/**
|
/**
|
||||||
* @brief Loads image from file, for later to be used as a texture
|
* @brief Loads image from file, for later to be used as a texture
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,14 +21,18 @@ static rse_err_t create_swapchain(struct graphics_context_t* context)
|
|||||||
{
|
{
|
||||||
VkSwapchainCreateInfoKHR create_info;
|
VkSwapchainCreateInfoKHR create_info;
|
||||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
VkBool32 surfaceSupported;
|
VkBool32 surfaceSupported;
|
||||||
|
VkExtent2D extent = {0};
|
||||||
|
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->vulkan_handles.physical_device,
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->vulkan_handles.physical_device,
|
||||||
context->vulkan_handles.surface,
|
context->vulkan_handles.surface,
|
||||||
&physical_device_surface_capabilities);
|
&physical_device_surface_capabilities);
|
||||||
|
|
||||||
|
STATUS_CHECK(image_get_extent(context, &extent));
|
||||||
|
|
||||||
/* Store extent in global variable, for later use */
|
/* Store extent in global variable, for later use */
|
||||||
context->swapchain_data.swapchain_extent = physical_device_surface_capabilities.currentExtent;
|
context->swapchain_data.swapchain_extent = extent;
|
||||||
|
|
||||||
/* Check if device supports surface for presentation */
|
/* Check if device supports surface for presentation */
|
||||||
vkGetPhysicalDeviceSurfaceSupportKHR(context->vulkan_handles.physical_device,
|
vkGetPhysicalDeviceSurfaceSupportKHR(context->vulkan_handles.physical_device,
|
||||||
@@ -52,7 +56,7 @@ static rse_err_t create_swapchain(struct graphics_context_t* context)
|
|||||||
create_info.pQueueFamilyIndices = context->queue_family_indices;
|
create_info.pQueueFamilyIndices = context->queue_family_indices;
|
||||||
create_info.preTransform = physical_device_surface_capabilities.currentTransform;
|
create_info.preTransform = physical_device_surface_capabilities.currentTransform;
|
||||||
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
create_info.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
create_info.clipped = VK_TRUE;
|
create_info.clipped = VK_TRUE;
|
||||||
create_info.oldSwapchain = VK_NULL_HANDLE;
|
create_info.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
|||||||
+4
-25
@@ -18,46 +18,25 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "SDL3/SDL_log.h"
|
||||||
#include "utilities/commons.h"
|
#include "utilities/commons.h"
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
#include "vulkan/vulkan_core.h"
|
|
||||||
#include "vulkan_base.h"
|
|
||||||
|
|
||||||
rse_err_t window_init(SDL_Window** window_handle, bool* is_framebuffer_resized)
|
rse_err_t window_init(SDL_Window** window_handle, bool* is_framebuffer_resized)
|
||||||
{
|
{
|
||||||
SDL_Init(SDL_INIT_VIDEO); // TODO: Move to initial phase of RSE initialization
|
(void)is_framebuffer_resized;
|
||||||
|
// TODO: Actually use this parameter?
|
||||||
(void)is_framebuffer_resized;; // TODO: Actually use this parameter?
|
|
||||||
|
|
||||||
*window_handle = SDL_CreateWindow("RedScarfEngine", 1024, 768, SDL_WINDOW_VULKAN);
|
*window_handle = SDL_CreateWindow("RedScarfEngine", 1024, 768, SDL_WINDOW_VULKAN);
|
||||||
|
|
||||||
if (NULL == *window_handle) {
|
if (NULL == *window_handle) {
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Window context creation failed");
|
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Window context creation failed. Reason: %s", SDL_GetError());
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RSE_ERROR_NO_ERROR;
|
return RSE_ERROR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t window_loop(struct graphics_context_t* context)
|
|
||||||
{
|
|
||||||
uint8_t done = 0;
|
|
||||||
SDL_Event event;
|
|
||||||
|
|
||||||
while (0 == done) {
|
|
||||||
while (SDL_PollEvent(&event)) {
|
|
||||||
if (SDL_EVENT_QUIT == event.type) {
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_frame(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDeviceWaitIdle(context->vulkan_handles.device);
|
|
||||||
return RSE_ERROR_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void window_terminate(SDL_Window* window_handle)
|
void window_terminate(SDL_Window* window_handle)
|
||||||
{
|
{
|
||||||
SDL_DestroyWindow(window_handle);
|
SDL_DestroyWindow(window_handle);
|
||||||
|
|||||||
@@ -32,14 +32,6 @@
|
|||||||
*/
|
*/
|
||||||
rse_err_t window_init(SDL_Window **window_handle, bool *is_framebuffer_resized);
|
rse_err_t window_init(SDL_Window **window_handle, bool *is_framebuffer_resized);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Main window loop
|
|
||||||
*
|
|
||||||
* @param context Graphics context
|
|
||||||
* @return rse_err_t WINDOW_SUCCESS or error code
|
|
||||||
*/
|
|
||||||
rse_err_t window_loop(struct graphics_context_t* context);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes window and terminates GLFW
|
* @brief Closes window and terminates GLFW
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ project('RedScarfEngine',
|
|||||||
'werror=true'
|
'werror=true'
|
||||||
])
|
])
|
||||||
|
|
||||||
|
add_project_arguments('-DWAYLAND=1', language : 'c')
|
||||||
|
|
||||||
subdir('utilities')
|
subdir('utilities')
|
||||||
subdir('graphics')
|
subdir('graphics')
|
||||||
|
subdir('events')
|
||||||
|
|
||||||
subdir('red_scarf_engine')
|
subdir('red_scarf_engine')
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror")
|
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} src/main.c)
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
|
||||||
${CMAKE_SOURCE_DIR})
|
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
||||||
graphics
|
|
||||||
utilities)
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
red_scarf_engine_srcs = [
|
red_scarf_engine_srcs = [
|
||||||
|
'src/red_scarf_engine.c',
|
||||||
'src/main.c'
|
'src/main.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -13,6 +14,10 @@ executable(
|
|||||||
],
|
],
|
||||||
dependencies : [
|
dependencies : [
|
||||||
sdl3_dep,
|
sdl3_dep,
|
||||||
|
rse_graphics_lib_dep,
|
||||||
|
],
|
||||||
|
link_with: [
|
||||||
|
rse_events_lib,
|
||||||
|
rse_utilities_lib,
|
||||||
],
|
],
|
||||||
link_with: rse_graphics_lib,
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* @file red_scarf_engine.h
|
||||||
|
* @author Piotr Krygier (piotrkrygier@everyonencancode.xyz)
|
||||||
|
* @brief Red Scarf Engine main entry point
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-03-03
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2026
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RED_SCARF_ENGINE_H_
|
||||||
|
#define RED_SCARF_ENGINE_H_
|
||||||
|
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
|
||||||
|
typedef struct rse_context_t* rse_context;
|
||||||
|
|
||||||
|
rse_err_t rse_init(rse_context* context);
|
||||||
|
rse_err_t rse_run(rse_context context);
|
||||||
|
|
||||||
|
#endif /* RED_SCARF_ENGINE_H_ */
|
||||||
@@ -1,31 +1,16 @@
|
|||||||
#include <SDL3/SDL_init.h>
|
#include "red_scarf_engine.h"
|
||||||
#include <SDL3/SDL_log.h>
|
|
||||||
#include "graphics/rse_graphics.h"
|
|
||||||
#include "utilities/errors_common.h"
|
#include "utilities/errors_common.h"
|
||||||
#include "SDL3/SDL_thread.h"
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
struct rse_graphics_context_t* context = NULL;
|
rse_context context;
|
||||||
SDL_Thread* graphics_task = NULL;
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
|
STATUS_CHECK(rse_init(&context));
|
||||||
|
STATUS_CHECK(rse_run(context));
|
||||||
STATUS_CHECK(rse_graphics_init(&context));
|
|
||||||
STATUS_CHECK(rse_graphics_test_function(context));
|
|
||||||
|
|
||||||
graphics_task = SDL_CreateThread(rse_graphics_run, "graphics_task", (void*) context);
|
|
||||||
|
|
||||||
if (NULL == graphics_task) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create graphics task");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_WaitThread(graphics_task, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#include "red_scarf_engine.h"
|
||||||
|
#include "graphics/rse_graphics.h"
|
||||||
|
#include "utilities/commons.h"
|
||||||
|
#include "utilities/errors_common.h"
|
||||||
|
#include "utilities/time_utils.h"
|
||||||
|
#include "events/rse_events_manager.h"
|
||||||
|
|
||||||
|
struct rse_context_t {
|
||||||
|
struct graphics_context_t graphics_context;
|
||||||
|
struct events_context_t events_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void fps_print(double* start_time)
|
||||||
|
{
|
||||||
|
static uint32_t frame_counts = 0U;
|
||||||
|
|
||||||
|
double now = time_get_sec_from_start();
|
||||||
|
|
||||||
|
frame_counts++;
|
||||||
|
if ((now - *start_time) > 1.0) {
|
||||||
|
printf("\rFPS: %u", frame_counts);
|
||||||
|
fflush(stdout);
|
||||||
|
frame_counts = 0;
|
||||||
|
*start_time += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t rse_init(rse_context* context)
|
||||||
|
{
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
struct rse_context_t* rse_context = NULL;
|
||||||
|
|
||||||
|
rse_malloc(*context, sizeof(struct rse_context_t));
|
||||||
|
|
||||||
|
rse_context = *context;
|
||||||
|
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
|
||||||
|
|
||||||
|
STATUS_CHECK(time_init());
|
||||||
|
STATUS_CHECK(rse_events_init(&rse_context->events_context));
|
||||||
|
STATUS_CHECK(rse_graphics_init(&rse_context->graphics_context));
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t rse_run(rse_context context)
|
||||||
|
{
|
||||||
|
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||||
|
double start_time;
|
||||||
|
|
||||||
|
start_time = time_get_sec_from_start();
|
||||||
|
|
||||||
|
STATUS_CHECK(rse_graphics_test_function(&context->graphics_context));
|
||||||
|
|
||||||
|
STATUS_CHECK(rse_graphics_run(&context->graphics_context));
|
||||||
|
while(true) {
|
||||||
|
time_update();
|
||||||
|
rse_events_main_loop(&context->events_context);
|
||||||
|
if (context->events_context.should_stop == EVENT_SHOULD_STOP_ENGINE_TRUE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rse_graphics_main_loop(&context->graphics_context);
|
||||||
|
fps_print(&start_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_graphics_deinit(&context->graphics_context);
|
||||||
|
rse_free(context);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[wrap-file]
|
||||||
|
directory = cglm-0.9.6
|
||||||
|
source_url = https://github.com/recp/cglm/archive/refs/tags/v0.9.6.tar.gz
|
||||||
|
source_filename = cglm-0.9.6.tar.gz
|
||||||
|
source_hash = be5e7d384561eb0fca59724a92b7fb44bf03e588a7eae5123a7d796002928184
|
||||||
|
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/cglm_0.9.6-1/cglm-0.9.6.tar.gz
|
||||||
|
wrapdb_version = 0.9.6-1
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
cglm = cglm_dep
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
project('stb', 'c')
|
||||||
|
|
||||||
|
stb_inc = include_directories('.')
|
||||||
|
|
||||||
|
stb_dep = declare_dependency(
|
||||||
|
include_directories: stb_inc,
|
||||||
|
)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
project(
|
||||||
|
'vulkan-headers',
|
||||||
|
'c',
|
||||||
|
license: 'Apache-2.0',
|
||||||
|
version: '1.4.353',
|
||||||
|
meson_version: '>=0.56.0',
|
||||||
|
)
|
||||||
|
|
||||||
|
vulkan_api_xml = files('registry/vk.xml')
|
||||||
|
|
||||||
|
vulkan_headers_dep = declare_dependency(
|
||||||
|
include_directories: include_directories('include'),
|
||||||
|
)
|
||||||
|
|
||||||
|
meson.override_dependency('VulkanHeaders', vulkan_headers_dep)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[wrap-git]
|
||||||
|
url = https://github.com/nothings/stb.git
|
||||||
|
revision = HEAD
|
||||||
|
depth = 1
|
||||||
|
patch_directory = stb/
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[wrap-file]
|
||||||
|
directory = Vulkan-Headers-1.4.353
|
||||||
|
source_url = https://github.com/KhronosGroup/Vulkan-Headers/archive/v1.4.353.tar.gz
|
||||||
|
source_filename = vulkan-headers-1.4.353.tar.gz
|
||||||
|
source_hash = aead572dd86def896eddac84cb31acb4ede28e3ac1ab97439d6ddd1b5a14d38e
|
||||||
|
patch_directory = vulkan_headers/
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
dependency_names = VulkanHeaders
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
[wrap-file]
|
||||||
|
directory = VulkanMemoryAllocator-3.3.0
|
||||||
|
source_url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/archive/refs/tags/v3.3.0.tar.gz
|
||||||
|
source_filename = VulkanMemoryAllocator-3.3.0.tar.gz
|
||||||
|
source_hash = c4f6bbe6b5a45c2eb610ca9d231158e313086d5b1a40c9922cb42b597419b14e
|
||||||
|
source_fallback_url = https://wrapdb.mesonbuild.com/v2/vulkan-memory-allocator_3.3.0-1/get_source/VulkanMemoryAllocator-3.3.0.tar.gz
|
||||||
|
patch_filename = vulkan-memory-allocator_3.3.0-1_patch.zip
|
||||||
|
patch_url = https://wrapdb.mesonbuild.com/v2/vulkan-memory-allocator_3.3.0-1/get_patch
|
||||||
|
patch_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/vulkan-memory-allocator_3.3.0-1/vulkan-memory-allocator_3.3.0-1_patch.zip
|
||||||
|
patch_hash = 85f3c1c82f3d1938fa295c80b06fc1c5c001f939f009b566c336a941d5d2d8b5
|
||||||
|
wrapdb_version = 3.3.0-1
|
||||||
|
|
||||||
|
[provide]
|
||||||
|
dependency_names = VulkanMemoryAllocator
|
||||||
+7240
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -22,13 +22,13 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef RSE_TEST
|
#ifndef RSE_TEST
|
||||||
#define rse_malloc(ptr, size) \
|
#define rse_malloc(ptr, size) \
|
||||||
ptr = malloc(size); \
|
ptr = calloc(1, size); \
|
||||||
if (ptr == NULL) { \
|
if (ptr == NULL) { \
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Memory allocation failure"); \
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Memory allocation failure"); \
|
||||||
exit(1); \
|
exit(1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define rse_free(ptr) free(ptr);
|
#define rse_free(ptr) if (ptr != NULL) free(ptr);
|
||||||
|
|
||||||
#define rse_memcpy(dst, src, size) memcpy(dst, src, size);
|
#define rse_memcpy(dst, src, size) memcpy(dst, src, size);
|
||||||
#define rse_memset(ptr, value, size) memset(ptr, value, size);
|
#define rse_memset(ptr, value, size) memset(ptr, value, size);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
|
#include "cgltf.h"
|
||||||
|
|
||||||
#define MAX_PATH_LENGTH (4096U)
|
#define MAX_PATH_LENGTH (4096U)
|
||||||
|
|
||||||
@@ -14,13 +15,13 @@
|
|||||||
* @param bytes_count Returned bytes count
|
* @param bytes_count Returned bytes count
|
||||||
* @param buffer Returned filled buffer
|
* @param buffer Returned filled buffer
|
||||||
*/
|
*/
|
||||||
rse_err_t file_read(const char* file_path, size_t* bytes_count, char* buffer);
|
rse_err_t file_read_bytes(const char* file_path, size_t* bytes_count, unsigned char* buffer);
|
||||||
|
|
||||||
rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer);
|
rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer);
|
||||||
|
|
||||||
rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* buffer_size, int* width, int* height);
|
|
||||||
|
|
||||||
rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size);
|
rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size);
|
||||||
|
|
||||||
|
rse_err_t file_load_gltf(const char* file_name, cgltf_data** data);
|
||||||
|
|
||||||
#endif /* FILE_UTILS_H */
|
#endif /* FILE_UTILS_H */
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
rse_utilities_srcs = [
|
rse_utilities_srcs = [
|
||||||
'src/file_utils.c'
|
'src/file_utils.c',
|
||||||
|
'src/time_utils.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
cc = meson.get_compiler('c')
|
cc = meson.get_compiler('c')
|
||||||
|
|
||||||
sdl3_dep = dependency('sdl3',
|
sdl3_dep = dependency('sdl3',
|
||||||
version : '>=3.4.0')
|
version : '>=3.4.0')
|
||||||
stb_dep = dependency('stb',
|
stb = dependency('stb',
|
||||||
version : '>=2.30.0')
|
fallback: ['stb', 'stb_dep'])
|
||||||
|
|
||||||
m_dep = cc.find_library('m')
|
m_dep = cc.find_library('m')
|
||||||
|
|
||||||
rse_utilities_lib = shared_library(
|
rse_utilities_lib = shared_library(
|
||||||
@@ -16,7 +18,7 @@ rse_utilities_lib = shared_library(
|
|||||||
include_directories : ['.'],
|
include_directories : ['.'],
|
||||||
dependencies : [
|
dependencies : [
|
||||||
sdl3_dep,
|
sdl3_dep,
|
||||||
stb_dep,
|
stb,
|
||||||
m_dep,
|
m_dep,
|
||||||
],
|
],
|
||||||
install : true
|
install : true
|
||||||
|
|||||||
+28
-69
@@ -1,5 +1,10 @@
|
|||||||
#include "file_utils.h"
|
#include "file_utils.h"
|
||||||
|
|
||||||
|
#define CGLTF_IMPLEMENTATION
|
||||||
|
#include "cgltf.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -8,9 +13,6 @@
|
|||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "errors_common.h"
|
#include "errors_common.h"
|
||||||
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#include "stb/stb_image.h"
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -113,70 +115,7 @@ rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* buffer_size, int* width, int* height)
|
rse_err_t file_read_bytes(const char* file_name, size_t* bytes_count, unsigned char* buffer)
|
||||||
{
|
|
||||||
int channels = 0;
|
|
||||||
stbi_uc* pixel_buffer = NULL;
|
|
||||||
size_t image_buffer_size = 0U;
|
|
||||||
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
|
||||||
char real_path[MAX_PATH_LENGTH] = {0};
|
|
||||||
|
|
||||||
if (buffer_size == NULL) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL buffer_size");
|
|
||||||
|
|
||||||
return RSE_ERROR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (width == NULL) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL width");
|
|
||||||
|
|
||||||
return RSE_ERROR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (height == NULL) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Provided NULL height");
|
|
||||||
|
|
||||||
return RSE_ERROR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
|
||||||
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixel_buffer = stbi_load(real_path, width, height, &channels, STBI_rgb_alpha);
|
|
||||||
|
|
||||||
if (pixel_buffer == NULL) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to load texture from file: %s", file_name);
|
|
||||||
return RSE_ERROR_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
image_buffer_size = *width * *height * 4; // TODO: "4" is very hardcoded value. Change this
|
|
||||||
|
|
||||||
if ((buffer != NULL) && (image_buffer_size > *buffer_size)) {
|
|
||||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"Provided buffer is to small to hold pixel data. %ld vs %ld",
|
|
||||||
*buffer_size,
|
|
||||||
image_buffer_size);
|
|
||||||
ret = RSE_ERROR_INTERNAL_ERROR;
|
|
||||||
|
|
||||||
goto image_free;
|
|
||||||
}
|
|
||||||
|
|
||||||
*buffer_size = image_buffer_size;
|
|
||||||
|
|
||||||
if (buffer != NULL) {
|
|
||||||
memset(buffer, 0, *buffer_size);
|
|
||||||
memcpy(buffer, pixel_buffer, *buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
image_free:
|
|
||||||
stbi_image_free(pixel_buffer);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
rse_err_t file_read(const char* file_name, size_t* bytes_count, char* buffer)
|
|
||||||
{
|
{
|
||||||
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
||||||
FILE* file = NULL;
|
FILE* file = NULL;
|
||||||
@@ -193,7 +132,7 @@ rse_err_t file_read(const char* file_name, size_t* bytes_count, char* buffer)
|
|||||||
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open file for read: %s", real_path);
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open file for read: %s", real_path);
|
||||||
ret = RSE_ERROR_INTERNAL_ERROR;
|
ret = RSE_ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
goto file_close;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
@@ -238,5 +177,25 @@ rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer)
|
|||||||
fwrite(buffer, bytes_count, 1, file);
|
fwrite(buffer, bytes_count, 1, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
return RSE_ERROR_NO_ERROR;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
rse_err_t file_load_gltf(const char* file_name, cgltf_data** data)
|
||||||
|
{
|
||||||
|
char real_path[MAX_PATH_LENGTH] = {0};
|
||||||
|
rse_err_t ret = RSE_ERROR_NO_ERROR;
|
||||||
|
cgltf_options options = {0};
|
||||||
|
|
||||||
|
strncpy(real_path, file_name, MAX_PATH_LENGTH);
|
||||||
|
if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cgltf_parse_file(&options, real_path, data) != cgltf_result_success) {
|
||||||
|
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to parse GLTF data");
|
||||||
|
|
||||||
|
return RSE_ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include "time_utils.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "SDL3/SDL_timer.h"
|
||||||
|
#include "commons.h"
|
||||||
|
#include "errors_common.h"
|
||||||
|
|
||||||
|
#define NS_TO_S(time) (time/1000000000)
|
||||||
|
double g_last_time = 0.0;
|
||||||
|
|
||||||
|
rse_err_t time_init(void)
|
||||||
|
{
|
||||||
|
g_last_time = NS_TO_S((double)SDL_GetTicksNS());
|
||||||
|
|
||||||
|
return RSE_ERROR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
double time_get_sec_from_start(void)
|
||||||
|
{
|
||||||
|
return NS_TO_S((double)SDL_GetTicksNS());
|
||||||
|
}
|
||||||
|
|
||||||
|
void time_update(void)
|
||||||
|
{
|
||||||
|
g_last_time = NS_TO_S((double)SDL_GetTicksNS());
|
||||||
|
}
|
||||||
|
|
||||||
|
double time_get_dt(void)
|
||||||
|
{
|
||||||
|
float time = NS_TO_S((double)SDL_GetTicksNS());
|
||||||
|
float dt = time - g_last_time;
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* @file file_utils.h
|
||||||
|
* @author Piotr Krygier (everyonecancode@gmail.com)
|
||||||
|
* @brief Common functionality for all modules
|
||||||
|
* @version 0.1
|
||||||
|
* @date 2026-02-11
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2023
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TIME_UTILS_H_
|
||||||
|
#define TIME_UTILS_H_
|
||||||
|
|
||||||
|
#include "commons.h"
|
||||||
|
|
||||||
|
rse_err_t time_init(void);
|
||||||
|
void time_update(void);
|
||||||
|
|
||||||
|
double time_get_sec_from_start(void);
|
||||||
|
|
||||||
|
double time_get_dt(void);
|
||||||
|
|
||||||
|
#endif // !TIME_UTILS_H_
|
||||||
Reference in New Issue
Block a user