1
0
forked from 0ad/0ad

Fix rendering options failures following 8a1b3d6769

Two issues are fixed:
- Atlas on non-Mac crashed when started from within the game.
- MSAA options crashed if enabled on startup.

The underlying issues where improper shutdown, and assuming the renderer
was initialised than it might not be (in particular, the post-processor
wasn't).

Tested by: Stan
Differential Revision: https://code.wildfiregames.com/D3131
This was SVN commit r24233.
This commit is contained in:
wraitii 2020-11-22 11:09:13 +00:00
parent b3c5347e26
commit 3391542fec
4 changed files with 97 additions and 91 deletions

View File

@ -593,11 +593,11 @@ static void InitRenderer()
// create renderer // create renderer
new CRenderer; new CRenderer;
g_RenderingOptions.ReadConfig();
// create terrain related stuff // create terrain related stuff
new CTerrainTextureManager; new CTerrainTextureManager;
g_RenderingOptions.ReadConfigAndSetupHooks();
g_Renderer.Open(g_xres, g_yres); g_Renderer.Open(g_xres, g_yres);
// Setup lighting environment. Since the Renderer accesses the // Setup lighting environment. Since the Renderer accesses the
@ -695,6 +695,8 @@ void Shutdown(int flags)
TIMER_END(L"shutdown Renderer"); TIMER_END(L"shutdown Renderer");
} }
g_RenderingOptions.ClearHooks();
g_Profiler2.ShutdownGPU(); g_Profiler2.ShutdownGPU();
// Free cursors before shutting down SDL, as they may depend on SDL. // Free cursors before shutting down SDL, as they may depend on SDL.

View File

@ -591,7 +591,7 @@ void CPostprocManager::SetPostEffect(const CStrW& name)
void CPostprocManager::UpdateAntiAliasingTechnique() void CPostprocManager::UpdateAntiAliasingTechnique()
{ {
if (!g_RenderingOptions.GetPreferGLSL()) if (!g_RenderingOptions.GetPreferGLSL() || !m_IsInitialized)
return; return;
CStr newAAName; CStr newAAName;
@ -651,7 +651,7 @@ void CPostprocManager::UpdateAntiAliasingTechnique()
void CPostprocManager::UpdateSharpeningTechnique() void CPostprocManager::UpdateSharpeningTechnique()
{ {
if (!g_RenderingOptions.GetPreferGLSL()) if (!g_RenderingOptions.GetPreferGLSL() || !m_IsInitialized)
return; return;
CStr newSharpName; CStr newSharpName;

View File

@ -33,7 +33,16 @@ class CRenderingOptions::ConfigHooks
public: public:
std::vector<CConfigDB::hook_t>::iterator begin() { return hooks.begin(); } std::vector<CConfigDB::hook_t>::iterator begin() { return hooks.begin(); }
std::vector<CConfigDB::hook_t>::iterator end() { return hooks.end(); } std::vector<CConfigDB::hook_t>::iterator end() { return hooks.end(); }
void insert(CConfigDB::hook_t&& hook) { return hooks.emplace_back(std::move(hook)); } template<typename T>
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<void()> hook)
{
hooks.emplace_back(g_ConfigDB.RegisterHookAndCall(name, hook));
}
void clear() { hooks.clear(); }
private: private:
std::vector<CConfigDB::hook_t> hooks; std::vector<CConfigDB::hook_t> hooks;
}; };
@ -95,89 +104,78 @@ CRenderingOptions::CRenderingOptions() : m_ConfigHooks(new ConfigHooks())
CRenderingOptions::~CRenderingOptions() CRenderingOptions::~CRenderingOptions()
{ {
// This is currently irrelevant since CConfigDB is deleted before CRenderingOptions ClearHooks();
// (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));
} }
template<typename T> void CRenderingOptions::ReadConfigAndSetupHooks()
void CRenderingOptions::SetupConfig(CStr8 name, T& variable)
{ {
m_ConfigHooks->insert(g_ConfigDB.RegisterHookAndCall(name, [name, &variable]() { CFG_GET_VAL(name, variable); })); m_ConfigHooks->Setup("renderpath", [this]() {
}
void CRenderingOptions::SetupConfig(CStr8 name, std::function<void()> hook)
{
m_ConfigHooks->insert(g_ConfigDB.RegisterHookAndCall(name, hook));
}
void CRenderingOptions::ReadConfig()
{
SetupConfig("preferglsl", [this]() {
bool enabled;
CFG_GET_VAL("preferglsl", enabled);
SetPreferGLSL(enabled);
});
SetupConfig("shadowquality", []() {
g_Renderer.GetShadowMap().RecreateTexture();
});
SetupConfig("shadows", [this]() {
bool enabled;
CFG_GET_VAL("shadows", enabled);
SetShadows(enabled);
});
SetupConfig("shadowpcf", [this]() {
bool enabled;
CFG_GET_VAL("shadowpcf", enabled);
SetShadowPCF(enabled);
});
SetupConfig("antialiasing", []() {
g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique();
});
SetupConfig("sharpness", []() {
g_Renderer.GetPostprocManager().UpdateSharpnessFactor();
});
SetupConfig("sharpening", []() {
g_Renderer.GetPostprocManager().UpdateSharpeningTechnique();
});
SetupConfig("postproc", m_PostProc);
SetupConfig("smoothlos", m_SmoothLOS);
SetupConfig("renderpath", [this]() {
CStr renderPath; CStr renderPath;
CFG_GET_VAL("renderpath", renderPath); CFG_GET_VAL("renderpath", renderPath);
SetRenderPath(RenderPathEnum::FromString(renderPath)); SetRenderPath(RenderPathEnum::FromString(renderPath));
}); });
SetupConfig("watereffects", m_WaterEffects); m_ConfigHooks->Setup("preferglsl", [this]() {
SetupConfig("waterfancyeffects", m_WaterFancyEffects); bool enabled;
SetupConfig("waterrealdepth", m_WaterRealDepth); CFG_GET_VAL("preferglsl", enabled);
SetupConfig("waterrefraction", m_WaterRefraction); SetPreferGLSL(enabled);
SetupConfig("waterreflection", m_WaterReflection); });
SetupConfig("watershadows", m_WaterShadows);
SetupConfig("particles", m_Particles); m_ConfigHooks->Setup("shadowquality", []() {
SetupConfig("fog", [this]() { if (CRenderer::IsInitialised())
g_Renderer.GetShadowMap().RecreateTexture();
});
m_ConfigHooks->Setup("shadows", [this]() {
bool enabled;
CFG_GET_VAL("shadows", enabled);
SetShadows(enabled);
});
m_ConfigHooks->Setup("shadowpcf", [this]() {
bool enabled;
CFG_GET_VAL("shadowpcf", enabled);
SetShadowPCF(enabled);
});
m_ConfigHooks->Setup("postproc", m_PostProc);
m_ConfigHooks->Setup("antialiasing", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetPostprocManager().UpdateAntiAliasingTechnique();
});
m_ConfigHooks->Setup("sharpness", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetPostprocManager().UpdateSharpnessFactor();
});
m_ConfigHooks->Setup("sharpening", []() {
if (CRenderer::IsInitialised())
g_Renderer.GetPostprocManager().UpdateSharpeningTechnique();
});
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);
m_ConfigHooks->Setup("particles", m_Particles);
m_ConfigHooks->Setup("fog", [this]() {
bool enabled; bool enabled;
CFG_GET_VAL("fog", enabled); CFG_GET_VAL("fog", enabled);
SetFog(enabled); SetFog(enabled);
}); });
SetupConfig("silhouettes", m_Silhouettes); m_ConfigHooks->Setup("silhouettes", m_Silhouettes);
SetupConfig("showsky", m_ShowSky); m_ConfigHooks->Setup("showsky", m_ShowSky);
SetupConfig("novbo", m_NoVBO); m_ConfigHooks->Setup("novbo", m_NoVBO);
SetupConfig("forcealphatest", m_ForceAlphaTest); m_ConfigHooks->Setup("forcealphatest", m_ForceAlphaTest);
SetupConfig("gpuskinning", [this]() { m_ConfigHooks->Setup("gpuskinning", [this]() {
bool enabled; bool enabled;
CFG_GET_VAL("gpuskinning", enabled); CFG_GET_VAL("gpuskinning", enabled);
if (enabled && !m_PreferGLSL) if (enabled && !m_PreferGLSL)
@ -186,25 +184,36 @@ void CRenderingOptions::ReadConfig()
m_GPUSkinning = true; 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) void CRenderingOptions::SetShadows(bool value)
{ {
m_Shadows = value; m_Shadows = value;
g_Renderer.MakeShadersDirty(); if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
} }
void CRenderingOptions::SetShadowPCF(bool value) void CRenderingOptions::SetShadowPCF(bool value)
{ {
m_ShadowPCF = value; m_ShadowPCF = value;
g_Renderer.MakeShadersDirty(); if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
} }
void CRenderingOptions::SetFog(bool value) void CRenderingOptions::SetFog(bool value)
{ {
m_Fog = value; m_Fog = value;
g_Renderer.MakeShadersDirty(); if (CRenderer::IsInitialised())
g_Renderer.MakeShadersDirty();
} }
void CRenderingOptions::SetPreferGLSL(bool value) void CRenderingOptions::SetPreferGLSL(bool value)
@ -218,6 +227,8 @@ void CRenderingOptions::SetPreferGLSL(bool value)
CFG_GET_VAL("gpuskinning", m_GPUSkinning); CFG_GET_VAL("gpuskinning", m_GPUSkinning);
m_PreferGLSL = value; m_PreferGLSL = value;
if (!CRenderer::IsInitialised())
return;
g_Renderer.MakeShadersDirty(); g_Renderer.MakeShadersDirty();
g_Renderer.RecomputeSystemShaderDefines(); g_Renderer.RecomputeSystemShaderDefines();
} }
@ -226,5 +237,6 @@ void CRenderingOptions::SetPreferGLSL(bool value)
void CRenderingOptions::SetRenderPath(RenderPath value) void CRenderingOptions::SetRenderPath(RenderPath value)
{ {
m_RenderPath = value; m_RenderPath = value;
g_Renderer.SetRenderPath(m_RenderPath); if (CRenderer::IsInitialised())
g_Renderer.SetRenderPath(m_RenderPath);
} }

View File

@ -19,6 +19,9 @@
* Keeps track of the settings used for rendering. * Keeps track of the settings used for rendering.
* Ideally this header file should remain very quick to parse, * Ideally this header file should remain very quick to parse,
* so avoid including other headers here unless absolutely necessary. * 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 #ifndef INCLUDED_RENDERINGOPTIONS
@ -55,7 +58,8 @@ public:
CRenderingOptions(); CRenderingOptions();
~CRenderingOptions(); ~CRenderingOptions();
void ReadConfig(); void ReadConfigAndSetupHooks();
void ClearHooks();
#define OPTION_DEFAULT_SETTER(NAME, TYPE) \ #define OPTION_DEFAULT_SETTER(NAME, TYPE) \
public: void Set##NAME(TYPE value) { m_##NAME = value; }\ public: void Set##NAME(TYPE value) { m_##NAME = value; }\
@ -113,18 +117,6 @@ OPTION_CUSTOM_SETTER(NAME, TYPE); OPTION_GETTER(NAME, TYPE); OPTION_DEF(NAME, TY
#undef OPTION_WITH_SIDE_EFFECT #undef OPTION_WITH_SIDE_EFFECT
private: private:
/**
* Registers a config hook for config variable @name that updates @variable.
* Also immediately updates variable with the value of the config.
*/
template<typename T>
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<void()> hook);
class ConfigHooks; class ConfigHooks;
std::unique_ptr<ConfigHooks> m_ConfigHooks; // Hide this via PImpl to avoid including ConfigDB.h here. std::unique_ptr<ConfigHooks> m_ConfigHooks; // Hide this via PImpl to avoid including ConfigDB.h here.
}; };