/** * @file graphics_context.h * @author Piotr Krygier (piotrkrygier@everyonencancode.xyz) * @brief Graphics context for Red Scarf Engine * @version 0.1 * @date 2024-05-22 * * @copyright Copyright (c) 2024 * */ #ifndef GRAPHICS_CONTEXT_H #define GRAPHICS_CONTEXT_H #include #include #include #include #include #include #include "utilities/entity.h" #include "utilities/vector.h" #include "vma/vk_mem_alloc.h" #include "vulkan/vulkan_core.h" #include "vulkan_commons.h" #define MAX_MESH_NUMBER 256U /* FIXME: This is the total number of instances * meshes. It shouldn't be so low */ #define MAX_INSTANCE_NUMBER (MAX_MESH_NUMBER * 256U) #define SWAPCHAIN_IMAGE_COUNT (3U) /** * @brief Maximum number of textures that can be loaded * */ #define RSE_MAX_IMAGE_COUNT 256 #define MAX_VULKAN_BUFFERS_COUNT (32U) #define MAX_PIPELINE_COUNT 16 #define MAX_CREATE_INFOS (32U) #define MAX_SHADER_STAGES 12U #define MAX_SHADER_MODULES_COUNT (128U) #define MAX_VERTEX_BINDINGS_COUNT (32U) #define MAX_SHADER_ATTRIBUTES_COUNT (32U) #define MAX_DYNAMIC_STATES_COUNT (32U) #define DESCRIPTOR_MAX_SETS (32U) #define DESCRIPTOR_TYPE_ID_MAX_ENUM (21U) #define RENDERER_MAX_COUNT MAX_PIPELINE_COUNT #define FONT_CHARACTERS_COUNT (94U) #define FONTS_MAX_COUNT (32U) struct graphics_context_t; enum QUEUE_FAMILY_INDEX { QUEUE_FAMILY_INDEX_GRAPHICS, QUEUE_FAMILY_INDEX_PRESENTATION, QUEUE_FAMILY_INDEX_LAST_INDEX, }; enum RENDER_TARGET { RENDER_TARGET_3D, RENDER_TARGET_2D, RENDER_TARGET_COUNT }; /** * @brief Represents data within vertex or instance buffer. * */ struct buffer_data_t { size_t count; size_t buffer_offset; }; struct vulkan_buffers_t { size_t vulkan_buffers_count; struct vulkan_buffer_t vulkan_buffers[MAX_VULKAN_BUFFERS_COUNT]; }; /** * @brief Wrapper for Vulkan buffer. Holds allocation data; * */ struct vulkan_image_t { uint8_t id_taken; size_t allocated_size; VkImage image; VkImageView image_view; VmaAllocation allocation; VmaAllocationInfo allocation_info; }; RSE_VECTOR_DEFINE(instance_vector_t, struct instance_data_t); /** * @brief Mesh data, with unique id and dynamic arrays holding vertices and indices. * One mesh can have multiple instances. * */ struct mesh_t { size_t vertex_count; bool is_dirty; size_t entities_count; entity_t* entities; /* Which entities are connected to this mesh */ size_t index_count; size_t instances_count; struct instance_vector_t instances_data; }; struct shader_modules_t { uint16_t shader_modules_count; VkShaderModule shader_modules[MAX_SHADER_MODULES_COUNT]; VkShaderStageFlagBits shaders_stages[MAX_SHADER_MODULES_COUNT]; }; struct required_dynamic_states_t { size_t dynamic_states_count; VkDynamicState dynamic_states[MAX_DYNAMIC_STATES_COUNT]; }; struct pipeline_infos_t { size_t pipeline_create_infos_count; VkGraphicsPipelineCreateInfo create_infos[MAX_CREATE_INFOS]; }; struct pipeline_t { VkPipeline pipeline; uint8_t id; /* Shader stages */ size_t shader_stages_count; VkPipelineShaderStageCreateInfo shader_stages[MAX_SHADER_STAGES]; /* Input assembly */ VkPipelineInputAssemblyStateCreateInfo input_assembly; /* Viewport state */ VkPipelineViewportStateCreateInfo viewport_state; /* Rasterizer */ VkPipelineRasterizationStateCreateInfo rasterizer; /* Multisampling */ VkPipelineMultisampleStateCreateInfo multisampling; /* Color blending */ VkPipelineColorBlendAttachmentState color_blend_attachment; VkPipelineColorBlendStateCreateInfo color_blending; /* Depth stencil */ VkPipelineDepthStencilStateCreateInfo depth_stencil; VkPipelineLayout pipeline_layout; size_t vertex_bindings_count; VkVertexInputBindingDescription vertex_bindings[MAX_VERTEX_BINDINGS_COUNT]; size_t shader_attributes_count; VkVertexInputAttributeDescription shader_attributes[MAX_SHADER_ATTRIBUTES_COUNT]; size_t dynamic_states_count; VkDynamicState dynamic_states[MAX_DYNAMIC_STATES_COUNT]; struct required_dynamic_states_t required_dynamic_states; struct descriptor_set_handle_t* descriptor_sets; }; struct pipeline_internal_t { rse_id_t descriptor_set_ids[MAX_PIPELINE_COUNT]; size_t pipelines_count; size_t pipeline_layouts_count; VkPipeline pipelines[MAX_PIPELINE_COUNT]; VkPipelineLayout pipeline_layouts[MAX_PIPELINE_COUNT]; }; struct descriptor_data_t { uint32_t pool_sizes_count; uint32_t descriptor_sets_count; VkDescriptorPool descriptor_pool; VkDescriptorPoolSize pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM]; VkDescriptorSet descriptor_sets[DESCRIPTOR_MAX_SETS]; VkDescriptorSetLayout set_layouts[DESCRIPTOR_MAX_SETS]; }; struct descriptor_set_layout_bindings_t { VkDescriptorSetLayoutBinding layout_bindings[DESCRIPTOR_MAX_SETS]; uint32_t layout_bindings_count; }; struct render_target_t { struct vulkan_buffer_t vertex_buffer; struct vulkan_buffer_t index_buffer; size_t instances_data_size; struct vulkan_buffer_t instance_buffer; struct vulkan_buffer_t draw_indirect_command_buffer; }; struct swapchain_data_t { VkSwapchainKHR swapchain; VkImageView swapchain_image_views[SWAPCHAIN_IMAGE_COUNT]; VkExtent2D swapchain_extent; VkFramebuffer swapchain_framebuffers[SWAPCHAIN_IMAGE_COUNT]; VkImage swapchain_images[SWAPCHAIN_IMAGE_COUNT]; }; struct vulkan_handles { VkSampler sampler; VkPhysicalDevice physical_device; VkDevice device; VmaAllocator allocator; VkSurfaceKHR surface; VkInstance instance; VkQueue graphics_queue; VkQueue present_queue; VkCommandPool command_pool; VkCommandBuffer command_buffers[SWAP_BUFFER_COUNT]; VkRenderPass render_pass; VkSemaphore image_available_semaphores[SWAP_BUFFER_COUNT]; VkSemaphore render_finished_semaphores[SWAP_BUFFER_COUNT]; VkFence in_flight_fences[SWAP_BUFFER_COUNT]; #ifndef NDEBUG VkDebugUtilsMessengerEXT debug_messenger; #endif // !NDEBUG }; struct mesh_data_t { uint32_t mesh_count; struct mesh_t mesh_bucket[MAX_MESH_NUMBER]; }; struct debug_overlay_t { rse_id_t texture_id; uint32_t* pixels; size_t pixels_size; struct vulkan_image_t image_handle; VkSampler sampler; }; typedef rse_err_t(*renderer_function_t)(struct graphics_context_t* context, rse_id_t renderer_id); struct renderer_t { renderer_function_t render_function; }; struct renderer_data_t { size_t renderers_count; struct renderer_t renderers[RENDERER_MAX_COUNT]; }; struct font_character_data_t { rse_id_t mesh_id; rse_id_t texture_id; }; struct sized_font_data_t { uint8_t font_size; struct font_character_data_t font_characters[FONT_CHARACTERS_COUNT]; }; struct fonts_data_t { struct sized_font_data_t fonts[FONTS_MAX_COUNT]; }; struct graphics_context_t { bool is_framebuffer_resized; uint32_t queue_family_indices[QUEUE_FAMILY_INDEX_LAST_INDEX]; uint32_t current_frame; uint32_t swapchain_images_count; SDL_Window* window_handle; struct renderer_data_t renderer_data; struct debug_overlay_t debug_overlay; struct vulkan_handles vulkan_handles; struct swapchain_data_t swapchain_data; struct descriptor_data_t descriptor_data; struct pipeline_internal_t pipelines_data; struct render_target_t render_targets[RENDER_TARGET_COUNT]; struct vulkan_buffers_t uniform_buffers; struct vulkan_image_t texture_images[RSE_MAX_IMAGE_COUNT]; struct vulkan_image_t depth_image; struct vulkan_image_t color_image; struct shader_modules_t shader_modules; struct mesh_data_t mesh_data; struct fonts_data_t fonts_data; }; #endif /* GRAPHICS_CONTEXT_H */