#include #include #define RT_DONT_DEFINE_RENDERER_GLOBAL #include "gfx.h" #include "renderer_api.h" #include "runtime/config.h" #include "runtime/dynamic_libs.h" /* Attributes are used to bind buffers (or textures) to symbolic values. * For example, an attribute might be bound to "CELL_GRID", which would be * replaced with the (at the time of the invoke) grid buffer of the current * world cell. */ rt_renderer_api g_renderer; #ifndef RT_STATIC_LIB static rt_dynlib _renderer_lib; #endif static bool _renderer_loaded = false; RT_DLLEXPORT RT_CVAR_S(rt_Renderer, "Select the render backend. Available options: [vk, null], Default: vk", "dx11"); extern rt_cvar rt_RenderViewArenaSize; extern rt_cvar rt_RenderListPoolSize; #ifdef RT_STATIC_LIB extern void RT_RENDERER_API_FN(RegisterCVars)(void); extern rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *); extern void RT_RENDERER_API_FN(Shutdown)(void); extern unsigned int RT_RENDERER_API_FN(GetMaxFramesInFlight)(void); extern void RT_RENDERER_API_FN(BeginFrame)(unsigned int); extern void RT_RENDERER_API_FN(EndFrame)(unsigned int); extern rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *); extern void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle); extern rt_result RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t, const rt_alloc_command_buffer_info *, rt_command_buffer_handle *); extern rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue, const rt_submit_command_buffers_info *); extern rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t, const rt_gpu_semaphore_info *, rt_gpu_semaphore_handle *); extern void RT_RENDERER_API_FN(DestroySemaphores)(uint32_t count, rt_gpu_semaphore_handle *); extern uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle); extern rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetSwapchainAvailableSemaphore)(void); extern rt_gpu_semaphore_handle RT_RENDERER_API_FN(GetRenderFinishedSemaphore)(void); extern rt_result RT_RENDERER_API_FN(CreateBuffers)(uint32_t, const rt_buffer_info *, rt_buffer_handle *); extern void RT_RENDERER_API_FN(DestroyBuffers)(uint32_t, rt_buffer_handle *); extern rt_render_graph_builder RT_RENDERER_API_FN(CreateRenderGraphBuilder)(void); extern void RT_RENDERER_API_FN(DestroyRenderGraphBuilder)(rt_render_graph_builder *); extern rt_result RT_RENDERER_API_FN(ExecuteRenderGraph)(rt_render_graph *); extern void RT_RENDERER_API_FN(SubmitRenderView)(rt_render_graph *render_graph, uint32_t pass_id, rt_render_view view); extern void RT_RENDERER_API_FN(ResetRenderGraph)(rt_render_graph *graph); extern void RT_RENDERER_API_FN(CmdBeginPass)(rt_command_buffer_handle, const rt_cmd_begin_pass_info *); extern void RT_RENDERER_API_FN(CmdEndPass)(rt_command_buffer_handle); extern void RT_RENDERER_API_FN(CmdTransitionRenderTarget)(rt_command_buffer_handle, rt_render_target_handle, rt_render_target_state); extern void RT_RENDERER_API_FN(CmdFlushRenderTargetWrite)(rt_command_buffer_handle, rt_render_target_handle); extern void RT_RENDERER_API_FN(CmdBindPipeline)(rt_command_buffer_handle, rt_pipeline_handle); extern void RT_RENDERER_API_FN(CmdBindVertexBuffers)(rt_command_buffer_handle, uint32_t, uint32_t, const rt_buffer_handle *, const uint64_t *); extern void RT_RENDERER_API_FN(CmdDraw)(rt_command_buffer_handle, uint32_t, uint32_t); #endif extern rt_result InitRenderLists(void); extern void ShutdownRenderLists(void); extern void ResetRenderLists(void); extern rt_result InitRenderViews(void); extern void ShutdownRenderViews(void); extern void ResetRenderViews(void); static bool LoadRenderer(void) { #if !defined(RT_STATIC_LIB) #define RETRIEVE_SYMBOL(name, type) \ g_renderer.name = (type *)rtGetSymbol(_renderer_lib, "rtRen" #name); \ if (!g_renderer.name) { \ rtReportError("GFX", \ "Unable to retrieve renderer function %s from backend %s", \ #name, \ rt_Renderer.s); \ } if (strcmp(rt_Renderer.s, "vk") == 0) { _renderer_lib = rtOpenLib(RT_DLLNAME("rtvk")); if (!_renderer_lib) { rtReportError("GFX", "Unable to load renderer backend: %s", RT_DLLNAME("rtvk")); return false; } RETRIEVE_SYMBOL(RegisterCVars, rt_register_renderer_cvars_fn); RETRIEVE_SYMBOL(Init, rt_init_renderer_fn); RETRIEVE_SYMBOL(Shutdown, rt_shutdown_renderer_fn); RETRIEVE_SYMBOL(GetMaxFramesInFlight, rt_get_max_frames_in_flight_fn); RETRIEVE_SYMBOL(BeginFrame, rt_begin_frame_fn); RETRIEVE_SYMBOL(EndFrame, rt_end_frame_fn); RETRIEVE_SYMBOL(CompilePipeline, rt_compile_pipeline_fn); RETRIEVE_SYMBOL(DestroyPipeline, rt_destroy_pipeline_fn); RETRIEVE_SYMBOL(AllocCommandBuffers, rt_alloc_command_buffers_fn); RETRIEVE_SYMBOL(SubmitCommandBuffers, rt_submit_command_buffers_fn); RETRIEVE_SYMBOL(CreateBuffers, rt_create_buffers_fn); RETRIEVE_SYMBOL(DestroyBuffers, rt_destroy_buffers_fn); RETRIEVE_SYMBOL(CreateRenderGrapbuilder, rt_create_render_graph_builder_fn); RETRIEVE_SYMBOL(DestroyRenderGraphBuilder, rt_destroy_render_graph_builder_fn); RETRIEVE_SYMBOL(ExecuteRenderGraph, rt_execute_render_graph_fn); RETRIEVE_SYMBOL(SubmitRenderView, rt_submit_render_view_fn); RETRIEVE_SYMBOL(ResetRenderGraph, rt_reset_render_graph_fn); RETRIEVE_SYMBOL(CmdBeginPass, rt_cmd_begin_pass_fn); RETRIEVE_SYMBOL(CmdEndPass, rt_cmd_end_pass_fn); RETRIEVE_SYMBOL(CmdTransitionRenderTarget, rt_cmd_transition_render_target_fn); RETRIEVE_SYMBOL(CmdFlushRenderTargetWrite, rt_cmd_flush_render_target_write_fn); RETRIEVE_SYMBOL(CmdBindPipeline, rt_cmd_bind_pipeline_fn); RETRIEVE_SYMBOL(CmdBindVertexBuffers, rt_cmd_bind_vertex_buffers_fn); RETRIEVE_SYMBOL(CmdDraw, rt_cmd_draw_fn); } else { rtReportError("GFX", "Unsupported renderer backend: (%s) %s", rt_Renderer.name, rt_Renderer.s); return false; } #undef RETRIEVE_SYMBOL #else g_renderer.RegisterCVars = &rtRenRegisterCVars; g_renderer.Init = &rtRenInit; g_renderer.Shutdown = &rtRenShutdown; g_renderer.GetMaxFramesInFlight = &rtRenGetMaxFramesInFlight; g_renderer.BeginFrame = &rtRenBeginFrame; g_renderer.EndFrame = &rtRenEndFrame; g_renderer.CompilePipeline = &rtRenCompilePipeline; g_renderer.DestroyPipeline = &rtRenDestroyPipeline; g_renderer.AllocCommandBuffers = &rtRenAllocCommandBuffers; g_renderer.SubmitCommandBuffers = &rtRenSubmitCommandBuffers; g_renderer.CreateBuffers = &rtRenCreateBuffers; g_renderer.DestroyBuffers = &rtRenDestroyBuffers; g_renderer.CreateRenderGraphBuilder = &rtRenCreateRenderGraphBuilder; g_renderer.DestroyRenderGraphBuilder = &rtRenDestroyRenderGraphBuilder; g_renderer.ExecuteRenderGraph = &rtRenExecuteRenderGraph; g_renderer.SubmitRenderView = &rtRenSubmitRenderView; g_renderer.ResetRenderGraph = &rtRenResetRenderGraph; g_renderer.CmdBeginPass = &rtRenCmdBeginPass; g_renderer.CmdEndPass = &rtRenCmdEndPass; g_renderer.CmdTransitionRenderTarget = &rtRenCmdTransitionRenderTarget; g_renderer.CmdFlushRenderTargetWrite = &rtRenCmdFlushRenderTargetWrite; g_renderer.CmdBindPipeline = &rtRenCmdBindPipeline; g_renderer.CmdBindVertexBuffers = &rtRenCmdBindVertexBuffers; g_renderer.CmdDraw = &rtRenCmdDraw; #endif return true; } RT_DLLEXPORT void rtRegisterRendererCVars(void) { if (!_renderer_loaded) { if (!LoadRenderer()) return; _renderer_loaded = true; } g_renderer.RegisterCVars(); } RT_DLLEXPORT rt_result rtInitGFX(rt_renderer_init_info *renderer_info) { rtRegisterCVAR(&rt_Renderer); rtRegisterCVAR(&rt_RenderViewArenaSize); rtRegisterCVAR(&rt_RenderListPoolSize); if (!_renderer_loaded) { if (!LoadRenderer()) return RT_UNKNOWN_ERROR; g_renderer.RegisterCVars(); } rt_result result; if ((result = g_renderer.Init(renderer_info)) != RT_SUCCESS) return result; if ((result = InitRenderLists()) != RT_SUCCESS) return result; if ((result = InitRenderViews()) != RT_SUCCESS) return result; return result; } RT_DLLEXPORT void rtShutdownGFX(void) { ShutdownRenderViews(); ShutdownRenderLists(); g_renderer.Shutdown(); } RT_DLLEXPORT void rtBeginGFXFrame(unsigned int frame_id) { g_renderer.BeginFrame(frame_id); } RT_DLLEXPORT void rtEndGFXFrame(unsigned int frame_id) { g_renderer.EndFrame(frame_id); ResetRenderLists(); ResetRenderViews(); }