#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_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 handle); #endif 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); } 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; #endif return true; } RT_DLLEXPORT void rtRegisterRendererCVars(void) { if (!_renderer_loaded) { if (!LoadRenderer()) return; _renderer_loaded = true; } g_renderer.RegisterCVars(); } RT_DLLEXPORT bool rtInitGFX(rt_renderer_init_info *renderer_info) { if (!_renderer_loaded) { if (!LoadRenderer()) return false; g_renderer.RegisterCVars(); } if (g_renderer.Init(renderer_info) != RT_SUCCESS) return false; return true; } RT_DLLEXPORT void rtShutdownGFX(void) { g_renderer.Shutdown(); }