Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp +++ source/ps/GameSetup/GameSetup.cpp @@ -593,11 +593,11 @@ // create renderer new CRenderer; - g_RenderingOptions.ReadConfig(); - // create terrain related stuff new CTerrainTextureManager; + g_RenderingOptions.ReadConfigAndSetupHooks(); + g_Renderer.Open(g_xres, g_yres); // Setup lighting environment. Since the Renderer accesses the @@ -695,6 +695,8 @@ TIMER_END(L"shutdown Renderer"); } + g_RenderingOptions.ClearHooks(); + g_Profiler2.ShutdownGPU(); // Free cursors before shutting down SDL, as they may depend on SDL. Index: source/renderer/PostprocManager.cpp =================================================================== --- source/renderer/PostprocManager.cpp +++ source/renderer/PostprocManager.cpp @@ -591,7 +591,7 @@ void CPostprocManager::UpdateAntiAliasingTechnique() { - if (!g_RenderingOptions.GetPreferGLSL()) + if (!g_RenderingOptions.GetPreferGLSL() || !m_IsInitialized) return; CStr newAAName; @@ -651,7 +651,7 @@ void CPostprocManager::UpdateSharpeningTechnique() { - if (!g_RenderingOptions.GetPreferGLSL()) + if (!g_RenderingOptions.GetPreferGLSL() || !m_IsInitialized) return; CStr newSharpName; Index: source/renderer/RenderingOptions.h =================================================================== --- source/renderer/RenderingOptions.h +++ source/renderer/RenderingOptions.h @@ -19,6 +19,9 @@ * Keeps track of the settings used for rendering. * Ideally this header file should remain very quick to parse, * so avoid including other headers here unless absolutely necessary. + * + * Lifetime concerns: g_RenderingOptions always exists, but hooks are tied to the configDB's lifetime + * an the renderer may or may not actually exist. */ #ifndef INCLUDED_RENDERINGOPTIONS @@ -55,7 +58,8 @@ CRenderingOptions(); ~CRenderingOptions(); - void ReadConfig(); + void ReadConfigAndSetupHooks(); + void ClearHooks(); #define OPTION_DEFAULT_SETTER(NAME, TYPE) \ public: void Set##NAME(TYPE value) { m_##NAME = value; }\ @@ -113,18 +117,6 @@ #undef OPTION_WITH_SIDE_EFFECT private: - /** - * Registers a config hook for config variable @name that updates @variable. - * Also immediately updates variable with the value of the config. - */ - template - void SetupConfig(CStr8 name, T& variable); - /** - * Registers a config hook for config variable @name. - * Also immediately triggers the hook. - */ - void SetupConfig(CStr8 name, std::function hook); - class ConfigHooks; std::unique_ptr m_ConfigHooks; // Hide this via PImpl to avoid including ConfigDB.h here. }; Index: source/renderer/RenderingOptions.cpp =================================================================== --- source/renderer/RenderingOptions.cpp +++ source/renderer/RenderingOptions.cpp @@ -33,7 +33,16 @@ public: std::vector::iterator begin() { return hooks.begin(); } std::vector::iterator end() { return hooks.end(); } - void insert(CConfigDB::hook_t&& hook) { return hooks.emplace_back(std::move(hook)); } + template + void Setup(CStr8 name, T& variable) + { + hooks.emplace_back(g_ConfigDB.RegisterHookAndCall(name, [name, &variable]() { CFG_GET_VAL(name, variable); })); + } + void Setup(CStr8 name, std::function hook) + { + hooks.emplace_back(g_ConfigDB.RegisterHookAndCall(name, hook)); + } + void clear() { hooks.clear(); } private: std::vector hooks; }; @@ -95,89 +104,78 @@ CRenderingOptions::~CRenderingOptions() { - // This is currently irrelevant since CConfigDB is deleted before CRenderingOptions - // (as only the latter is a static variable), but the check is a good idea regardless. - if (!CConfigDB::IsInitialised()) - return; - for (CConfigDB::hook_t& hook : *m_ConfigHooks) - g_ConfigDB.UnregisterHook(std::move(hook)); + ClearHooks(); } -template -void CRenderingOptions::SetupConfig(CStr8 name, T& variable) +void CRenderingOptions::ReadConfigAndSetupHooks() { - m_ConfigHooks->insert(g_ConfigDB.RegisterHookAndCall(name, [name, &variable]() { CFG_GET_VAL(name, variable); })); -} + m_ConfigHooks->Setup("renderpath", [this]() { + CStr renderPath; + CFG_GET_VAL("renderpath", renderPath); + SetRenderPath(RenderPathEnum::FromString(renderPath)); + }); -void CRenderingOptions::SetupConfig(CStr8 name, std::function hook) -{ - m_ConfigHooks->insert(g_ConfigDB.RegisterHookAndCall(name, hook)); -} - -void CRenderingOptions::ReadConfig() -{ - SetupConfig("preferglsl", [this]() { + m_ConfigHooks->Setup("preferglsl", [this]() { bool enabled; CFG_GET_VAL("preferglsl", enabled); SetPreferGLSL(enabled); }); - SetupConfig("shadowquality", []() { - g_Renderer.GetShadowMap().RecreateTexture(); + m_ConfigHooks->Setup("shadowquality", []() { + if (CRenderer::IsInitialised()) + g_Renderer.GetShadowMap().RecreateTexture(); }); - SetupConfig("shadows", [this]() { + m_ConfigHooks->Setup("shadows", [this]() { bool enabled; CFG_GET_VAL("shadows", enabled); SetShadows(enabled); }); - SetupConfig("shadowpcf", [this]() { + m_ConfigHooks->Setup("shadowpcf", [this]() { bool enabled; CFG_GET_VAL("shadowpcf", enabled); SetShadowPCF(enabled); }); - SetupConfig("antialiasing", []() { - g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique(); - }); + m_ConfigHooks->Setup("postproc", m_PostProc); - SetupConfig("sharpness", []() { - g_Renderer.GetPostprocManager().UpdateSharpnessFactor(); + m_ConfigHooks->Setup("antialiasing", []() { + if (CRenderer::IsInitialised()) + g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique(); }); - SetupConfig("sharpening", []() { - g_Renderer.GetPostprocManager().UpdateSharpeningTechnique(); + m_ConfigHooks->Setup("sharpness", []() { + if (CRenderer::IsInitialised()) + g_Renderer.GetPostprocManager().UpdateSharpnessFactor(); }); - SetupConfig("postproc", m_PostProc); - SetupConfig("smoothlos", m_SmoothLOS); - - SetupConfig("renderpath", [this]() { - CStr renderPath; - CFG_GET_VAL("renderpath", renderPath); - SetRenderPath(RenderPathEnum::FromString(renderPath)); + m_ConfigHooks->Setup("sharpening", []() { + if (CRenderer::IsInitialised()) + g_Renderer.GetPostprocManager().UpdateSharpeningTechnique(); }); - SetupConfig("watereffects", m_WaterEffects); - SetupConfig("waterfancyeffects", m_WaterFancyEffects); - SetupConfig("waterrealdepth", m_WaterRealDepth); - SetupConfig("waterrefraction", m_WaterRefraction); - SetupConfig("waterreflection", m_WaterReflection); - SetupConfig("watershadows", m_WaterShadows); + m_ConfigHooks->Setup("smoothlos", m_SmoothLOS); + + m_ConfigHooks->Setup("watereffects", m_WaterEffects); + m_ConfigHooks->Setup("waterfancyeffects", m_WaterFancyEffects); + m_ConfigHooks->Setup("waterrealdepth", m_WaterRealDepth); + m_ConfigHooks->Setup("waterrefraction", m_WaterRefraction); + m_ConfigHooks->Setup("waterreflection", m_WaterReflection); + m_ConfigHooks->Setup("watershadows", m_WaterShadows); - SetupConfig("particles", m_Particles); - SetupConfig("fog", [this]() { + m_ConfigHooks->Setup("particles", m_Particles); + m_ConfigHooks->Setup("fog", [this]() { bool enabled; CFG_GET_VAL("fog", enabled); SetFog(enabled); }); - SetupConfig("silhouettes", m_Silhouettes); - SetupConfig("showsky", m_ShowSky); + m_ConfigHooks->Setup("silhouettes", m_Silhouettes); + m_ConfigHooks->Setup("showsky", m_ShowSky); - SetupConfig("novbo", m_NoVBO); + m_ConfigHooks->Setup("novbo", m_NoVBO); - SetupConfig("forcealphatest", m_ForceAlphaTest); - SetupConfig("gpuskinning", [this]() { + m_ConfigHooks->Setup("forcealphatest", m_ForceAlphaTest); + m_ConfigHooks->Setup("gpuskinning", [this]() { bool enabled; CFG_GET_VAL("gpuskinning", enabled); if (enabled && !m_PreferGLSL) @@ -186,25 +184,36 @@ m_GPUSkinning = true; }); - SetupConfig("renderactors", m_RenderActors); + m_ConfigHooks->Setup("renderactors", m_RenderActors); +} + +void CRenderingOptions::ClearHooks() +{ + if (CConfigDB::IsInitialised()) + for (CConfigDB::hook_t& hook : *m_ConfigHooks) + g_ConfigDB.UnregisterHook(std::move(hook)); + m_ConfigHooks->clear(); } void CRenderingOptions::SetShadows(bool value) { m_Shadows = value; - g_Renderer.MakeShadersDirty(); + if (CRenderer::IsInitialised()) + g_Renderer.MakeShadersDirty(); } void CRenderingOptions::SetShadowPCF(bool value) { m_ShadowPCF = value; - g_Renderer.MakeShadersDirty(); + if (CRenderer::IsInitialised()) + g_Renderer.MakeShadersDirty(); } void CRenderingOptions::SetFog(bool value) { m_Fog = value; - g_Renderer.MakeShadersDirty(); + if (CRenderer::IsInitialised()) + g_Renderer.MakeShadersDirty(); } void CRenderingOptions::SetPreferGLSL(bool value) @@ -218,6 +227,8 @@ CFG_GET_VAL("gpuskinning", m_GPUSkinning); m_PreferGLSL = value; + if (!CRenderer::IsInitialised()) + return; g_Renderer.MakeShadersDirty(); g_Renderer.RecomputeSystemShaderDefines(); } @@ -226,5 +237,6 @@ void CRenderingOptions::SetRenderPath(RenderPath value) { m_RenderPath = value; - g_Renderer.SetRenderPath(m_RenderPath); + if (CRenderer::IsInitialised()) + g_Renderer.SetRenderPath(m_RenderPath); }