diff --git a/OgreMain/src/OgreHlmsDiskCache.cpp b/OgreMain/src/OgreHlmsDiskCache.cpp index 57a420c79d..dd1fbdf585 100644 --- a/OgreMain/src/OgreHlmsDiskCache.cpp +++ b/OgreMain/src/OgreHlmsDiskCache.cpp @@ -206,6 +206,9 @@ namespace Ogre uint32 numEntries; const HlmsDiskCache::SourceCode *sourceCode; bool templatesOutOfDate; + bool exceptionFound; // GUARDED_BY( mutex ) + std::exception_ptr threadedException; // GUARDED_BY( mutex ) + LightweightMutex mutex; CompilerJobParams( Hlms *_hlms, const HlmsDiskCache::SourceCodeVec &_sourceCode, bool _templatesOutOfDate ) : @@ -213,7 +216,8 @@ namespace Ogre currentEntry( 0u ), numEntries( static_cast( _sourceCode.size() ) ), sourceCode( _sourceCode.data() ), - templatesOutOfDate( _templatesOutOfDate ) + templatesOutOfDate( _templatesOutOfDate ), + exceptionFound( false ) { } }; @@ -250,20 +254,37 @@ namespace Ogre if( idx >= numEntries ) break; - // Compile shaders - if( !templatesOutOfDate ) + try { - // Templates haven't changed, send the Hlms-processed shader code for compilation - hlms->_compileShaderFromPreprocessedSource( sourceCode[idx].mergedCache, - sourceCode[idx].sourceFile, idx, threadIdx ); + // Compile shaders + if( !templatesOutOfDate ) + { + // Templates haven't changed, send the Hlms-processed shader code for compilation + hlms->_compileShaderFromPreprocessedSource( + sourceCode[idx].mergedCache, sourceCode[idx].sourceFile, idx, threadIdx ); + } + else + { + // Templates have changed, they need to be run through the Hlms + // preprocessor again before they can be compiled again + Hlms::ShaderCodeCache shaderCodeCache( sourceCode[idx].mergedCache.pieces ); + shaderCodeCache.mergedCache.setProperties = + sourceCode[idx].mergedCache.setProperties; + hlms->compileShaderCode( shaderCodeCache, idx, threadIdx ); + } } - else + catch( Exception & ) { - // Templates have changed, they need to be run through the Hlms - // preprocessor again before they can be compiled again - Hlms::ShaderCodeCache shaderCodeCache( sourceCode[idx].mergedCache.pieces ); - shaderCodeCache.mergedCache.setProperties = sourceCode[idx].mergedCache.setProperties; - hlms->compileShaderCode( shaderCodeCache, idx, threadIdx ); + ScopedLock lock( jobParams.mutex ); + // We can only report one exception. + if( !jobParams.exceptionFound ) + { + // Force the other threads to stop iterating. We're aborting. + jobParams.currentEntry.store( jobParams.numEntries, + std::memory_order::memory_order_relaxed ); + jobParams.exceptionFound = true; + jobParams.threadedException = std::current_exception(); + } } } } @@ -393,6 +414,12 @@ namespace Ogre _compileShadersThread( jobParams, Hlms::kNoTid ); } + if( jobParams.exceptionFound ) + { + hlms->clearShaderCache(); + std::rethrow_exception( jobParams.threadedException ); + } + hlms->_setShadersGenerated( jobParams.numEntries ); }