diff --git a/include/renderer/internal/vulkan/vulkan_buffer.h b/include/renderer/internal/vulkan/vulkan_buffer.h index 3afded3d..4c66f98a 100644 --- a/include/renderer/internal/vulkan/vulkan_buffer.h +++ b/include/renderer/internal/vulkan/vulkan_buffer.h @@ -28,6 +28,7 @@ #include #include // u32 +#include typedef struct vulkan_buffer_create_info_t { @@ -48,6 +49,7 @@ typedef struct vulkan_buffer_create_info_t typedef struct vulkan_buffer_t { + __VULKAN_OBJECT__; vulkan_renderer_t* renderer; // pointer to the vulkan_renderer_t object VkBuffer vo_handle; VkDeviceMemory vo_memory; diff --git a/include/renderer/internal/vulkan/vulkan_host_buffered_buffer.h b/include/renderer/internal/vulkan/vulkan_host_buffered_buffer.h index 5b123282..3e9e20c7 100644 --- a/include/renderer/internal/vulkan/vulkan_host_buffered_buffer.h +++ b/include/renderer/internal/vulkan/vulkan_host_buffered_buffer.h @@ -3,6 +3,7 @@ #include #include #include +#include typedef struct vulkan_host_buffered_buffer_create_info_t { @@ -19,6 +20,7 @@ typedef BUFFER buffer_t; /* a GPU buffer having a coherent copy on the host side */ typedef struct vulkan_host_buffered_buffer_t { + __VULKAN_OBJECT__; vulkan_renderer_t* renderer; vulkan_buffer_t device_buffer; buffer_t host_buffer; @@ -27,6 +29,9 @@ typedef struct vulkan_host_buffered_buffer_t bool is_dirty; } vulkan_host_buffered_buffer_t; +#define VULKAN_HOST_BUFFERED_BUFFER(typed_ptr) VULKAN_OBJECT_TYPE_CAST(vulkan_host_buffered_buffer_t*, VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, typed_ptr) +#define VULKAN_HOST_BUFFERED_BUFFER_CONST(typed_ptr) VULKAN_OBJECT_TYPE_CONST_CAST(const vulkan_host_buffered_buffer_t*, VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, typed_ptr) + BEGIN_CPP_COMPATIBLE diff --git a/include/renderer/internal/vulkan/vulkan_instance_buffer.h b/include/renderer/internal/vulkan/vulkan_instance_buffer.h index e2c9a6e2..bf6e8e61 100644 --- a/include/renderer/internal/vulkan/vulkan_instance_buffer.h +++ b/include/renderer/internal/vulkan/vulkan_instance_buffer.h @@ -27,6 +27,7 @@ #pragma once #include +#include #include typedef struct vulkan_renderer_t vulkan_renderer_t; @@ -39,6 +40,7 @@ typedef struct vulkan_instance_buffer_create_info_t typedef struct vulkan_instance_buffer_t { + __VULKAN_OBJECT__; vulkan_renderer_t* renderer; vulkan_buffer_t device_buffer; // buffer in the device memory multi_buffer_t host_buffer; // buffer in the host memory @@ -46,7 +48,8 @@ typedef struct vulkan_instance_buffer_t bool is_dirty; } vulkan_instance_buffer_t; -#define VULKAN_INSTANCE_BUFFER(ptr) CAST_TO(vulkan_instance_buffer_t*, ptr) +#define VULKAN_INSTANCE_BUFFER(ptr) VULKAN_OBJECT_TYPE_CAST(vulkan_instance_t*, VULKAN_OBJECT_TYPE_INSTANCE_BUFFER, ptr) +#define VULKAN_INSTANCE_BUFFER_CONST(ptr) VULKAN_OBJECT_TYPE_CONST_CAST(const vulkan_instance_t*, VULKAN_OBJECT_TYPE_INSTANCE_BUFFER, ptr) BEGIN_CPP_COMPATIBLE diff --git a/include/renderer/internal/vulkan/vulkan_object.h b/include/renderer/internal/vulkan/vulkan_object.h new file mode 100644 index 00000000..670ab2a9 --- /dev/null +++ b/include/renderer/internal/vulkan/vulkan_object.h @@ -0,0 +1,121 @@ +#pragma once + +#include // stdbool.h +#include // memset +#include // _debug_assert__ + +typedef enum vulkan_object_nationality_t +{ + VULKAN_OBJECT_NATIONALITY_UNDEFINED = 0, + VULKAN_OBJECT_NATIONALITY_EXTERNAL, + VULKAN_OBJECT_NATIONALITY_INTERNAL, + VULKAN_OBJECT_NATIONALITY_MAX +} vulkan_object_nationality_t; + +typedef enum vulkan_object_type_t +{ + VULKAN_OBJECT_TYPE_UNDEFINED = 0, + VULKAN_OBJECT_TYPE_BUFFER, + VULKAN_OBJECT_TYPE_SHADER_MODULE, + VULKAN_OBJECT_TYPE_INSTANCE_BUFFER, + VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, + VULKAN_OBJECT_TYPE_MAX +} vulkan_object_type_t; + +typedef struct vulkan_object_t +{ + vulkan_object_nationality_t nationality; + + /* type information need not to be retained in release mode */ + IF_DEBUG( vulkan_object_type_t type; ) +} vulkan_object_t; + +#define VULKAN_OBJECT(typed_ptr) REINTERPRET_CAST(vulkan_object_t*, typed_ptr) +#define VULKAN_OBJECT_CONST(typed_ptr) REINTERPRET_CONST_CAST(vulkan_object_t*, typed_ptr) +#define VULKAN_OBJECT_VOID(void_ptr) CAST_TO(vulkan_object_t*, void_ptr) +#define VULKAN_OBJECT_CONST_VOID(void_ptr) CAST_TO(const vulkan_object_t*, void_ptr) + +#define __VULKAN_OBJECT__ vulkan_object_t __vo##__LINE__ +#define VULKAN_OBJECT_INIT(typed_ptr, type, nationality) vulkan_object_init(VULKAN_OBJECT(typed_ptr), type, nationality) +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void vulkan_object_init(vulkan_object_t* obj, vulkan_object_type_t type, bool nationality) +{ + obj->type = type; + obj->nationality = nationality; +} +#define VULKAN_OBJECT_MEMZERO(typed_ptr, type) vulkan_object_memzero(CAST_TO(void*, VULKAN_OBJECT_VERIFY_FORWARD(typed_ptr)), sizeof(typed_ptr[0])) +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void vulkan_object_memzero(void* ptr, u32 size) +{ + _debug_assert__((ptr != NULL) && (size != 0)); + _debug_assert__(size >= sizeof(vulkan_object_t)); + memset(ptr + sizeof(vulkan_object_t), 0, size - sizeof(vulkan_object_t)); +} + + + + +/* nationality (memory ownership) */ +#define VULKAN_OBJECT_IS_INTERNAL(typed_ptr) (VULKAN_OBJECT_GET_NATIONALITY(typed_ptr) == VULKAN_OBJECT_NATIONALITY_INTERNAL) +#define VULKAN_OBJECT_IS_EXTERNAL(typed_ptr) (VULKAN_OBJECT_GET_NATIONALITY(typed_ptr) == VULKAN_OBJECT_NATIONALITY_EXTERNAL) +#define VULKAN_OBJECT_IS_UNDEFINED(typed_ptr) (VULKAN_OBJECT_GET_NATIONALITY(typed_ptr) == VULKAN_OBJECT_NATIONALITY_UNDEFINED) +#define VULKAN_OBJECT_IS_NATIONALITY_GARBAGE(typed_ptr) (VULKAN_OBJECT_IS_UNDEFINED(typed_ptr) || (VULKAN_OBJECT_GET_NATIONALITY(typed_ptr) >= VULKAN_OBJECT_NATIONALITY_MAX)) + +/* type of the object */ +#define VULKAN_OBJECT_IS_TYPE_UNDEFINED(typed_ptr) (VULKAN_OBJECT_GET_TYPE(typed_ptr) == VULKAN_OBJECT_TYPE_UNDEFINED) +#define VULKAN_OBJECT_IS_TYPE_GARBAGE(typed_ptr) (VULKAN_OBJECT_IS_TYPE_UNDEFINED(typed_ptr) || (VULKAN_OBJECT_GET_TYPE(typed_ptr) >= VULKAN_OBJECT_TYPE_MAX)) + +#define VULKAN_OBJECT_SET_NATIONALITY(typed_ptr, nationality) vulkan_object_set_nationality(VULKAN_OBJECT(typed_ptr), nationality) +#define VULKAN_OBJECT_GET_NATIONALITY(typed_ptr) vulkan_object_get_nationality(VULKAN_OBJECT_CONST(typed_ptr)) +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE vulkan_object_nationality_t vulkan_object_get_nationality(const vulkan_object_t* obj) { return obj->nationality; } +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void vulkan_object_set_nationality(vulkan_object_t* obj, bool nationality) { obj->nationality = nationality; } + +/* usage of VULKAN_OBJECT_SET_TYPE Or VULKAN_OBJECT_GET_TYPE is not permitted in release mode */ +#ifdef GLOBAL_DEBUG +# define VULKAN_OBJECT_SET_TYPE(typed_ptr, type) vulkan_object_set_type(VULKAN_OBJECT(typed_ptr), type) +# define VULKAN_OBJECT_GET_TYPE(typed_ptr) vulkan_object_get_type(VULKAN_OBJECT_CONST(typed_ptr)) + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE vulkan_object_type_t vulkan_object_get_type(const vulkan_object_t* obj) { return obj->type; } + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void vulkan_object_set_type(vulkan_object_t* obj, vulkan_object_type_t type) { obj->type = type; } +#endif /* GLOBAL_DEBUG */ + +#ifdef GLOBAL_DEBUG +# define VULKAN_OBJECT_TYPE_CAST(dst_ptr_type, vulkan_object_type, src_typed_ptr) REINTERPRET_CAST(dst_ptr_type, VULKAN_OBJECT_TYPE_CHECK_FORWARD(src_typed_ptr, vulkan_object_type)) +# define VULKAN_OBJECT_TYPE_CONST_CAST(dst_ptr_type, vulkan_object_type, src_typed_ptr) REINTERPRET_CONST_CAST(dst_ptr_type, VULKAN_OBJECT_TYPE_CHECK_CONST_FORWARD(src_typed_ptr, vulkan_object_type)) +# define VULKAN_OBJECT_TYPE_CHECK(type_ptr, vulkan_object_type) vulkan_object_type_check(type_ptr, vulkan_object_type) + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void vulkan_object_type_check(const vulkan_object_t* obj, vulkan_object_type_t type) + { + debug_assert__(obj->type == type, "Vulkan Object type mismatched"); + } +# define VULKAN_OBJECT_TYPE_CHECK_FORWARD(typed_ptr, vulkan_object_type) vulkan_object_type_check_forward(VULKAN_OBJECT_CONST(typed_ptr), vulkan_object_type) + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void* vulkan_object_type_check_forward(const vulkan_object_t* obj, vulkan_object_type_t type) + { + vulkan_object_type_check(obj, type); + return CAST_TO(void*, obj); + } +# define VULKAN_OBJECT_TYPE_CHECK_CONST_FORWARD(typed_ptr, vulkan_object_type) vulkan_object_type_check_const_forward(VULKAN_OBJECT_CONST(typed_ptr), vulkan_object_type) + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE const void* vulkan_object_type_check_const_forward(const vulkan_object_t* obj, vulkan_object_type_t type) + { + vulkan_object_type_check(obj, type); + return CAST_TO(const void*, obj); + } +#else /* GLOBAL_DEBUG */ +# define VULKAN_OBJECT_TYPE_CAST(dst_ptr_type, vulkan_object_type, src_typed_ptr) REINTERPRET_CAST(dst_ptr_type, src_typed_ptr) +# define VULKAN_OBJECT_TYPE_CONST_CAST(dst_ptr_type, vulkan_object_type, src_typed_ptr) REINTERPRET_CONST_CAST(dst_ptr_type, src_typed_ptr) +#endif /* GLOBAL_RELEASE */ + +/* no verification of vulkan objects can be done in release mode */ +#ifdef GLOBAL_DEBUG +# define VULKAN_OBJECT_VERIFY(typed_ptr) vulkan_object_verify(VULKAN_OBJECT_CONST(typed_ptr)) + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void vulkan_object_verify(const vulkan_object_t* obj) + { + debug_assert__(!VULKAN_OBJECT_IS_TYPE_GARBAGE(obj), "Vulkan Object Type is Garbage"); + debug_assert__(!VULKAN_OBJECT_IS_NATIONALITY_GARBAGE(obj), "Vulkan Object Nationality is Garbage"); + } +# define VULKAN_OBJECT_VERIFY_FORWARD(typed_ptr) vulkan_object_verify_forward(VULKAN_OBJECT_CONST(typed_ptr)) + static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE const void* vulkan_object_verify_forward(const vulkan_object_t* obj) + { + vulkan_object_verify(obj); + return CAST_TO(const void*, obj); + } +#else +# define VULKAN_OBJECT_VERIFY(typed_ptr) +# define VULKAN_OBJECT_VERIFY_FORWARD(typed_ptr) typed_ptr +#endif diff --git a/include/renderer/internal/vulkan/vulkan_renderer.h b/include/renderer/internal/vulkan/vulkan_renderer.h index 69b44f92..b5a8ebc0 100644 --- a/include/renderer/internal/vulkan/vulkan_renderer.h +++ b/include/renderer/internal/vulkan/vulkan_renderer.h @@ -36,11 +36,14 @@ #include #include +#include + typedef struct render_window_t render_window_t; typedef struct vulkan_shader_library_t vulkan_shader_library_t; typedef struct vulkan_material_library_t vulkan_material_library_t; typedef struct vulkan_render_pass_pool_t vulkan_render_pass_pool_t; typedef struct vulkan_camera_system_t vulkan_camera_system_t; +typedef struct vulkan_buffer_t vulkan_buffer_t; typedef enum vulkan_renderer_gpu_type_t { @@ -76,6 +79,24 @@ typedef struct vulkan_renderer_t VkSemaphore vo_render_finished_semaphore; VkFence vo_fence; + /* global_set::screen_info + * { + * uvec2 resolution; // resolution of the display (in pixels) + * uvec2 dpi; // dpi of the display (in pixels per inch) + * uvec2 size; // window size (in pixels) + * mat4 matrix; // matrix to project onto the window/screen + * } */ + struct + { + struct_descriptor_t struct_def; + struct_field_handle_t resolution_field; + struct_field_handle_t dpi_field; + struct_field_handle_t size_field; + struct_field_handle_t matrix_field; + vulkan_buffer_t* buffer; + event_subscription_handle_t update_handle; + } screen_info; + render_window_t* window; vulkan_swapchain_create_info_t swapchain_create_info; // for recreating the swapchain vulkan_swapchain_t* swapchain; diff --git a/include/renderer/internal/vulkan/vulkan_shader_module.h b/include/renderer/internal/vulkan/vulkan_shader_module.h index 3222fcb0..3ae8188a 100644 --- a/include/renderer/internal/vulkan/vulkan_shader_module.h +++ b/include/renderer/internal/vulkan/vulkan_shader_module.h @@ -29,6 +29,7 @@ #include #include #include +#include typedef struct vulkan_shader_module_create_info_t { @@ -53,11 +54,15 @@ typedef struct vulkan_shader_module_load_info_t /* vulkan_stage_shader_t renamed to vulkan_shader_module_t */ typedef struct vulkan_shader_module_t { + __VULKAN_OBJECT__; vulkan_renderer_t* renderer; VkShaderModule vo_module; VkPipelineShaderStageCreateInfo vo_stage; } vulkan_shader_module_t; +#define VULKAN_SHADER_MODULE(typed_ptr) VULKAN_OBJECT_TYPE_CAST(vulkan_shader_module_t*, VULKAN_OBJECT_TYPE_SHADER_MODULE, typed_ptr) +#define VULKAN_SHADER_MODULE_CONST(typed_ptr) VULKAN_OBJECT_TYPE_CONST_CAST(const vulkan_shader_module_t*, VULKAN_OBJECT_TYPE_SHADER_MODULE, typed_ptr) + BEGIN_CPP_COMPATIBLE /* constructors & destructors */ diff --git a/include/renderer/render_window.h b/include/renderer/render_window.h index d479b50a..37232a3c 100644 --- a/include/renderer/render_window.h +++ b/include/renderer/render_window.h @@ -27,10 +27,8 @@ #pragma once #include -#include #include #include -#include static const type_t TYPE_ID(render_window_t) = TYPE_ID_CREATE(1); @@ -41,24 +39,6 @@ typedef struct render_window_t /* handle to the internal GLFWwindow object */ void* handle; - /* pointer to API specific GPU buffer object */ - void* api_buffer; - /* pointer to the memory mapped GPU buffer data of the above object */ - void* api_buffer_data_ptr; - - /* global_set::screen_info - * { - * uvec2 resolution; // resolution of the display (in pixels) - * uvec2 dpi; // dpi of the display (in pixels per inch) - * uvec2 size; // window size (in pixels) - * mat4 matrix; // matrix to project onto the window/screen - * } */ - struct_descriptor_t screen_info_struct; - struct_field_handle_t resolution_field; - struct_field_handle_t dpi_field; - struct_field_handle_t size_field; - struct_field_handle_t matrix_field; - /* width of the window (in pixels) */ u32 width; /* height of the window (in pixels) */ @@ -75,8 +55,6 @@ RENDERER_API bool render_window_should_close(render_window_t* window); RENDERER_API void render_window_poll_events(render_window_t* window); RENDERER_API void render_window_destroy(render_window_t* window); -RENDERER_API void render_window_initialize_api_buffer(render_window_t* window, void* driver); - // getters RENDERER_API void render_window_get_framebuffer_extent(render_window_t* window, u32* out_width, u32* out_height); diff --git a/include/renderer/struct_descriptor.h b/include/renderer/struct_descriptor.h index 88bea56d..dda7f9a4 100644 --- a/include/renderer/struct_descriptor.h +++ b/include/renderer/struct_descriptor.h @@ -338,6 +338,7 @@ RENDERER_API void struct_descriptor_add_field(struct_descriptor_t* descriptor, c RENDERER_API void struct_descriptor_add_field2(struct_descriptor_t* descriptor, const char* name, struct_descriptor_t* record); RENDERER_API void struct_descriptor_add_field_array(struct_descriptor_t* descriptor, const char* name, u8 type, u32 array_size); RENDERER_API void struct_descriptor_add_field_array2(struct_descriptor_t* descriptor, const char* name, struct_descriptor_t* record, u32 array_size); +RENDERER_API void struct_descriptor_free(memory_allocator_t* allocator, struct_descriptor_t* descriptor); RENDERER_API void struct_descriptor_map(struct_descriptor_t* descriptor, void* ptr); RENDERER_API void* struct_descriptor_get_mapped(struct_descriptor_t* descriptor); diff --git a/shared-dependencies/BufferLib b/shared-dependencies/BufferLib index ba6161cb..b1641370 160000 --- a/shared-dependencies/BufferLib +++ b/shared-dependencies/BufferLib @@ -1 +1 @@ -Subproject commit ba6161cbf9c61b14413dfd2912207da8e090ee49 +Subproject commit b1641370a338ff0e269194e327e49d9b7f49990e diff --git a/source/renderer/render_window.c b/source/renderer/render_window.c index dc8cd3f9..93b0ec95 100644 --- a/source/renderer/render_window.c +++ b/source/renderer/render_window.c @@ -31,11 +31,8 @@ #include #include #include -#include -#include #include #include -#include #include #define GLFW_INCLUDE_VULKAN @@ -50,24 +47,10 @@ static void glfwErrorCallback(int code, const char* description) } #endif -static void update_screen_info(render_window_t* window) -{ - /* set the window size value */ - AUTO size = iextent2d(window->width, window->height); - struct_descriptor_set_uvec2(&window->screen_info_struct, window->size_field, CAST_TO(uint*, &size)); - - /* set the screen matrix */ - AUTO matrix = mat4_ortho_projection(-0.04f, 100, size.height, (f32)size.width / (f32)size.height); - mat4_move(matrix, mat4_transpose(matrix)); - struct_descriptor_set_mat4(&window->screen_info_struct, window->matrix_field, CAST_TO(f32*, &matrix)); -} - static void glfwOnWindowResizeCallback(GLFWwindow* glfw_window, int width, int height) { AUTO window = CAST_TO(render_window_t*, glfwGetWindowUserPointer(glfw_window)); render_window_get_framebuffer_extent(window, &window->width, &window->height); - /* update the screen matrix and window size in the global set */ - update_screen_info(window); event_publish(window->on_resize_event); } @@ -107,12 +90,6 @@ RENDERER_API void render_window_poll_events(render_window_t* window) RENDERER_API void render_window_destroy(render_window_t* window) { - _debug_assert__(window->api_buffer != NULL); - - /* unmap the gpu buffer's data before destroying it */ - vulkan_buffer_unmap(VULKAN_BUFFER(window->api_buffer)); - vulkan_buffer_destroy(VULKAN_BUFFER(window->api_buffer)); - event_destroy(window->on_resize_event); event_release_resources(window->on_resize_event); glfwDestroyWindow(window->handle); @@ -142,53 +119,3 @@ RENDERER_API void render_window_get_vulkan_surface(render_window_t* window, void VkSurfaceKHR surface = glfw_get_vulkan_surface(window->handle, CAST_TO(vulkan_renderer_t*, vk_driver)); memcpy(out_surface, &surface, sizeof(VkSurfaceKHR)); } - -RENDERER_API void render_window_initialize_api_buffer(render_window_t* window, void* vk_driver) -{ - _debug_assert_wrn__(window->api_buffer == NULL); - - /* definition of the 'screen info' struct */ - struct_descriptor_begin(window->allocator, &window->screen_info_struct, "screen_info", 0); - struct_descriptor_add_field_uvec2(&window->screen_info_struct, "resolution"); - struct_descriptor_add_field_uvec2(&window->screen_info_struct, "dpi"); - struct_descriptor_add_field_uvec2(&window->screen_info_struct, "size"); - struct_descriptor_add_field_mat4(&window->screen_info_struct, "matrix"); - struct_descriptor_end(window->allocator, &window->screen_info_struct); - - /* get the field handles, to later use them to modify the field values */ - window->resolution_field = struct_descriptor_get_field_handle(&window->screen_info_struct, "resolution"); - window->dpi_field = struct_descriptor_get_field_handle(&window->screen_info_struct, "dpi"); - window->size_field = struct_descriptor_get_field_handle(&window->screen_info_struct, "size"); - window->matrix_field = struct_descriptor_get_field_handle(&window->screen_info_struct, "matrix"); - - /* calculate the size of the struct and offsets of the fields inside it */ - struct_descriptor_recalculate(&window->screen_info_struct); - - /* create gpu buffer with the required size */ - vulkan_buffer_create_info_t create_info = - { - .size = struct_descriptor_sizeof(&window->screen_info_struct), - .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .vo_sharing_mode = VK_SHARING_MODE_EXCLUSIVE, - .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT - }; - vulkan_buffer_t* buffer = vulkan_buffer_create(CAST_TO(vulkan_renderer_t*, vk_driver), &create_info); - window->api_buffer = CAST_TO(void*, buffer); - - /* write to the descriptor with binding VULKAN_DESCRIPTOR_BINDING_SCREEN */ - vulkan_descriptor_set_write_uniform_buffer(&CAST_TO(vulkan_renderer_t*, vk_driver)->global_set, VULKAN_DESCRIPTOR_BINDING_SCREEN, buffer); - - /* map the gpu buffer to the host memory */ - struct_descriptor_map(&window->screen_info_struct, vulkan_buffer_map(buffer)); - - /* set the display resolution value */ - AUTO resolution = display_get_resolution(); - struct_descriptor_set_uvec2(&window->screen_info_struct, window->size_field, CAST_TO(uint*, &resolution)); - - /* set the display dpi value */ - AUTO dpi = display_get_dpi(); - struct_descriptor_set_uvec2(&window->screen_info_struct, window->dpi_field, CAST_TO(uint*, &dpi)); - - /* set the screen matrix and window size */ - update_screen_info(window); -} diff --git a/source/renderer/struct_descriptor.c b/source/renderer/struct_descriptor.c index 2b51a739..b62827da 100644 --- a/source/renderer/struct_descriptor.c +++ b/source/renderer/struct_descriptor.c @@ -465,6 +465,21 @@ RENDERER_API void struct_descriptor_add_field_array2(struct_descriptor_t* descri field->array_size = array_size; } +static void* _malloc(buf_ucount_t size, void* user_data) +{ + return memory_allocator_alloc(CAST_TO(memory_allocator_t*, user_data), MEMORY_ALLOCATION_TYPE_IN_MEMORY_BUFFER, size); +} + +static void _free(void* ptr, void* user_data) +{ + memory_allocator_dealloc(CAST_TO(memory_allocator_t*, user_data), ptr); +} + +static void* _realloc(void* old_ptr, buf_ucount_t size, void* user_data) +{ + return memory_allocator_realloc(CAST_TO(memory_allocator_t*, user_data), old_ptr, MEMORY_ALLOCATION_TYPE_IN_MEMORY_BUFFER, size); +} + RENDERER_API void struct_descriptor_begin(memory_allocator_t* allocator, struct_descriptor_t* descriptor, const char* name, u8 type) { memzero(descriptor, struct_descriptor_t); @@ -473,7 +488,7 @@ RENDERER_API void struct_descriptor_begin(memory_allocator_t* allocator, struct_ descriptor->type = type; BUFFER* buffer = memory_allocator_alloc_obj(allocator, MEMORY_ALLOCATION_TYPE_OBJ_BUFFER, BUFFER); - BUFFER _buffer = buf_create(sizeof(struct_field_t), 1, 0); + BUFFER _buffer = buf_create_a(sizeof(struct_field_t), 1, 0, _malloc, _free, _realloc, CAST_TO(void*, allocator)); memcopy(buffer, &_buffer, BUFFER); descriptor->fields = CAST_TO(struct_field_t*, buffer); } @@ -487,6 +502,21 @@ RENDERER_API void struct_descriptor_end(memory_allocator_t* allocator, struct_de struct_descriptor_recalculate(descriptor); } +RENDERER_API void struct_descriptor_free(memory_allocator_t* allocator, struct_descriptor_t* descriptor) +{ + _debug_assert__((descriptor->field_count != 0) || (descriptor->fields == NULL)); + if(descriptor->field_count > 0) + { + for(u32 i = 0; i < descriptor->field_count; i++) + { + struct_field_t field = descriptor->fields[i]; + if(field.record != NULL) + struct_descriptor_free(allocator, field.record); + } + memory_allocator_dealloc(allocator, descriptor->fields); + } +} + #ifdef GLOBAL_DEBUG static void check_precondition(struct_descriptor_t* descriptor, struct_field_handle_t handle) diff --git a/source/renderer/vulkan/vulkan_bitmap_text.c b/source/renderer/vulkan/vulkan_bitmap_text.c index b0752e70..a1be2be6 100644 --- a/source/renderer/vulkan/vulkan_bitmap_text.c +++ b/source/renderer/vulkan/vulkan_bitmap_text.c @@ -134,6 +134,7 @@ RENDERER_API void vulkan_bitmap_text_create_no_alloc(vulkan_renderer_t* renderer /* initially we can store render information of upto 512 characters, so there will be no chance of buffer resize until 512 */ .capacity = 512 }; + VULKAN_OBJECT_INIT(&text->glyph_render_data_buffer, VULKAN_OBJECT_TYPE_INSTANCE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_instance_buffer_create(renderer, &grd_buffer_create_info, &text->glyph_render_data_buffer); _debug_assert__(glsl_sizeof(vulkan_bitmap_text_glyph_glsl_glyph_texcoord_t) == sizeof(vulkan_bitmap_text_glyph_glsl_glyph_texcoord_t)); @@ -147,6 +148,7 @@ RENDERER_API void vulkan_bitmap_text_create_no_alloc(vulkan_renderer_t* renderer /* this buffer will be indexed with glyph_render_data_t.indx */ .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT }; + VULKAN_OBJECT_INIT(&text->glyph_texcoord_buffer, VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_host_buffered_buffer_create_no_alloc(renderer, &buffer_create_info, &text->glyph_texcoord_buffer); _debug_assert__(glsl_sizeof(glsl_mat4_t) == sizeof(glsl_mat4_t)); @@ -160,6 +162,7 @@ RENDERER_API void vulkan_bitmap_text_create_no_alloc(vulkan_renderer_t* renderer /* this buffer will be indexed with glyph_render_data_t.stid */ .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT }; + VULKAN_OBJECT_INIT(&text->text_string_transform_buffer, VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_host_buffered_buffer_create_no_alloc(renderer, &buffer_create_info, &text->text_string_transform_buffer); text->glyph_texcoord_index_table = dictionary_create(pair_t(utf32_t, u32), u32, 127, utf32_u32_equal_to); @@ -228,8 +231,9 @@ RENDERER_API void vulkan_bitmap_text_release_resources(vulkan_bitmap_text_t* tex { buf_free(&text->glyph_layout_data_buffer); buf_free(&text->text_strings); - // vulkan_host_buffered_buffer_release_resources(&text->text_string_transform_buffer); - // vulkan_host_buffered_buffer_release_resources(&text->glyph_texcoord_buffer); + vulkan_instance_buffer_release_resources(&text->glyph_render_data_buffer); + vulkan_host_buffered_buffer_release_resources(&text->text_string_transform_buffer); + vulkan_host_buffered_buffer_release_resources(&text->glyph_texcoord_buffer); } RENDERER_API void vulkan_bitmap_text_draw(vulkan_bitmap_text_t* text) diff --git a/source/renderer/vulkan/vulkan_buffer.c b/source/renderer/vulkan/vulkan_buffer.c index 5825c5b5..8d003416 100644 --- a/source/renderer/vulkan/vulkan_buffer.c +++ b/source/renderer/vulkan/vulkan_buffer.c @@ -41,6 +41,7 @@ RENDERER_API vulkan_buffer_t* vulkan_buffer_new(memory_allocator_t* allocator) { vulkan_buffer_t* buffer = memory_allocator_alloc_obj(allocator, MEMORY_ALLOCATION_TYPE_OBJ_VK_BUFFER, vulkan_buffer_t); memzero(buffer, vulkan_buffer_t); + VULKAN_OBJECT_INIT(buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_INTERNAL); return buffer; } @@ -54,9 +55,9 @@ RENDERER_API vulkan_buffer_t* vulkan_buffer_create(vulkan_renderer_t* renderer, RENDERER_API void vulkan_buffer_create_no_alloc(vulkan_renderer_t* renderer, vulkan_buffer_create_info_t* create_info, vulkan_buffer_t* buffer) { - assert(((create_info->stride != 0) && (create_info->count != 0)) || (create_info->size != 0)); + _debug_assert__(((create_info->stride != 0) && (create_info->count != 0)) || (create_info->size != 0)); - memzero(buffer, vulkan_buffer_t); + VULKAN_OBJECT_MEMZERO(buffer, vulkan_buffer_t); buffer->renderer = renderer; u32 buffer_size = (create_info->size == 0) ? (create_info->stride * create_info->count) : create_info->size; @@ -99,8 +100,8 @@ RENDERER_API void vulkan_buffer_destroy(vulkan_buffer_t* buffer) RENDERER_API void vulkan_buffer_release_resources(vulkan_buffer_t* buffer) { - // TODO: - // heap_free(buffer); + if(VULKAN_OBJECT_IS_INTERNAL(buffer)) + memory_allocator_dealloc(buffer->renderer->allocator, buffer); } RENDERER_API void vulkan_buffer_copy_data(vulkan_buffer_t* buffer, u32 buffer_offset, void* data, u32 data_size) diff --git a/source/renderer/vulkan/vulkan_camera.c b/source/renderer/vulkan/vulkan_camera.c index fcfdbf79..c5824e04 100644 --- a/source/renderer/vulkan/vulkan_camera.c +++ b/source/renderer/vulkan/vulkan_camera.c @@ -64,6 +64,7 @@ static void* create_buffer_and_map(vulkan_camera_t* camera, vulkan_buffer_t OUT .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; _debug_assert__(create_info.size == (64 * 4)); + VULKAN_OBJECT_INIT(buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(camera->renderer, &create_info, buffer); vulkan_descriptor_set_create_info_t set_create_info = @@ -547,6 +548,7 @@ RENDERER_API void vulkan_camera_destroy(vulkan_camera_t* camera) vulkan_descriptor_set_destroy(&camera->sets[i]); vulkan_buffer_unmap(&camera->buffers[i]); vulkan_buffer_destroy(&camera->buffers[i]); + vulkan_buffer_release_resources(&camera->buffers[i]); } buf_ucount_t pass_count = buf_get_element_count(&camera->render_passes); for(buf_ucount_t i = 0; i < pass_count; i++) diff --git a/source/renderer/vulkan/vulkan_graphics_pipeline.c b/source/renderer/vulkan/vulkan_graphics_pipeline.c index e049f41e..31790cd8 100644 --- a/source/renderer/vulkan/vulkan_graphics_pipeline.c +++ b/source/renderer/vulkan/vulkan_graphics_pipeline.c @@ -67,6 +67,7 @@ RENDERER_API void vulkan_graphics_pipeline_create_no_alloc(vulkan_renderer_t* re for(u32 i = 0; i < pipeline->shader_module_count; i++) { vulkan_shader_module_create_info_t module_create_info = REINTERPRET_TO(vulkan_shader_module_create_info_t, create_info->spirv_codes[i]); + VULKAN_OBJECT_INIT(&pipeline->shader_modules[i], VULKAN_OBJECT_TYPE_SHADER_MODULE, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_shader_module_create_no_alloc(renderer, &module_create_info, &pipeline->shader_modules[i]); pipeline->vo_shader_stages[i] = pipeline->shader_modules[i].vo_stage; } @@ -343,10 +344,18 @@ RENDERER_API void vulkan_graphics_pipeline_destroy(vulkan_graphics_pipeline_t* p { vkDestroyPipeline(pipeline->renderer->logical_device->vo_handle, pipeline->vo_handle, VULKAN_ALLOCATION_CALLBACKS(pipeline->renderer)); pipeline->vo_handle = VK_NULL_HANDLE; + + /* destroy shader modules */ + for(u32 i = 0; i < pipeline->shader_module_count; i++) + vulkan_shader_module_destroy(&pipeline->shader_modules[i]); } RENDERER_API void vulkan_graphics_pipeline_release_resources(vulkan_graphics_pipeline_t* pipeline) { + /* destroy shader modules */ + for(u32 i = 0; i < pipeline->shader_module_count; i++) + vulkan_shader_module_release_resources(&pipeline->shader_modules[i]); + memory_allocator_dealloc(pipeline->renderer->allocator, pipeline->shader_modules); memory_allocator_dealloc(pipeline->renderer->allocator, pipeline->vo_shader_stages); memory_allocator_dealloc(pipeline->renderer->allocator, pipeline->vo_binding_descriptions); diff --git a/source/renderer/vulkan/vulkan_host_buffered_buffer.c b/source/renderer/vulkan/vulkan_host_buffered_buffer.c index 007003f5..5edf3d7c 100644 --- a/source/renderer/vulkan/vulkan_host_buffered_buffer.c +++ b/source/renderer/vulkan/vulkan_host_buffered_buffer.c @@ -6,6 +6,7 @@ RENDERER_API vulkan_host_buffered_buffer_t* vulkan_host_buffered_buffer_new(memo { vulkan_host_buffered_buffer_t* buffer = memory_allocator_alloc_obj(allocator, MEMORY_ALLOCATION_TYPE_OBJ_VK_HOST_BUFFERED_BUFFER, vulkan_host_buffered_buffer_t); memzero(buffer, vulkan_host_buffered_buffer_t); + VULKAN_OBJECT_INIT(buffer, VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); return buffer; } @@ -18,7 +19,7 @@ RENDERER_API vulkan_host_buffered_buffer_t* vulkan_host_buffered_buffer_create(v RENDERER_API void vulkan_host_buffered_buffer_create_no_alloc(vulkan_renderer_t* renderer, vulkan_host_buffered_buffer_create_info_t* create_info, vulkan_host_buffered_buffer_t OUT buffer) { - memzero(buffer, vulkan_host_buffered_buffer_t); + VULKAN_OBJECT_MEMZERO(buffer, vulkan_host_buffered_buffer_t); buffer->renderer = renderer; /* if capacity is non zero (> 0) then create a GPU side buffer */ if(create_info->capacity > 0) @@ -31,6 +32,7 @@ RENDERER_API void vulkan_host_buffered_buffer_create_no_alloc(vulkan_renderer_t* .vo_sharing_mode = VK_SHARING_MODE_EXCLUSIVE, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(&buffer->device_buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(renderer, &buffer_create_info, &buffer->device_buffer); buffer->has_device_buffer = true; } @@ -53,7 +55,8 @@ RENDERER_API void vulkan_host_buffered_buffer_destroy(vulkan_host_buffered_buffe RENDERER_API void vulkan_host_buffered_buffer_release_resources(vulkan_host_buffered_buffer_t* buffer) { buf_free(&buffer->host_buffer); - memory_allocator_dealloc(buffer->allocator, buffer); + if(VULKAN_OBJECT_IS_INTERNAL(buffer)) + memory_allocator_dealloc(buffer->allocator, buffer); } @@ -94,6 +97,7 @@ RENDERER_API bool vulkan_host_buffered_buffer_commit(vulkan_host_buffered_buffer { _debug_assert__(vulkan_buffer_get_size(device_buffer) != 0); vulkan_buffer_destroy(device_buffer); + vulkan_buffer_release_resources(device_buffer); } /* create a new vulkan buffer object */ @@ -104,6 +108,7 @@ RENDERER_API bool vulkan_host_buffered_buffer_commit(vulkan_host_buffered_buffer .vo_sharing_mode = VK_SHARING_MODE_EXCLUSIVE, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(device_buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(buffer->renderer, &create_info, device_buffer); buffer->has_device_buffer = true; if(is_resized != NULL) diff --git a/source/renderer/vulkan/vulkan_instance_buffer.c b/source/renderer/vulkan/vulkan_instance_buffer.c index d747c031..a8e84e78 100644 --- a/source/renderer/vulkan/vulkan_instance_buffer.c +++ b/source/renderer/vulkan/vulkan_instance_buffer.c @@ -27,12 +27,14 @@ #include #include #include // memcopyv +#include // constructors and destructors RENDERER_API void vulkan_instance_buffer_create(vulkan_renderer_t* renderer, vulkan_instance_buffer_create_info_t* create_info, vulkan_instance_buffer_t* out_instance_buffer) { _debug_assert__(out_instance_buffer != NULL); _debug_assert__(create_info->stride != 0); + VULKAN_OBJECT_MEMZERO(out_instance_buffer, vulkan_instance_buffer_t); multi_buffer_create(create_info->stride, create_info->capacity, &out_instance_buffer->host_buffer); vulkan_buffer_init(&out_instance_buffer->device_buffer); out_instance_buffer->renderer = renderer; @@ -47,6 +49,7 @@ RENDERER_API void vulkan_instance_buffer_create(vulkan_renderer_t* renderer, vul .vo_sharing_mode = VK_SHARING_MODE_EXCLUSIVE, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(&out_instance_buffer->device_buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(renderer, &_create_info, &out_instance_buffer->device_buffer); out_instance_buffer->has_device_buffer = true; } @@ -61,10 +64,11 @@ RENDERER_API void vulkan_instance_buffer_destroy(vulkan_instance_buffer_t* insta RENDERER_API void vulkan_instance_buffer_release_resources(vulkan_instance_buffer_t* instance_buffer) { - // not need to call _release_resources for instance_buffer->device_buffer because it is already inlined inside vulkan_instance_buffer_t object - // if(instance_buffer->has_device_buffer) - // vulkan_buffer_release_resources(&instance_buffer->device_buffer); + if(instance_buffer->has_device_buffer) + vulkan_buffer_release_resources(&instance_buffer->device_buffer); multi_buffer_free(&instance_buffer->host_buffer); + if(VULKAN_OBJECT_IS_INTERNAL(instance_buffer)) + memory_allocator_dealloc(instance_buffer->renderer->allocator, instance_buffer); } // getters @@ -105,7 +109,10 @@ RENDERER_API bool vulkan_instance_buffer_commit(vulkan_instance_buffer_t* instan if(count > device_buffer->count) { if(instance_buffer->has_device_buffer) + { vulkan_buffer_destroy(device_buffer); + vulkan_buffer_release_resources(device_buffer); + } vulkan_buffer_create_info_t create_info = { .stride = buf_get_element_size(&host_buffer->buffer), @@ -114,6 +121,7 @@ RENDERER_API bool vulkan_instance_buffer_commit(vulkan_instance_buffer_t* instan .vo_sharing_mode = VK_SHARING_MODE_EXCLUSIVE, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(device_buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(instance_buffer->renderer, &create_info, device_buffer); instance_buffer->has_device_buffer = true; _is_resized = true; diff --git a/source/renderer/vulkan/vulkan_light.c b/source/renderer/vulkan/vulkan_light.c index 913d1a00..f694b050 100644 --- a/source/renderer/vulkan/vulkan_light.c +++ b/source/renderer/vulkan/vulkan_light.c @@ -101,7 +101,7 @@ static void setup_gpu_resources(vulkan_light_t* light) .vo_sharing_mode = light->renderer->vo_sharing_mode, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; - + VULKAN_OBJECT_INIT(&light->buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(light->renderer, &create_info, &light->buffer); struct_descriptor_map(&light->struct_definition, vulkan_buffer_map(&light->buffer)); vulkan_descriptor_set_write_uniform_buffer(&light->renderer->global_set, VULKAN_DESCRIPTOR_BINDING_LIGHT, &light->buffer); diff --git a/source/renderer/vulkan/vulkan_material.c b/source/renderer/vulkan/vulkan_material.c index 10c1866b..2648061d 100644 --- a/source/renderer/vulkan/vulkan_material.c +++ b/source/renderer/vulkan/vulkan_material.c @@ -85,6 +85,7 @@ static void setup_material_resources(vulkan_material_t* material) .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(&resource->buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(material->renderer, &create_info, &resource->buffer); vulkan_descriptor_set_write_uniform_buffer(&material->material_set, binding->binding_number, &resource->buffer); } diff --git a/source/renderer/vulkan/vulkan_mesh.c b/source/renderer/vulkan/vulkan_mesh.c index 7c34fb94..844d13f4 100644 --- a/source/renderer/vulkan/vulkan_mesh.c +++ b/source/renderer/vulkan/vulkan_mesh.c @@ -102,7 +102,7 @@ RENDERER_API void vulkan_mesh_destroy(vulkan_mesh_t* mesh) { AUTO vertex_buffer = CAST_TO(vulkan_vertex_buffer_t*, buf_get_ptr_at(&mesh->vertex_buffers, i)); vulkan_buffer_destroy(vertex_buffer->buffer); - // vulkan_buffer_release_resources(vertex_buffer->buffer); + vulkan_buffer_release_resources(vertex_buffer->buffer); } buf_clear(&mesh->vertex_buffers, NULL); diff --git a/source/renderer/vulkan/vulkan_render_object.c b/source/renderer/vulkan/vulkan_render_object.c index c21e6cc5..48f8a89e 100644 --- a/source/renderer/vulkan/vulkan_render_object.c +++ b/source/renderer/vulkan/vulkan_render_object.c @@ -76,6 +76,7 @@ static void setup_gpu_resources(vulkan_render_object_t* object) .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; _debug_assert__(create_info.size == (64 * 2)); + VULKAN_OBJECT_INIT(&object->buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(object->renderer, &create_info, &object->buffer); struct_descriptor_map(&object->struct_definition, vulkan_buffer_map(&object->buffer)); vulkan_descriptor_set_write_uniform_buffer(&object->object_set, VULKAN_DESCRIPTOR_BINDING_TRANSFORM, &object->buffer); diff --git a/source/renderer/vulkan/vulkan_renderer.c b/source/renderer/vulkan/vulkan_renderer.c index eb1a5eca..7713685b 100644 --- a/source/renderer/vulkan/vulkan_renderer.c +++ b/source/renderer/vulkan/vulkan_renderer.c @@ -37,7 +37,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -55,6 +57,7 @@ UNUSED_FUNCTION static void memory_allocator_dump(memory_allocator_t* allocator, } static void recreate_swapchain(void* _window, void* renderer); +static void update_screen_info(void* _window, void* renderer); RENDERER_API render_window_t* vulkan_renderer_get_window(vulkan_renderer_t* renderer) { return renderer->window; } @@ -184,6 +187,24 @@ static VkFence get_unsigned_fence(vulkan_renderer_t* renderer) # define PLATFORM_SPECIFIC_VK_SURFACE_EXTENSION "VK_KHR_win32_surface" #endif +static struct_descriptor_t create_screen_info_struct(memory_allocator_t* allocator) +{ + struct_descriptor_t screen_info_struct; + /* definition of the 'screen info' struct */ + struct_descriptor_begin(allocator, &screen_info_struct, "screen_info", 0); + struct_descriptor_add_field_uvec2(&screen_info_struct, "resolution"); + struct_descriptor_add_field_uvec2(&screen_info_struct, "dpi"); + struct_descriptor_add_field_uvec2(&screen_info_struct, "size"); + struct_descriptor_add_field_mat4(&screen_info_struct, "matrix"); + struct_descriptor_end(allocator, &screen_info_struct); + return screen_info_struct; +} + +static CAN_BE_UNUSED_FUNCTION INLINE_IF_RELEASE_MODE void destroy_screen_info_struct(memory_allocator_t* allocator, struct_descriptor_t* screen_info) +{ + struct_descriptor_free(allocator, screen_info); +} + RENDERER_API vulkan_renderer_t* vulkan_renderer_init(renderer_t* _renderer, vulkan_renderer_gpu_type_t preferred_gpu_type, u32 width, u32 height, const char* title, bool full_screen, bool resizable) { vulkan_renderer_t* renderer = memory_allocator_alloc_obj(allocator, MEMORY_ALLOCATION_TYPE_OBJ_renderer, vulkan_renderer_t); @@ -393,7 +414,46 @@ DEBUG_BLOCK setup_global_set(renderer); /* create GPU buffer (till now the logical device has been created) to store window details to be made available to shaders */ - render_window_initialize_api_buffer(renderer->window, renderer); + renderer->screen_info.struct_def = create_screen_info_struct(renderer->allocator); + /* calculate the size of the struct and offsets of the fields inside it */ + struct_descriptor_recalculate(&renderer->screen_info.struct_def); + /* get the field handles, to later use them to modify the field values */ + renderer->screen_info.resolution_field = struct_descriptor_get_field_handle(&renderer->screen_info.struct_def, "resolution"); + renderer->screen_info.dpi_field = struct_descriptor_get_field_handle(&renderer->screen_info.struct_def, "dpi"); + renderer->screen_info.size_field = struct_descriptor_get_field_handle(&renderer->screen_info.struct_def, "size"); + renderer->screen_info.matrix_field = struct_descriptor_get_field_handle(&renderer->screen_info.struct_def, "matrix"); + /* create gpu buffer with the required size */ + vulkan_buffer_create_info_t buffer_create_info = + { + .size = struct_descriptor_sizeof(&renderer->screen_info.struct_def), + .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + .vo_sharing_mode = VK_SHARING_MODE_EXCLUSIVE, + .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT + }; + renderer->screen_info.buffer = vulkan_buffer_create(renderer, &buffer_create_info); + + /* write to the descriptor with binding VULKAN_DESCRIPTOR_BINDING_SCREEN */ + vulkan_descriptor_set_write_uniform_buffer(&renderer->global_set, VULKAN_DESCRIPTOR_BINDING_SCREEN, renderer->screen_info.buffer); + + /* map the gpu buffer to the host memory */ + struct_descriptor_map(&renderer->screen_info.struct_def, vulkan_buffer_map(renderer->screen_info.buffer)); + + /* set the display resolution value */ + AUTO resolution = display_get_resolution(); + struct_descriptor_set_uvec2(&renderer->screen_info.struct_def, renderer->screen_info.size_field, CAST_TO(uint*, &resolution)); + + /* set the display dpi value */ + AUTO dpi = display_get_dpi(); + struct_descriptor_set_uvec2(&renderer->screen_info.struct_def, renderer->screen_info.dpi_field, CAST_TO(uint*, &dpi)); + + subscription = (event_subscription_create_info_t) + { + .handler = EVENT_HANDLER(update_screen_info), + .handler_data = (void*)renderer, + .wait_for = SIGNAL_NOTHING_BIT, + .signal = SIGNAL_NOTHING_BIT + }; + renderer->screen_info.update_handle = event_subscribe(renderer->window->on_resize_event, &subscription); // create the shader and material library renderer->shader_library = vulkan_shader_library_create(renderer); @@ -564,6 +624,7 @@ RENDERER_API bool vulkan_renderer_is_running(vulkan_renderer_t* renderer) RENDERER_API void vulkan_renderer_terminate(vulkan_renderer_t* renderer) { + event_unsubscribe(renderer->window->on_resize_event, renderer->screen_info.update_handle); event_unsubscribe(renderer->window->on_resize_event, renderer->swapchain_recreate_handle); // memory_allocator_dump(renderer->allocator, "memdump1.dump"); @@ -574,17 +635,25 @@ RENDERER_API void vulkan_renderer_terminate(vulkan_renderer_t* renderer) vulkan_camera_system_destroy(renderer->camera_system); vulkan_camera_system_release_resources(renderer->camera_system); - // destroy the shader library - vulkan_shader_library_destroy(renderer->shader_library); - vulkan_shader_library_release_resources(renderer->shader_library); + // destroy the render pass pool + vulkan_render_pass_pool_destroy(renderer->render_pass_pool); + vulkan_render_pass_pool_release_resources(renderer->render_pass_pool); // destroy the material library vulkan_material_library_destroy(renderer->material_library); vulkan_material_library_release_resources(renderer->material_library); - // destroy the render pass pool - vulkan_render_pass_pool_destroy(renderer->render_pass_pool); - vulkan_render_pass_pool_release_resources(renderer->render_pass_pool); + // destroy the shader library + vulkan_shader_library_destroy(renderer->shader_library); + vulkan_shader_library_release_resources(renderer->shader_library); + + /* unmap the gpu buffer's data before destroying it */ + vulkan_buffer_unmap(renderer->screen_info.buffer); + vulkan_buffer_destroy(renderer->screen_info.buffer); + vulkan_buffer_release_resources(renderer->screen_info.buffer); + + // release resources for screen info struct definition and its fields + struct_descriptor_free(renderer->allocator, &renderer->screen_info.struct_def); // destroy global set vulkan_descriptor_set_destroy(&renderer->global_set); @@ -598,39 +667,39 @@ RENDERER_API void vulkan_renderer_terminate(vulkan_renderer_t* renderer) vulkan_descriptor_set_layout_destroy(&renderer->global_set_layout); vulkan_descriptor_set_layout_release_resources(&renderer->global_set_layout); + vkDestroyDescriptorPool(renderer->logical_device->vo_handle, renderer->vo_descriptor_pool, VULKAN_ALLOCATION_CALLBACKS(renderer)); + + vkFreeCommandBuffers(renderer->logical_device->vo_handle, renderer->vo_command_pool, renderer->swapchain->image_count, renderer->vo_command_buffers); + memory_allocator_dealloc(renderer->allocator, renderer->vo_command_buffers); + // destroy swapchain vulkan_swapchain_destroy(renderer->swapchain); vulkan_swapchain_release_resources(renderer->swapchain); - // NOTE: VkSurfaceKHR must be destroyed after the swapchain - vkDestroySurfaceKHR(renderer->instance->handle, renderer->vo_surface, VULKAN_ALLOCATION_CALLBACKS(renderer)); - render_window_destroy(renderer->window); + vkFreeCommandBuffers(renderer->logical_device->vo_handle, renderer->vo_command_pool, 1, &renderer->vo_aux_command_buffer); - // destroy semaphores - vkDestroySemaphore(renderer->logical_device->vo_handle, renderer->vo_image_available_semaphore, VULKAN_ALLOCATION_CALLBACKS(renderer)); - vkDestroySemaphore(renderer->logical_device->vo_handle, renderer->vo_render_finished_semaphore, VULKAN_ALLOCATION_CALLBACKS(renderer)); + vkDestroyCommandPool(renderer->logical_device->vo_handle, renderer->vo_command_pool, VULKAN_ALLOCATION_CALLBACKS(renderer)); // destroy fences vkDestroyFence(renderer->logical_device->vo_handle, renderer->vo_fence, VULKAN_ALLOCATION_CALLBACKS(renderer)); - vkDestroyDescriptorPool(renderer->logical_device->vo_handle, renderer->vo_descriptor_pool, VULKAN_ALLOCATION_CALLBACKS(renderer)); - - vkFreeCommandBuffers(renderer->logical_device->vo_handle, renderer->vo_command_pool, 1, &renderer->vo_aux_command_buffer); - vkFreeCommandBuffers(renderer->logical_device->vo_handle, renderer->vo_command_pool, renderer->swapchain->image_count, renderer->vo_command_buffers); - vkDestroyCommandPool(renderer->logical_device->vo_handle, renderer->vo_command_pool, VULKAN_ALLOCATION_CALLBACKS(renderer)); + // destroy semaphores + vkDestroySemaphore(renderer->logical_device->vo_handle, renderer->vo_image_available_semaphore, VULKAN_ALLOCATION_CALLBACKS(renderer)); + vkDestroySemaphore(renderer->logical_device->vo_handle, renderer->vo_render_finished_semaphore, VULKAN_ALLOCATION_CALLBACKS(renderer)); // destroy logical device vulkan_logical_device_destroy(renderer->logical_device); vulkan_logical_device_release_resources(renderer->logical_device); + // NOTE: VkSurfaceKHR must be destroyed after the swapchain + vkDestroySurfaceKHR(renderer->instance->handle, renderer->vo_surface, VULKAN_ALLOCATION_CALLBACKS(renderer)); + render_window_destroy(renderer->window); + // destroy instance vulkan_instance_destroy(renderer->instance); vulkan_instance_release_resources(renderer->instance); vulkan_allocator_destroy(renderer->vk_allocator); - - memory_allocator_dealloc(renderer->allocator, renderer->vo_command_buffers); - memory_allocator_dealloc(renderer->allocator, renderer); LOG_MSG("Renderer exited successfully\n"); } @@ -644,3 +713,19 @@ static void recreate_swapchain(void* _window, void* _renderer) vulkan_swapchain_refresh(renderer->swapchain, &renderer->swapchain_create_info); debug_log_info("Swapchain recreate success"); } + +static void update_screen_info(void* _window, void* _renderer) +{ + AUTO window = CAST_TO(render_window_t*, _window); + vulkan_renderer_t* renderer = _renderer; + + /* set the window size value */ + AUTO size = iextent2d(window->width, window->height); + struct_descriptor_set_uvec2(&renderer->screen_info.struct_def, renderer->screen_info.size_field, CAST_TO(uint*, &size)); + + /* set the screen matrix */ + AUTO matrix = mat4_ortho_projection(-0.04f, 100, size.height, (f32)size.width / (f32)size.height); + mat4_move(matrix, mat4_transpose(matrix)); + struct_descriptor_set_mat4(&renderer->screen_info.struct_def, renderer->screen_info.matrix_field, CAST_TO(f32*, &matrix)); +} + diff --git a/source/renderer/vulkan/vulkan_shader_module.c b/source/renderer/vulkan/vulkan_shader_module.c index f6df5fdb..512dea2e 100644 --- a/source/renderer/vulkan/vulkan_shader_module.c +++ b/source/renderer/vulkan/vulkan_shader_module.c @@ -41,6 +41,7 @@ RENDERER_API vulkan_shader_module_t* vulkan_shader_module_new(memory_allocator_t { vulkan_shader_module_t* shader = memory_allocator_alloc_obj(allocator, MEMORY_ALLOCATION_TYPE_OBJ_VK_SHADER_MODULE, vulkan_shader_module_t); memzero(shader, vulkan_shader_module_t); + VULKAN_OBJECT_INIT(shader, VULKAN_OBJECT_TYPE_SHADER_MODULE, VULKAN_OBJECT_NATIONALITY_INTERNAL); return shader; } @@ -53,7 +54,7 @@ RENDERER_API vulkan_shader_module_t* vulkan_shader_module_create(vulkan_renderer RENDERER_API void vulkan_shader_module_create_no_alloc(vulkan_renderer_t* renderer, vulkan_shader_module_create_info_t* create_info, vulkan_shader_module_t* shader) { - memzero(shader, vulkan_shader_module_t); + VULKAN_OBJECT_MEMZERO(shader, vulkan_shader_module_t); shader->renderer = renderer; shader->vo_module = get_shader_module(renderer, create_info->spirv, create_info->length); @@ -62,6 +63,8 @@ RENDERER_API void vulkan_shader_module_create_no_alloc(vulkan_renderer_t* render RENDERER_API void vulkan_shader_module_load_no_alloc(vulkan_renderer_t* renderer, vulkan_shader_module_load_info_t* load_info, vulkan_shader_module_t OUT shader) { + VULKAN_OBJECT_MEMZERO(shader, vulkan_shader_module_t); + shader->renderer = renderer; BUFFER* shader_bytes = load_binary_from_file(load_info->file_path); shader->vo_module = get_shader_module(renderer, shader_bytes->bytes, shader_bytes->element_count); shader->vo_stage = get_pipeline_shader_stage_create_info(shader->vo_module, load_info->type, "main"); @@ -82,7 +85,8 @@ RENDERER_API void vulkan_shader_module_destroy(vulkan_shader_module_t* shader) RENDERER_API void vulkan_shader_module_release_resources(vulkan_shader_module_t* shader) { - memory_allocator_dealloc(shader->renderer->allocator, shader); + if(VULKAN_OBJECT_IS_INTERNAL(shader)) + memory_allocator_dealloc(shader->renderer->allocator, shader); } static VkShaderModule get_shader_module(vulkan_renderer_t* renderer, void* spirv, u32 length) diff --git a/source/renderer/vulkan/vulkan_text_mesh.c b/source/renderer/vulkan/vulkan_text_mesh.c index f71df9ff..c88929ce 100644 --- a/source/renderer/vulkan/vulkan_text_mesh.c +++ b/source/renderer/vulkan/vulkan_text_mesh.c @@ -115,6 +115,7 @@ RENDERER_API void vulkan_text_mesh_create_no_alloc(vulkan_renderer_t* renderer, /* this buffer will be indexed with glyph_render_data_t.stid */ .vo_usage_flags = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT }; + VULKAN_OBJECT_INIT(&text->text_string_transform_buffer, VULKAN_OBJECT_TYPE_HOST_BUFFERED_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_host_buffered_buffer_create_no_alloc(renderer, &buffer_create_info, &text->text_string_transform_buffer); } @@ -142,6 +143,7 @@ RENDERER_API void vulkan_text_mesh_release_resources(vulkan_text_mesh_t* text_me dictionary_free(&((vulkan_text_mesh_string_t*)buf_get_ptr_at(strings, i))->glyph_sub_buffer_handles); buf_free(strings); dictionary_free(glyph_render_data_buffers); + vulkan_host_buffered_buffer_release_resources(&text_mesh->text_string_transform_buffer); memory_allocator_dealloc(text_mesh->renderer->allocator, text_mesh); } @@ -587,6 +589,7 @@ static vulkan_instance_buffer_t* get_instance_buffer(vulkan_renderer_t* renderer .stride = INSTANCE_BUFFER_STRIDE, .capacity = 10, }; + VULKAN_OBJECT_INIT(&buffer, VULKAN_OBJECT_TYPE_INSTANCE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_instance_buffer_create(renderer, &create_info, &buffer); dictionary_add(buffers, &key, &buffer); index = dictionary_get_count(buffers) - 1; diff --git a/source/renderer/vulkan/vulkan_texture.c b/source/renderer/vulkan/vulkan_texture.c index ce6634f0..be42a933 100644 --- a/source/renderer/vulkan/vulkan_texture.c +++ b/source/renderer/vulkan/vulkan_texture.c @@ -654,6 +654,7 @@ RENDERER_API void vulkan_texture_upload_data(vulkan_texture_t* texture, u32 data .vo_sharing_mode = texture->renderer->vo_sharing_mode, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(&staging_buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(texture->renderer, &create_info, &staging_buffer); for(u32 i = 0; i < data_count; i++) @@ -662,6 +663,7 @@ RENDERER_API void vulkan_texture_upload_data(vulkan_texture_t* texture, u32 data vulkan_image_view_copy_from_buffer(&texture->image_view, &staging_buffer); vulkan_buffer_destroy(&staging_buffer); + vulkan_buffer_release_resources(&staging_buffer); } else { @@ -682,11 +684,13 @@ RENDERER_API void vulkan_texture_upload_data(vulkan_texture_t* texture, u32 data .vo_sharing_mode = texture->renderer->vo_sharing_mode, .vo_memory_property_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT }; + VULKAN_OBJECT_INIT(&staging_buffer, VULKAN_OBJECT_TYPE_BUFFER, VULKAN_OBJECT_NATIONALITY_EXTERNAL); vulkan_buffer_create_no_alloc(texture->renderer, &create_info, &staging_buffer); vulkan_image_view_copy_from_buffer(&texture->image_view, &staging_buffer); vulkan_buffer_destroy(&staging_buffer); + vulkan_buffer_release_resources(&staging_buffer); } break; default: