#ifndef LRHI_H #define LRHI_H #include #include #include #include #include #define LRHI_LOG(...) \ do { \ fprintf(stderr, "[LRHI %s:%d] ", __FILE__, __LINE__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ } while (0) #define LRHI_LOG_ERR(...) LRHI_LOG("ERR: " __VA_ARGS__) #define ARRAY_LENGTH(arr) (sizeof(arr) / sizeof((arr)[0])) #define LRHI_PANIC(...) \ do { \ LRHI_LOG("Panic: " __VA_ARGS__); \ exit(1); \ } while (0) #define LRHI_KB 1024 #define LRHI_MB (1024 * LRHI_KB) #define LRHI_GB (1024 * LRHI_MB) struct lrhi_allocator { void *(*allocate)(ptrdiff_t size, void *ctx); void (*free)(void *ptr, ptrdiff_t size, void *ctx); void *ctx; }; void *lrhi_allocator_allocate(struct lrhi_allocator *allocator, ptrdiff_t size); void lrhi_allocator_free(struct lrhi_allocator *allocator, ptrdiff_t size, void *ptr); typedef struct lrhi_arena lrhi_arena; lrhi_arena *lrhi_arena_create(struct lrhi_allocator *allocator, ptrdiff_t arena_size); void lrhi_arena_destroy(struct lrhi_allocator *allocator, lrhi_arena *arena); void *lrhi_arena_allocate(lrhi_arena *arena, ptrdiff_t size); void lrhi_arena_reset(lrhi_arena *arena); struct lrhi_allocator lrhi_arena_allocator(lrhi_arena *arena); struct lrhi_instance_desc { bool enable_validation_layers; }; struct lrhi_instance; typedef struct lrhi_instance lrhi_instance; struct lrhi_surface_configuration { uint32_t width; uint32_t height; }; struct lrhi_surface; typedef struct lrhi_surface lrhi_surface; struct lrhi_device; typedef struct lrhi_device lrhi_device; struct lrhi_shader_module_desc { const char *label; const unsigned char *spirv_source; size_t spirv_source_size; }; struct lrhi_shader_module; typedef struct lrhi_shader_module lrhi_shader_module; struct lrhi_pipeline_layout; typedef struct lrhi_pipeline_layout lrhi_pipeline_layout; struct lrhi_render_pass; typedef struct lrhi_render_pass lrhi_render_pass; struct lrhi_descriptor_set_layout; typedef struct lrhi_descriptor_set_layout lrhi_descriptor_set_layout; enum lrhi_descriptor_type { lrhi_DESCRIPTOR_TYPE_UNIFORM_BUFFER, lrhi_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, }; typedef uint32_t lrhi_shader_stages; #define lrhi_SHADER_STAGE_VERTEX (1 << 0) #define lrhi_SHADER_STAGE_FRAGMENT (1 << 0) struct lrhi_descriptor_set_layout_binding { uint32_t binding; enum lrhi_descriptor_type descriptor_type; uint32_t descriptor_count; lrhi_shader_stages visibility; }; struct lrhi_descriptor_set_layout_desc { uint32_t binding_count; const struct lrhi_descriptor_set_layout_binding *bindings; }; struct lrhi_pipeline_layout_desc { uint32_t set_layout_count; lrhi_descriptor_set_layout *set_layouts; }; enum lrhi_vertex_input_rate { lrhi_VERTEX_INPUT_RATE_VERTEX, lrhi_VERTEX_INPUT_RATE_INSTANCE, }; struct lrhi_vertex_input_binding_desc { uint32_t binding; uint32_t stride; enum lrhi_vertex_input_rate input_rate; }; enum lrhi_format { lrhi_FORMAT_B8G8R8A8_SRGB, lrhi_FORMAT_R8G8B8A8_SRGB, lrhi_FORMAT_R32G32_SFLOAT, lrhi_FORMAT_R32G32B32_SFLOAT, lrhi_FORMAT_D32_SFLOAT }; struct lrhi_vertex_input_attribute_desc { uint32_t binding; uint32_t location; enum lrhi_format format; uint32_t offset; }; struct lrhi_vertex_input { const struct lrhi_vertex_input_binding_desc *bindings; const struct lrhi_vertex_input_attribute_desc *attributes; int binding_count; int attribute_count; }; enum lrhi_compare_function { lrhi_COMPARE_FUNCTION_NEVER, lrhi_COMPARE_FUNCTION_LESS, lrhi_COMPARE_FUNCTION_EQUAL, lrhi_COMPARE_FUNCTION_LESS_EQUAL, lrhi_COMPARE_FUNCTION_GREATER, lrhi_COMPARE_FUNCTION_NOT_EQUAL, lrhi_COMPARE_FUNCTION_GREATER_EQUAL, lrhi_COMPARE_FUNCTION_ALWAYS }; struct lrhi_pipeline_depth_stencil_state_desc { bool depth_write_enabled; enum lrhi_compare_function compare_function; }; struct lrhi_pipeline_desc { const struct lrhi_vertex_input *vertex_input; const struct lrhi_pipeline_depth_stencil_state_desc *depth_stencil; const lrhi_shader_module *vertex_module; const lrhi_shader_module *fragment_module; const lrhi_pipeline_layout *layout; const lrhi_render_pass *pass; }; struct lrhi_pipeline; typedef struct lrhi_pipeline lrhi_pipeline; struct lrhi_command_buffer; typedef struct lrhi_command_buffer lrhi_command_buffer; struct lrhi_clear_color { float r; float g; float b; float a; }; struct lrhi_texture_view; typedef struct lrhi_texture_view lrhi_texture_view; struct lrhi_render_pass_color_attachment { lrhi_texture_view *view; }; struct lrhi_render_pass_depth_stencil_attachment { lrhi_texture_view *view; }; struct lrhi_render_pass_begin_desc { struct lrhi_clear_color clear_color; lrhi_render_pass *pass; const struct lrhi_render_pass_color_attachment *color_attachments; uint32_t color_attachment_count; const struct lrhi_render_pass_depth_stencil_attachment *depth_stencil_attachment; lrhi_surface *surface; }; struct lrhi_viewport { float x; float y; float width; float height; float min_depth; float max_depth; }; struct lrhi_scissor { float x_offset; float y_offset; float width; float height; }; struct lrhi_buffer; typedef struct lrhi_buffer lrhi_buffer; typedef uint32_t lrhi_buffer_usage; #define lrhi_BUFFER_USAGE_VERTEX (1 << 0) #define lrhi_BUFFER_USAGE_INDEX (1 << 1) #define lrhi_BUFFER_USAGE_TRANSFER (1 << 2) #define lrhi_BUFFER_USAGE_UNIFORM (1 << 3) struct lrhi_buffer_desc { uint32_t size; lrhi_buffer_usage usage; }; struct lrhi_texture; typedef struct lrhi_texture lrhi_texture; typedef uint32_t lrhi_texture_usage; #define lrhi_TEXTURE_USAGE_COPY_SRC (1 << 0) #define lrhi_TEXTURE_USAGE_COPY_DST (1 << 1) #define lrhi_TEXTURE_USAGE_TEXTURE_BINDING (1 << 2) #define lrhi_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT (1 << 3) struct lrhi_texture_desc { uint32_t width; uint32_t height; uint32_t mip_level_count; uint32_t sample_count; enum lrhi_format format; lrhi_texture_usage usage; }; struct lrhi_texel_copy_buffer_layout { uint64_t offset; uint32_t bytes_per_row; uint32_t rows_per_image; }; struct lrhi_texel_copy_buffer_desc { lrhi_buffer *buffer; const struct lrhi_texel_copy_buffer_layout *layout; }; struct lrhi_texel_copy_texture_desc { lrhi_texture *texture; uint32_t mip_level; }; typedef uint32_t lrhi_image_aspect; #define lrhi_IMAGE_ASPECT_COLOR (1 << 0) #define lrhi_IMAGE_ASPECT_DEPTH (1 << 1) struct lrhi_texture_view_desc { lrhi_texture *texture; enum lrhi_format format; lrhi_image_aspect aspect; }; struct lrhi_sampler; typedef struct lrhi_sampler lrhi_sampler; enum lrhi_filter { lrhi_FILTER_NEAREST, lrhi_FILTER_LINEAR, }; enum lrhi_sampler_address_mode { lrhi_SAMPLER_ADDRESS_MODE_REPEAT, lrhi_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, lrhi_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, lrhi_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, }; struct lrhi_sampler_desc { enum lrhi_filter mag_filter; enum lrhi_filter min_filter; enum lrhi_sampler_address_mode address_mode_u; enum lrhi_sampler_address_mode address_mode_v; }; struct lrhi_descriptor_buffer_info { lrhi_buffer *buffer; uint32_t offset; uint64_t range; }; struct lrhi_descriptor_texture_info { lrhi_texture_view *view; lrhi_sampler *sampler; }; struct lrhi_descriptor_set_entry { uint32_t binding; uint32_t array_element; enum lrhi_descriptor_type descriptor_type; const struct lrhi_descriptor_buffer_info *buffer_info; const struct lrhi_descriptor_texture_info *texture_info; }; struct lrhi_descriptor_set_desc { lrhi_descriptor_set_layout *layout; const struct lrhi_descriptor_set_entry *entries; uint32_t entry_count; }; struct lrhi_descriptor_set; typedef struct lrhi_descriptor_set lrhi_descriptor_set; struct lrhi_buffer_init_desc { unsigned char *content; uint32_t size; lrhi_buffer_usage usage; }; struct lrhi_buffer_copy_region { uint64_t src_offset; uint64_t dst_offset; uint64_t size; }; struct lrhi_buffer_copy { lrhi_buffer *src; lrhi_buffer *dst; uint32_t region_count; const struct lrhi_buffer_copy_region *regions; }; enum lrhi_attachment_load_op { lrhi_ATTACHMENT_LOAD_OP_LOAD, lrhi_ATTACHMENT_LOAD_OP_CLEAR, lrhi_ATTACHMENT_LOAD_OP_DONT_CARE }; enum lrhi_attachment_store_op { lrhi_ATTACHMENT_STORE_OP_STORE, lrhi_ATTACHMENT_STORE_OP_DONT_CARE }; struct lrhi_attachment_desc { enum lrhi_format format; uint32_t sample_count; enum lrhi_attachment_load_op load_op; enum lrhi_attachment_store_op store_op; }; struct lrhi_render_pass_desc { uint32_t color_attachment_count; const struct lrhi_attachment_desc *color_attachments; const struct lrhi_attachment_desc *depth_stencil_attachment; }; typedef void (*lrhi_surface_reconfigured_callback)(int32_t width, int32_t height, void *user_data); enum lrhi_window_backend { LRHI_WINDOW_BACKEND_X11, }; struct lrhi_native_surface { enum lrhi_window_backend backend; void *window_hnd; void *display_hnd; }; /** * Creates a new instance. * * \param allocator The allocator to use for creating the instance. * \param window_backend The window backend that will be used. * \param desc The instance configuration. * \returns The created instance on success, NULL on failure. */ lrhi_instance *lrhi_instance_create(struct lrhi_allocator *allocator, enum lrhi_window_backend window_backend, const struct lrhi_instance_desc *desc); /** * Destroys the instance. * * \param allocator The allocator used to allocate the instance. * \param instance The instance to destroy. */ void lrhi_instance_destroy(struct lrhi_allocator *allocator, lrhi_instance *instance); /** * Creates a logical device connected to a physical device. * * \param instance The instance to use to fetch the physical device. * \param surface The surface to use. * \returns The created device on success, NULL on failure. */ lrhi_device *lrhi_instance_create_device(lrhi_instance *instance, lrhi_surface *surface); /** * Destroys a logical device. * * \param instance The instance used to create the device. * \param device The device to destroy. */ void lrhi_instance_destroy_device(lrhi_instance *instance, lrhi_device *device); /** * Creates a buffer. * * \param device The logical device used to create the buffer. * \param desc The buffer description. * \returns The created buffer on success, NULL on failure. */ lrhi_buffer *lrhi_device_create_buffer(lrhi_device *device, const struct lrhi_buffer_desc *desc); /** * Creates a buffer with initial data. * * \param device The logical device used to create the buffer. * \param desc The buffer description. * \returns The created buffer on success, NULL on failure. */ lrhi_buffer * lrhi_device_create_buffer_init(lrhi_device *device, const struct lrhi_buffer_init_desc *desc); /** * Destroys a buffer. * * \param device The logical device used to create the buffer. * \param buffer The buffer to destroy. */ void lrhi_device_destroy_buffer(lrhi_device *device, lrhi_buffer *buffer); /** * Maps a buffer. * * \param device The logical device to use. * \param buffer The buffer to map. * \returns The mapped buffer on success, NULL on failure. */ void *lrhi_device_map_buffer(lrhi_device *device, lrhi_buffer *buffer); /** * Unmaps a buffer. * * \param device The logical device to use. * \param buffer The buffer to unmap. */ void lrhi_device_unmap_buffer(lrhi_device *device, lrhi_buffer *buffer); /** * Returns the allocated size of a buffer. * * \returns The allocated size of the buffer in bytes. */ uint32_t lrhi_buffer_size(lrhi_buffer *buffer); /** * Creates a texture. * * \param device The logical device used to create the texture. * \param desc The texture description. * \returns The created texture on success, NULL on failure. */ lrhi_texture *lrhi_device_create_texture(lrhi_device *device, const struct lrhi_texture_desc *desc); /** * Destroys a texture. * * \param device The logical device used to create the texture. * \param texture The texture to destroy. */ void lrhi_device_destroy_texture(lrhi_device *device, lrhi_texture *texture); /** * Writes data into a texture. * * \param device The logical device to use. * \param texture The target texture. * \param data The data to write. * \param data_size The size of the data to write in bytes. * \param layout Layout of the texutre in a buffer's memory. * \param width The width of the texture. * \param heightThe height of the texture. */ void lrhi_device_write_texture( lrhi_device *device, const struct lrhi_texel_copy_texture_desc *texture, unsigned char *data, size_t data_size, const struct lrhi_texel_copy_buffer_layout *layout, uint32_t width, uint32_t height); /** * Creates a texture view. * * \param device The logical device used to create the texture view. * \param desc The texture view description. * \returns The created texture view on success, NULL on failure. */ lrhi_texture_view * lrhi_device_create_texture_view(lrhi_device *device, const struct lrhi_texture_view_desc *desc); /** * Destroys a texture view. * * \param device The logical device used to create the texture view. * \param texture_view The texture view to destroy. */ void lrhi_device_destroy_texture_view(lrhi_device *device, lrhi_texture_view *texture_view); /** * Creates a sampler. * * \param device The logical device used to create the sampler. * \param desc The sampler description. * \returns The created sampler on success, NULL on failure. */ lrhi_sampler *lrhi_device_create_sampler(lrhi_device *device, const struct lrhi_sampler_desc *desc); /** * Destroys a sampler. * * \param device The logical device used to create the sampler. * \param sampler The sampler to destroy. */ void lrhi_device_destroy_sampler(lrhi_device *device, lrhi_sampler *sampler); /** * Creates a shader module. * * \param device The logical device used to create the shader module. * \param desc The shader module description. * \returns The created shader module on success, NULL on failure. */ lrhi_shader_module * lrhi_device_create_shader_module(lrhi_device *device, const struct lrhi_shader_module_desc *desc); /** * Destroys a shader module. * * \param device The logical device used to create the shader module. * \param module The shader module to destroy. */ void lrhi_device_destroy_shader_module(lrhi_device *device, lrhi_shader_module *module); /** * Wait for the device to become idle * * \param device The logical device to idle. */ void lrhi_device_wait_idle(lrhi_device *device); /** * Creates a descriptor set layout. * * \param device The logical device used to create the descriptor set layout. * \param desc The descriptor set layout description. * \returns The created descriptor set layout on success, NULL on failure. */ lrhi_descriptor_set_layout *lrhi_device_create_descriptor_set_layout( lrhi_device *device, const struct lrhi_descriptor_set_layout_desc *desc); /** * Destroys a descriptor set layout. * * \param device The logical device used to create the descriptor set layout. * \param layout The descriptor set layout to destroy. */ void lrhi_device_destroy_descriptor_set_layout( lrhi_device *device, lrhi_descriptor_set_layout *layout); /** * Creates a descriptor set. * * \param device The logical device used to create the descriptor set. * \param desc The descriptor set description. * \returns The created descriptor set on success, NULL on failure. */ lrhi_descriptor_set * lrhi_device_create_descriptor_set(lrhi_device *device, const struct lrhi_descriptor_set_desc *desc); /** * Creates a pipeline layout. * * \param device The logical device used to create the pipeline layout. * \param desc The pipeline layout description. * \returns The created pipeline layout on success, NULL on failure. */ lrhi_pipeline_layout *lrhi_device_create_pipeline_layout( lrhi_device *device, const struct lrhi_pipeline_layout_desc *desc); /** * Destroys a pipeline layout. * * \param device The logical device used to create the pipeline layout. * \param layout The pipeline layout to destroy. */ void lrhi_device_destroy_pipeline_layout(lrhi_device *device, lrhi_pipeline_layout *layout); /** * Creates a render pass. * * \param device The logical device used to create the render pass. * \param desc The render pass description. * \returns The created render pass on success, NULL on failure. */ lrhi_render_pass * lrhi_device_create_render_pass(lrhi_device *device, const struct lrhi_render_pass_desc *desc); /** * Destroys a render pass. * * \param device The logical device used to create the render pass. * \param pass The render pass to destroy. */ void lrhi_device_destroy_render_pass(lrhi_device *device, lrhi_render_pass *pass); /** * Creates a pipeline. * * \param device The logical device used to create the pipeline. * \param desc The pipeline description. * \returns The created pipeline on success, NULL on failure. */ lrhi_pipeline * lrhi_device_create_pipeline(lrhi_device *device, const struct lrhi_pipeline_desc *desc); /** * Destroys a pipeline. * * \param device The logical device used to create the pipeline. * \param pipeline The pipeline to destroy. */ void lrhi_device_destroy_pipeline(lrhi_device *device, lrhi_pipeline *pipeline); /** * Begins recording a command buffer. * * \param device The logical device to use. * \returns The recording command buffer. */ lrhi_command_buffer *lrhi_command_buffer_begin(lrhi_device *device); /** * Begins recording a render pass. * * \param buffer The command buffer to use. * \param desc The render pass begin description. */ void lrhi_command_begin_render_pass( lrhi_command_buffer *buffer, const struct lrhi_render_pass_begin_desc *desc); /** * Ends recording a render pass. * * \param buffer The command buffer to use. */ void lrhi_command_end_render_pass(lrhi_command_buffer *buffer); /** * Copies a buffer's data to another buffer. * * \param buffer The command buffer to use. * \param copy The buffer copy description. */ void lrhi_command_copy_buffer_to_buffer(lrhi_command_buffer *buffer, const struct lrhi_buffer_copy *copy); /** * Copies a buffer's data to a texture. * * \param cmdbuf The command buffer to use. * \param buffer The source buffer texel copy description. * \param texture The target texture description. * \param The width of the texture. * \param The height of the texture */ void lrhi_command_copy_buffer_to_texture( lrhi_command_buffer *cmdbuf, const struct lrhi_texel_copy_buffer_desc *buffer, const struct lrhi_texel_copy_texture_desc *texture, uint32_t width, uint32_t height); /** * Binds a pipeline. * * \param buffer The command buffer to use. * \param pipeline The pipeline to bind. */ void lrhi_command_bind_pipeline(lrhi_command_buffer *buffer, lrhi_pipeline *pipeline); /** * Binds vertex buffers. * * \param buffer The command buffer to use. * \param first_binding The index of the first vertex input binding. * \param binding_count The number of vertex input bindings. * \param buffers The buffers to bind. * \params offsets The buffer offsets. */ void lrhi_command_bind_vertex_buffers(lrhi_command_buffer *buffer, uint32_t first_binding, uint32_t binding_count, lrhi_buffer **buffers, uint64_t *offsets); /** * Binds an index buffer. * * \param cmdbuf The command buffer to use. * \param index_buffer The index buffer to bind. * \param offset The index buffer offset. */ void lrhi_command_bind_index_buffer(lrhi_command_buffer *cmdbuf, lrhi_buffer *index_buffer, uint64_t offset); /** * Binds descriptor sets. * * \param cmdbuf The command buffer to use. * \param pipeline_layout The pipeline layout to use. * \param first_set The index of the first set to be bound. * \param descriptor_set_count The number of descriptor sets to bind. * \param sets The descriptor sets to bind. * \param dynamic_offset_count The number of dynamic offsets. * \param dynamic_offsets The dynamic offsets. */ void lrhi_command_bind_descriptor_set(lrhi_command_buffer *cmdbuf, lrhi_pipeline_layout *pipeline_layout, uint32_t first_set, uint32_t descriptor_set_count, const lrhi_descriptor_set *sets, uint32_t dynamic_offset_count, const uint32_t *dynamic_offsets); /** * Sets the viewport. * * \param buffer The command buffer to use. * \param viewport The viewport to use. */ void lrhi_command_set_viewport(lrhi_command_buffer *buffer, const struct lrhi_viewport *viewport); /** * Sets the scissor. * * \param buffer The command buffer to use. * \param scissor The scissor to use. */ void lrhi_command_set_scissor(lrhi_command_buffer *buffer, const struct lrhi_scissor *scissor); /** * Draws primitives. * * \param buffer The command buffer to use. * \param vertex_count The number of vertices to draw. * \param instance_count The number of instances to draw. * \param first_vertex Index of the first vertex to draw. * \param first_instance Index of the first instance to draw. */ void lrhi_command_draw(lrhi_command_buffer *buffer, uint32_t vertex_count, uint32_t instance_count, uint32_t first_vertex, uint32_t first_instance); /** * Draws indexed primitives. * * \param buffer The command buffer to use. * \param index_count The number of indices to draw. * \param instance_count The number of instances to draw. * \param first_index Index of the first index to draw. * \param first_vertex Index of the first vertex to draw. * \param first_instance Index of the first instance to draw. */ void lrhi_command_draw_indexed(lrhi_command_buffer *cmdbuf, uint32_t index_count, uint32_t instance_count, uint32_t first_index, uint32_t first_vertex, uint32_t first_instance); /** * Ends recording a command buffer. * * \param buffer The command buffer. * \returns true on success, false on failure. */ bool lrhi_command_buffer_end(lrhi_command_buffer *buffer); /** * Submits a command buffer. * * \param device The logical device to use. * \param buffer The command buffer to submit. * \param surface The surface to use. * \returns true on success, false on failure. */ bool lrhi_device_submit_command_buffer(lrhi_device *device, lrhi_command_buffer *buffer, lrhi_surface *surface); /** * Creates a surface. * * \param instance The instance used to create the surface. * \param platform The platform used to create the surface. * \param surface_reconfigured_callback The callback to use when the surface is * reconfigured. * \param surface_reconfigured_user_data The user data passed to the * surface_reconfigured_callback. * \returns the surface created on success, NULL on failure. */ lrhi_surface *lrhi_instance_create_surface( lrhi_instance *instance, struct lrhi_native_surface *surface, lrhi_surface_reconfigured_callback surface_reconfigured_callback, void *surface_reconfigured_user_data); /** * Destroys a surface. * * \param instance The instance used to create the surface. * \param device The device used with this surface. * \param surface The surface to destroy. */ void lrhi_instance_destroy_surface(lrhi_instance *instance, lrhi_device *device, lrhi_surface *surface); /** * Resizes a surface. * * \param surface The surface to resize. * \param width The requested width for the surface. * \param height The requested height for the surface. */ void lrhi_surface_resize(lrhi_surface *surface, int32_t width, int32_t height); /** * Configures a surface. * * \param surface The surface to configure. * \param device The device to use. * \param configuration The surface configuration. * \return true on success, false on failure. */ bool lrhi_surface_configure( lrhi_surface *surface, lrhi_device *device, const struct lrhi_surface_configuration *configuration); /** * Returns the next swapchain image of a surface. * * \param surface The surface to fetch the next swapchain image from. * \param device The device used with the surface. * \return The next swapchain image's texture view. */ lrhi_texture_view *lrhi_surface_acquire_next_image(lrhi_surface *surface, lrhi_device *device); /** * Presents the surface. * * \param device The device used with the surface. * \param surface The surface to present. * \return true on success, false on failure. */ bool lrhi_surface_present(lrhi_device *device, lrhi_surface *surface); #endif // LRHI_H