RenderSystem fallbacks


04-11-2010 18:46:09

I've been using Mogre for throwing together a quick and easy visualisation for a physics simulations class. I've been using the Direct3D rendersystem on my development station with no issue, however the person grading wants the program to work on lab computers that don't have Direct3D setup. Thankfully, switching to OpenGL works fine, so I went about to implementing a way of having it fall back to OpenGL if Direct3D fails. At first I just checked for null return values on Root.GetRenderSystemByName() like so:
RenderSystem rs = _root.GetRenderSystemByName("Direct3D9 Rendering Subsystem");

if (rs == null)
rs = _root.GetRenderSystemByName("OpenGL Rendering Subsystem");

However, it turns out plugin load failure is thrown on Root construction. So the unhandled constructor exception gives me a null _root and nothing works. So I added an exception handler when constructing the root:
// Create root object
_root = new Root();
catch (System.Runtime.InteropServices.SEHException ex)
if (!Mogre.OgreException.IsThrown || Mogre.OgreException.LastException.Number != OgreException.ExceptionCodes.ERR_INTERNAL_ERROR)
throw ex;
if (_root == null)
_root = new Root("plugins_fallback.cfg");

The fallback plugins cfg simply doesn't have Direct3D9 render system enabled, and everything seems to initialise fine. The root gets assigned the OpenGL rendersystem at the null check from before.

However, it turns out the first attempt to create the root does allocate a native root to an extent, as I can look with the debugger during the exception to see Mogre.Root.Singleton._native set. Somehow, this incomplete Root gets garbage collected afterwards, causing Mogre to crash on the root's Finalizer, and I haven't found any way to avoid this. Is this a bug with regards to incomplete Root construction, or am I handling my RenderSystem fallback wrong?


04-11-2010 22:57:08

what about using root.LoadPlugin to load plugins manually, instead of using a config file ? this way, you need to instantiate root only once, and you can add a try catch block only on the line loading the d3d9 plugin, so you can load opengl plugin as a fallback.

I haven't test it extensively, but this way, you could avoid creating 2 root objects.


05-11-2010 00:10:23

Ah, that works.

I wasn't even aware Ogre could be told to manually load plugins -- all examples I'd seen relied on it, even those that used a custom config dialog. Learn something new everyday, thanks!


05-11-2010 21:16:21

I never like the idea of using exception handling to determine state information.

I solved this by simply determining whether the user has the correct DirectX version installed (in my case it has to be very specific), and if not just modify the Ogre.cfg (whatever you call it)... to have the OpenGL render subsystem set.
then call root like this:

m_Root = new Root(c_OgrePluginLocation, PathHelper.CreateAbsolutePath(OgreRenderingMode.OgreDisplayOptions), PathHelper.CreateAbsolutePath(c_OgreLog));



if (m_OgreRenderingMode.LoadFromConfig && m_Root.RestoreConfig())
m_ValidUpdateRenderSystem = true;
else if (!TrySetDefaultRenderSystem())