Skip to content

Commit

Permalink
Support optionally skipping plugins that failed to load
Browse files Browse the repository at this point in the history
Plugins.cfg file must use "PluginOptional" instead of "Plugin"
This feature is needed for Vulkan as old GPUs will crash the whole
engine if the driver or the GPU is too old
  • Loading branch information
darksylinc committed Dec 23, 2021
1 parent 0adb2b6 commit 091cc39
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 87 deletions.
12 changes: 6 additions & 6 deletions CMake/Templates/plugins.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
PluginFolder=@OGRE_PLUGIN_DIR_REL@

# Define plugins
@OGRE_COMMENT_RENDERSYSTEM_METAL@ Plugin=RenderSystem_Metal
@OGRE_COMMENT_RENDERSYSTEM_D3D11@ Plugin=RenderSystem_Direct3D11
@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ Plugin=RenderSystem_GL3Plus
@OGRE_COMMENT_RENDERSYSTEM_GLES@ Plugin=RenderSystem_GLES
@OGRE_COMMENT_RENDERSYSTEM_GLES2@ Plugin=RenderSystem_GLES2
@OGRE_COMMENT_RENDERSYSTEM_METAL@ PluginOptional=RenderSystem_Metal
@OGRE_COMMENT_RENDERSYSTEM_D3D11@ PluginOptional=RenderSystem_Direct3D11
@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ PluginOptional=RenderSystem_GL3Plus
@OGRE_COMMENT_RENDERSYSTEM_GLES@ PluginOptional=RenderSystem_GLES
@OGRE_COMMENT_RENDERSYSTEM_GLES2@ PluginOptional=RenderSystem_GLES2
# If you add another RenderSystem make sure Vulkan is the last one or you might encounter issues on nVidia cards.
@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ Plugin=RenderSystem_Vulkan
@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ PluginOptional=RenderSystem_Vulkan
@OGRE_COMMENT_PLUGIN_PARTICLEFX@ Plugin=Plugin_ParticleFX
12 changes: 6 additions & 6 deletions CMake/Templates/plugins_d.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
PluginFolder=@OGRE_PLUGIN_DIR_DBG@

# Define plugins
@OGRE_COMMENT_RENDERSYSTEM_D3D11@ Plugin=RenderSystem_Direct3D11_d
@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ Plugin=RenderSystem_GL3Plus_d
@OGRE_COMMENT_RENDERSYSTEM_GLES@ Plugin=RenderSystem_GLES_d
@OGRE_COMMENT_RENDERSYSTEM_GLES2@ Plugin=RenderSystem_GLES2_d
@OGRE_COMMENT_RENDERSYSTEM_METAL@ Plugin=RenderSystem_Metal_d
@OGRE_COMMENT_RENDERSYSTEM_D3D11@ PluginOptional=RenderSystem_Direct3D11_d
@OGRE_COMMENT_RENDERSYSTEM_GL3PLUS@ PluginOptional=RenderSystem_GL3Plus_d
@OGRE_COMMENT_RENDERSYSTEM_GLES@ PluginOptional=RenderSystem_GLES_d
@OGRE_COMMENT_RENDERSYSTEM_GLES2@ PluginOptional=RenderSystem_GLES2_d
@OGRE_COMMENT_RENDERSYSTEM_METAL@ PluginOptional=RenderSystem_Metal_d
# If you add another RenderSystem make sure Vulkan is the last one or you might encounter issues on nVidia cards.
@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ Plugin=RenderSystem_Vulkan_d
@OGRE_COMMENT_RENDERSYSTEM_VULKAN@ PluginOptional=RenderSystem_Vulkan_d
@OGRE_COMMENT_PLUGIN_PARTICLEFX@ Plugin=Plugin_ParticleFX_d
6 changes: 5 additions & 1 deletion OgreMain/include/OgreDynLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,18 @@ namespace Ogre {
~DynLib();

/** Load the library
@param bOptional When true, we will skip it if it fails to initialize
*/
void load();
void load( const bool bOptional );
/** Unload the library
*/
void unload();
/// Get the name of the library
const String& getName(void) const { return mName; }

/// Returns true if it's successfully loaded
bool isLoaded(void) const;

/**
Returns the address of the given symbol from the loaded library.
@param
Expand Down
4 changes: 3 additions & 1 deletion OgreMain/include/OgreDynLibManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ namespace Ogre {
/** Loads the passed library.
@param filename
The name of the library. The extension can be omitted.
@param bOptional
When true, we will skip it if it fails to initialize
*/
DynLib* load(const String& filename);
DynLib *load( const String &filename, const bool bOptional );

/** Unloads the passed library.
@param lib
Expand Down
3 changes: 2 additions & 1 deletion OgreMain/include/OgreRoot.h
Original file line number Diff line number Diff line change
Expand Up @@ -711,8 +711,9 @@ namespace Ogre
method which instantiates a Plugin subclass and calls Root::installPlugin.
It should also implement dllStopPlugin (see Root::unloadPlugin)
@param pluginName Name of the plugin library to load
@param bOptional When true, we will skip it if it fails to initialize
*/
void loadPlugin(const String& pluginName);
void loadPlugin(const String& pluginName, const bool bOptional);

/** Manually unloads a Plugin contained in a DLL / DSO.
@remarks
Expand Down
46 changes: 31 additions & 15 deletions OgreMain/src/OgreDynLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ namespace Ogre {
}

//-----------------------------------------------------------------------
void DynLib::load()
void DynLib::load( const bool bOptional )
{
// Log library load
LogManager::getSingleton().logMessage("Loading library " + mName);
Expand Down Expand Up @@ -105,11 +105,21 @@ namespace Ogre {
}
#endif
if( !mInst )
OGRE_EXCEPT(
Exception::ERR_INTERNAL_ERROR,
"Could not load dynamic library " + mName +
". System Error: " + dynlibError(),
"DynLib::load" );
{
if( !bOptional )
{
OGRE_EXCEPT(
Exception::ERR_INTERNAL_ERROR,
"Could not load dynamic library " + mName + ". System Error: " + dynlibError(),
"DynLib::load" );
}
else
{
LogManager::getSingleton().logMessage( "Could not load optional dynamic library " +
mName + ". System Error: " + dynlibError(),
LML_CRITICAL );
}
}
}

//-----------------------------------------------------------------------
Expand All @@ -118,17 +128,19 @@ namespace Ogre {
// Log library unload
LogManager::getSingleton().logMessage("Unloading library " + mName);

if( DYNLIB_UNLOAD( mInst ) )
if( mInst )
{
OGRE_EXCEPT(
Exception::ERR_INTERNAL_ERROR,
"Could not unload dynamic library " + mName +
". System Error: " + dynlibError(),
"DynLib::unload");
if( DYNLIB_UNLOAD( mInst ) )
{
OGRE_EXCEPT(
Exception::ERR_INTERNAL_ERROR,
"Could not unload dynamic library " + mName + ". System Error: " + dynlibError(),
"DynLib::unload" );
}
}

}

//-----------------------------------------------------------------------
bool DynLib::isLoaded( void ) const { return mInst != NULL; }
//-----------------------------------------------------------------------
void* DynLib::getSymbol( const String& strName ) const throw()
{
Expand Down Expand Up @@ -185,7 +197,11 @@ namespace Ogre {
#endif
return ret;
#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE || OGRE_PLATFORM == OGRE_PLATFORM_FREEBSD
return String(dlerror());
const char *errorStr = dlerror();
if( errorStr )
return String( errorStr );
else
return String( "" );
#else
return String("");
#endif
Expand Down
10 changes: 5 additions & 5 deletions OgreMain/src/OgreDynLibManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ namespace Ogre
{
}
//-----------------------------------------------------------------------
DynLib* DynLibManager::load( const String& filename)
DynLib *DynLibManager::load( const String &filename, const bool bOptional )
{
DynLibList::iterator i = mLibList.find(filename);
if (i != mLibList.end())
DynLibList::iterator i = mLibList.find( filename );
if( i != mLibList.end() )
{
return i->second;
}
else
{
DynLib* pLib = OGRE_NEW DynLib(filename);
pLib->load();
DynLib *pLib = OGRE_NEW DynLib( filename );
pLib->load( bOptional );
mLibList[filename] = pLib;
return pLib;
}
Expand Down
126 changes: 82 additions & 44 deletions OgreMain/src/OgreRoot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1203,23 +1203,22 @@ namespace Ogre {
//-----------------------------------------------------------------------
void Root::loadPlugins( const String& pluginsfile )
{
StringVector pluginList;
String pluginDir;
ConfigFile cfg;

try {
try
{
cfg.load( pluginsfile );
}
catch (Exception)
catch( Exception )
{
LogManager::getSingleton().logMessage(pluginsfile + " not found, automatic plugin loading disabled.");
LogManager::getSingleton().logMessage( pluginsfile +
" not found, automatic plugin loading disabled." );
return;
}

pluginDir = cfg.getSetting("PluginFolder"); // Ignored on Mac OS X, uses Resources/ directory
pluginList = cfg.getMultiSetting("Plugin");

if (!pluginDir.empty() && *pluginDir.rbegin() != '/' && *pluginDir.rbegin() != '\\')
String pluginDir =
cfg.getSetting( "PluginFolder" ); // Ignored on Mac OS X, uses Resources/ directory
if( !pluginDir.empty() && *pluginDir.rbegin() != '/' && *pluginDir.rbegin() != '\\' )
{
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WINRT
pluginDir += "\\";
Expand All @@ -1228,11 +1227,22 @@ namespace Ogre {
#endif
}

for( StringVector::iterator it = pluginList.begin(); it != pluginList.end(); ++it )
{
loadPlugin(pluginDir + (*it));
// First load optional plugins (which tend to be all RenderSystems)
const StringVector pluginList = cfg.getMultiSetting( "PluginOptional" );
for( StringVector::const_iterator it = pluginList.begin(); it != pluginList.end(); ++it )
{
loadPlugin( pluginDir + ( *it ), true );
}
}
{
// Then load non-optional plugins (which tend to depend on RenderSystems)
const StringVector pluginList = cfg.getMultiSetting( "Plugin" );
for( StringVector::const_iterator it = pluginList.begin(); it != pluginList.end(); ++it )
{
loadPlugin( pluginDir + ( *it ), false );
}
}

}
//-----------------------------------------------------------------------
void Root::shutdownPlugins(void)
Expand All @@ -1256,18 +1266,21 @@ namespace Ogre {
{
#if OGRE_PLATFORM != OGRE_PLATFORM_NACL && OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
// unload dynamic libs first
for (PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i)
for( PluginLibList::reverse_iterator i = mPluginLibs.rbegin(); i != mPluginLibs.rend(); ++i )
{
// Call plugin shutdown
#ifdef __GNUC__
__extension__
#endif
DLL_STOP_PLUGIN pFunc = reinterpret_cast<DLL_STOP_PLUGIN>((*i)->getSymbol("dllStopPlugin"));
// this will call uninstallPlugin
pFunc();
if( ( *i )->isLoaded() )
{
// Call plugin shutdown
# ifdef __GNUC__
__extension__
# endif
DLL_STOP_PLUGIN pFunc =
reinterpret_cast<DLL_STOP_PLUGIN>( ( *i )->getSymbol( "dllStopPlugin" ) );
// this will call uninstallPlugin
pFunc();
}
// Unload library & destroy
DynLibManager::getSingleton().unload(*i);

DynLibManager::getSingleton().unload( *i );
}
mPluginLibs.clear();

Expand Down Expand Up @@ -1459,29 +1472,52 @@ namespace Ogre {

}
//-----------------------------------------------------------------------
void Root::loadPlugin(const String& pluginName)
void Root::loadPlugin( const String &pluginName, const bool bOptional )
{
#if OGRE_PLATFORM != OGRE_PLATFORM_NACL && OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
// Load plugin library
DynLib* lib = DynLibManager::getSingleton().load( pluginName );
DynLib* lib = DynLibManager::getSingleton().load( pluginName, bOptional );

// Store for later unload
// Check for existence, because if called 2+ times DynLibManager returns existing entry
if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) == mPluginLibs.end())
{
mPluginLibs.push_back(lib);

// Call startup function
#ifdef __GNUC__
__extension__
#endif
DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
if( lib->isLoaded() )
{
// Call startup function
# ifdef __GNUC__
__extension__
# endif
DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol( "dllStartPlugin" );

if (!pFunc)
OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName,
"Root::loadPlugin");
if( !pFunc )
{
OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND,
"Cannot find symbol dllStartPlugin in library " + pluginName,
"Root::loadPlugin" );
}

// This must call installPlugin
pFunc();
try
{
// This must call installPlugin
pFunc();
}
catch( Exception &e )
{
if( !bOptional )
{
throw;
}
else
{
LogManager::getSingleton().logMessage(
"Optional Plugin " + pluginName + " failed with exception:", LML_CRITICAL );
LogManager::getSingleton().logMessage( e.getFullDescription(), LML_CRITICAL );
}
}
}
}
#endif
}
Expand All @@ -1495,19 +1531,21 @@ namespace Ogre {
{
if ((*i)->getName() == pluginName)
{
// Call plugin shutdown
#ifdef __GNUC__
__extension__
#endif
DLL_STOP_PLUGIN pFunc = (DLL_STOP_PLUGIN)(*i)->getSymbol("dllStopPlugin");
// this must call uninstallPlugin
pFunc();
if( ( *i )->isLoaded() )
{
// Call plugin shutdown
# ifdef __GNUC__
__extension__
# endif
DLL_STOP_PLUGIN pFunc = ( DLL_STOP_PLUGIN )( *i )->getSymbol( "dllStopPlugin" );
// this must call uninstallPlugin
pFunc();
}
// Unload library (destroyed by DynLibManager)
DynLibManager::getSingleton().unload(*i);
mPluginLibs.erase(i);
DynLibManager::getSingleton().unload( *i );
mPluginLibs.erase( i );
return;
}

}
#endif
}
Expand Down
7 changes: 6 additions & 1 deletion PlugIns/ParticleFX/src/OgreParticleFX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ namespace Ogre {

ParticleFXPlugin* plugin;
//-----------------------------------------------------------------------
extern "C" void _OgreParticleFXExport dllStartPlugin(void) throw()

# if __cplusplus >= 201103L
extern "C" void _OgreParticleFXExport dllStartPlugin( void ) noexcept( false )
# else
extern "C" void _OgreParticleFXExport dllStartPlugin( void ) throw( Exception )
# endif
{
plugin = OGRE_NEW ParticleFXPlugin();
Root::getSingleton().installPlugin(plugin);
Expand Down
6 changes: 5 additions & 1 deletion RenderSystems/Direct3D11/src/OgreD3D11EngineDll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ namespace Ogre
{
D3D11Plugin* plugin;

extern "C" void _OgreD3D11Export dllStartPlugin(void) throw()
# if __cplusplus >= 201103L
extern "C" void _OgreD3D11Export dllStartPlugin( void ) noexcept( false )
# else
extern "C" void _OgreD3D11Export dllStartPlugin( void ) throw( Exception )
# endif
{
plugin = new D3D11Plugin();
Root::getSingleton().installPlugin(plugin);
Expand Down
Loading

0 comments on commit 091cc39

Please sign in to comment.