#include #include #define RT_DONT_DEFINE_RENDERER_GLOBAL #include "config.h" #include "dynamic_libs.h" #include "gfx.h" #include "renderer_api.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; static rt_dynlib _renderer_lib; static bool _renderer_loaded = false; RT_DLLEXPORT RT_CVAR_S(rt_Renderer, "Select the render backend. Available options: [vk], Default: vk", "vk"); #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 rt_pipeline_handle RT_RENDERER_API_FN(CompilePipeline)(const rt_pipeline_info *); extern void RT_RENDERER_API_FN(DestroyPipeline)(rt_pipeline_handle); extern rt_render_target_handle RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_target_info *); extern void RT_RENDERER_API_FN(DestroyRenderTarget)(rt_render_target_handle); #endif extern rt_result InitFramegraphManager(void); extern void ShutdownFramegraphManager(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(CompilePipeline, rt_compile_pipeline_fn); RETRIEVE_SYMBOL(DestroyPipeline, rt_destroy_pipeline_fn); RETRIEVE_SYMBOL(CreateRenderTarget, rt_create_render_target_fn); RETRIEVE_SYMBOL(DestroyRenderTarget, rt_destroy_render_target_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.CompilePipeline = &rtRenCompilePipeline; g_renderer.DestroyPipeline = &rtRenDestroyPipeline; g_renderer.CreateRenderTarget = &rtRenCreateRenderTarget; g_renderer.DestroyRenderTarget = &rtRenDestroyRenderTarget; #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) { 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 = InitFramegraphManager()) != RT_SUCCESS) return result; return result; } RT_DLLEXPORT void rtShutdownGFX(void) { ShutdownFramegraphManager(); g_renderer.Shutdown(); }