From 8d194a1601252261155807301d106b16224540bb Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 3 Aug 2022 19:12:45 +0200 Subject: [PATCH 01/24] Shaders: rudimentary hot reloader on shaders every frame we poll the files and check if they are older or newer than the last test, if they are newer we find all the shader that included that file and update them --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- components/shader/shadermanager.cpp | 105 +++++++++++++++++++++- components/shader/shadermanager.hpp | 8 +- 3 files changed, 108 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 8c39c13941..2aef65029c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -902,7 +902,7 @@ namespace MWRender void RenderingManager::update(float dt, bool paused) { reportStats(); - + mResourceSystem->getSceneManager()->getShaderManager().update(); float rainIntensity = mSky->getPrecipitationAlpha(); mWater->setRainIntensity(rainIntensity); diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 8136bab447..7030042fb2 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -5,7 +5,7 @@ #include #include #include - +#include #include #include @@ -16,6 +16,11 @@ namespace Shader { ShaderManager::ShaderManager() + { + mHotReloadManager = std::make_unique(); + } + + ShaderManager::~ShaderManager() { } @@ -68,7 +73,7 @@ namespace Shader // Recursively replaces include statements with the actual source of the included files. // Adjusts #line statements accordingly and detects cyclic includes. // includingFiles is the set of files that include this file directly or indirectly, and is intentionally not a reference to allow automatic cleanup. - static bool parseIncludes(const std::filesystem::path& shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set includingFiles) + static bool parseIncludes(const std::filesystem::path& shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set& includingFiles) { // An include is cyclic if it is being included by itself if (includingFiles.insert(shaderPath/fileName).second == false) @@ -355,12 +360,100 @@ namespace Shader return true; } + struct HotReloadManager + { + + + std::filesystem::file_time_type mLastAutoRecompileTime; + using KeysHolder = std::set; + std::unordered_map mShaderFiles; + HotReloadManager() + { + mLastAutoRecompileTime = std::chrono::file_clock::now(); + } + + void addShaderFiles(std::set& shaderFiles,const osg::ref_ptr& shader,const std::string& templateName,const ShaderManager::DefineMap& defines ) + { + for (const std::filesystem::path& file : shaderFiles) + { + KeysHolder* shaderSet_ptr; + auto found = mShaderFiles.find(file.string()); + if (found != mShaderFiles.end()) //Apparently there is an issue that prevents me from using operator[] + { + shaderSet_ptr = &found->second; + } + else + { + shaderSet_ptr = &mShaderFiles.insert(std::make_pair<>(file.string(), KeysHolder())).first->second; + } + auto& shaderSet = *shaderSet_ptr; + shaderSet.insert(std::make_pair( templateName, defines )); + } + } + + void update(ShaderManager& Manager) + { + for (auto& shader : mShaderFiles) + { + std::filesystem::path pathShaderToTest = (shader.first); + + std::filesystem::file_time_type write_time = std::filesystem::last_write_time(pathShaderToTest); + //Log(Debug::Info) << std::format("{} write time is {} compared to {} ", shader.first, write_time, mLastAutoRecompileTime); + if (write_time.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch()) + { + for (const ShaderManager:: MapKey& descriptor : shader.second) + { + const std::string& templateName = descriptor.first; + ShaderManager::ShaderMap::iterator shaderIt = Manager.mShaders.find(std::make_pair(templateName, descriptor.second)); + + ShaderManager::TemplateMap::iterator templateIt = Manager.mShaderTemplates.find(templateName); //Can't be Null, if we're here it means the template was added + std::set insertedPaths; + { + std::filesystem::path path = (std::filesystem::path(Manager.mPath) / templateName); + std::ifstream stream; + stream.open(path); + if (stream.fail()) + { + Log(Debug::Error) << "Failed to open " << path.string(); + } + std::stringstream buffer; + buffer << stream.rdbuf(); + + // parse includes + int fileNumber = 1; + std::string source = buffer.str(); + if (!addLineDirectivesAfterConditionalBlocks(source) + || !parseIncludes(std::filesystem::path(Manager.mPath), source, templateName, fileNumber, insertedPaths)) + { + } + templateIt->second = source; + + //if (shaderIt == Manager.mShaders.end()) + { + std::string shaderSource = templateIt->second; + std::vector linkedShaderNames; + if (!Manager.createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, descriptor.second)) + { + + } + shaderIt->second->setShaderSource(shaderSource); + } + } + } + } + } + mLastAutoRecompileTime = std::chrono::file_clock::now(); + } + }; + osg::ref_ptr ShaderManager::getShader(const std::string &templateName, const ShaderManager::DefineMap &defines, osg::Shader::Type shaderType) { std::unique_lock lock(mMutex); // read the template if we haven't already TemplateMap::iterator templateIt = mShaderTemplates.find(templateName); + std::set insertedPaths; + if (templateIt == mShaderTemplates.end()) { std::filesystem::path path = (std::filesystem::path(mPath) / templateName); @@ -378,7 +471,7 @@ namespace Shader int fileNumber = 1; std::string source = buffer.str(); if (!addLineDirectivesAfterConditionalBlocks(source) - || !parseIncludes(std::filesystem::path(mPath), source, templateName, fileNumber, {})) + || !parseIncludes(std::filesystem::path(mPath), source, templateName, fileNumber, insertedPaths)) return nullptr; templateIt = mShaderTemplates.insert(std::make_pair(templateName, source)).first; @@ -402,6 +495,7 @@ namespace Shader // Append shader source filename for debugging. static unsigned int counter = 0; shader->setName(Misc::StringUtils::format("%u %s", counter++, templateName)); + mHotReloadManager->addShaderFiles(insertedPaths, shader, templateName, defines); lock.unlock(); getLinkedShaders(shader, linkedShaderNames, defines); @@ -535,4 +629,9 @@ namespace Shader return unit; } + void ShaderManager::update() + { + mHotReloadManager->update(*this); + } + } diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index 4d3cc9937a..e0649047ef 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -14,14 +14,15 @@ namespace Shader { - + struct HotReloadManager; /// @brief Reads shader template files and turns them into a concrete shader, based on a list of define's. /// @par Shader templates can get the value of a define with the syntax @define. class ShaderManager { public: - + friend HotReloadManager; ShaderManager(); + ~ShaderManager(); void setShaderPath(const std::string& path); @@ -67,6 +68,7 @@ namespace Shader int reserveGlobalTextureUnits(Slot slot); + void update(); private: void getLinkedShaders(osg::ref_ptr shader, const std::vector& linkedShaderNames, const DefineMap& defines); void addLinkedShaders(osg::ref_ptr shader, osg::ref_ptr program); @@ -96,7 +98,7 @@ namespace Shader int mMaxTextureUnits = 0; int mReservedTextureUnits = 0; - + std::unique_ptr mHotReloadManager; std::array mReservedTextureUnitsBySlot = {-1, -1}; }; From 4e7c1c5befc626dd81441cf27cd9027f42ce9be2 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 3 Aug 2022 19:21:48 +0200 Subject: [PATCH 02/24] Added break when the operation failed --- components/shader/shadermanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 7030042fb2..cef4e8dd0d 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -425,6 +425,7 @@ namespace Shader if (!addLineDirectivesAfterConditionalBlocks(source) || !parseIncludes(std::filesystem::path(Manager.mPath), source, templateName, fileNumber, insertedPaths)) { + break; } templateIt->second = source; @@ -434,7 +435,7 @@ namespace Shader std::vector linkedShaderNames; if (!Manager.createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, descriptor.second)) { - + break; } shaderIt->second->setShaderSource(shaderSource); } From 6b38d6222398c50ca115a7fb14d90981d833be35 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 3 Aug 2022 19:56:19 +0200 Subject: [PATCH 03/24] Added lua bindings to toggle hot reload (disabled by default) or to trigger a reload --- apps/openmw/mwlua/debugbindings.cpp | 14 ++++++++++++++ components/shader/shadermanager.cpp | 18 ++++++++++++++++++ components/shader/shadermanager.hpp | 2 ++ 3 files changed, 34 insertions(+) diff --git a/apps/openmw/mwlua/debugbindings.cpp b/apps/openmw/mwlua/debugbindings.cpp index fe00fa72b2..189d44cd86 100644 --- a/apps/openmw/mwlua/debugbindings.cpp +++ b/apps/openmw/mwlua/debugbindings.cpp @@ -6,6 +6,10 @@ #include "../mwbase/world.hpp" #include "../mwrender/renderingmanager.hpp" +#include +#include +#include + #include namespace MWLua @@ -46,6 +50,16 @@ namespace MWLua }); }; + api["triggerShaderReload"] = [context]() + { + MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().triggerShaderReload(); + }; + + api["togggleShaderHotReload"] = [context](bool value) + { + MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().setHotReloadEnabled(value); + }; + return LuaUtil::makeReadOnly(api); } } diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index cef4e8dd0d..ec0e30c97a 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -367,8 +367,10 @@ namespace Shader std::filesystem::file_time_type mLastAutoRecompileTime; using KeysHolder = std::set; std::unordered_map mShaderFiles; + bool mHotReloadEnabled; HotReloadManager() { + mHotReloadEnabled = false; mLastAutoRecompileTime = std::chrono::file_clock::now(); } @@ -392,6 +394,12 @@ namespace Shader } void update(ShaderManager& Manager) + { + if (mHotReloadEnabled) + reloadTouchedShaders(Manager); + } + + void reloadTouchedShaders(ShaderManager& Manager) { for (auto& shader : mShaderFiles) { @@ -635,4 +643,14 @@ namespace Shader mHotReloadManager->update(*this); } + void ShaderManager::setHotReloadEnabled(bool value) + { + mHotReloadManager->mHotReloadEnabled = value; + } + + void ShaderManager::triggerShaderReload() + { + mHotReloadManager->reloadTouchedShaders(*this); + } + } diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index e0649047ef..01efeea6c7 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -69,6 +69,8 @@ namespace Shader int reserveGlobalTextureUnits(Slot slot); void update(); + void setHotReloadEnabled(bool value); + void triggerShaderReload(); private: void getLinkedShaders(osg::ref_ptr shader, const std::vector& linkedShaderNames, const DefineMap& defines); void addLinkedShaders(osg::ref_ptr shader, osg::ref_ptr program); From 31d412527daf75bff05a9e1428d3c5573015ea86 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 3 Aug 2022 20:17:53 +0200 Subject: [PATCH 04/24] forgot memory include --- components/shader/shadermanager.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index 01efeea6c7..50bc101ed6 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include From f78fa989ee5727457c9dc17b706553635f9af348 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 3 Aug 2022 20:50:39 +0200 Subject: [PATCH 05/24] fixed include, cleaned comments and indentation --- components/shader/shadermanager.cpp | 61 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index ec0e30c97a..621f59b072 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -5,7 +5,8 @@ #include #include #include -#include +#include +#include #include #include @@ -406,7 +407,6 @@ namespace Shader std::filesystem::path pathShaderToTest = (shader.first); std::filesystem::file_time_type write_time = std::filesystem::last_write_time(pathShaderToTest); - //Log(Debug::Info) << std::format("{} write time is {} compared to {} ", shader.first, write_time, mLastAutoRecompileTime); if (write_time.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch()) { for (const ShaderManager:: MapKey& descriptor : shader.second) @@ -416,38 +416,35 @@ namespace Shader ShaderManager::TemplateMap::iterator templateIt = Manager.mShaderTemplates.find(templateName); //Can't be Null, if we're here it means the template was added std::set insertedPaths; + std::filesystem::path path = (std::filesystem::path(Manager.mPath) / templateName); + std::ifstream stream; + stream.open(path); + if (stream.fail()) { - std::filesystem::path path = (std::filesystem::path(Manager.mPath) / templateName); - std::ifstream stream; - stream.open(path); - if (stream.fail()) - { - Log(Debug::Error) << "Failed to open " << path.string(); - } - std::stringstream buffer; - buffer << stream.rdbuf(); - - // parse includes - int fileNumber = 1; - std::string source = buffer.str(); - if (!addLineDirectivesAfterConditionalBlocks(source) - || !parseIncludes(std::filesystem::path(Manager.mPath), source, templateName, fileNumber, insertedPaths)) - { - break; - } - templateIt->second = source; - - //if (shaderIt == Manager.mShaders.end()) - { - std::string shaderSource = templateIt->second; - std::vector linkedShaderNames; - if (!Manager.createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, descriptor.second)) - { - break; - } - shaderIt->second->setShaderSource(shaderSource); - } + Log(Debug::Error) << "Failed to open " << path.string(); } + std::stringstream buffer; + buffer << stream.rdbuf(); + + // parse includes + int fileNumber = 1; + std::string source = buffer.str(); + if (!addLineDirectivesAfterConditionalBlocks(source) + || !parseIncludes(std::filesystem::path(Manager.mPath), source, templateName, fileNumber, insertedPaths)) + { + break; + } + templateIt->second = source; + + + std::string shaderSource = templateIt->second; + std::vector linkedShaderNames; + if (!Manager.createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, descriptor.second)) + { + break; + } + shaderIt->second->setShaderSource(shaderSource); + } } } From fc8838c7dddc7742481d5e3f9dd3c5a63aa283b3 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 3 Aug 2022 23:05:35 +0200 Subject: [PATCH 06/24] Renamed lua binding, and use action to avoid concurrency issue --- apps/openmw/mwlua/debugbindings.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwlua/debugbindings.cpp b/apps/openmw/mwlua/debugbindings.cpp index 189d44cd86..d8a257a032 100644 --- a/apps/openmw/mwlua/debugbindings.cpp +++ b/apps/openmw/mwlua/debugbindings.cpp @@ -52,12 +52,18 @@ namespace MWLua api["triggerShaderReload"] = [context]() { - MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().triggerShaderReload(); + context.mLuaManager->addAction([] + { + MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().triggerShaderReload(); + }); }; - api["togggleShaderHotReload"] = [context](bool value) + api["setShaderHotReloadEnabled"] = [context](bool value) { - MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().setHotReloadEnabled(value); + context.mLuaManager->addAction([value] + { + MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().setHotReloadEnabled(value); + }); }; return LuaUtil::makeReadOnly(api); From aa51d6de2aac22a9dc2496af71e89dbe2b552637 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 00:14:53 +0200 Subject: [PATCH 07/24] Missing chrono include ? --- components/shader/shadermanager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 621f59b072..e7d9ddb33b 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include From 68d0698924c6d57394c94b43d150d0af02d881da Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 09:09:26 +0200 Subject: [PATCH 08/24] Fixed cyclical included check --- components/shader/shadermanager.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index e7d9ddb33b..336d47e68f 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -74,11 +74,12 @@ namespace Shader // Recursively replaces include statements with the actual source of the included files. // Adjusts #line statements accordingly and detects cyclic includes. - // includingFiles is the set of files that include this file directly or indirectly, and is intentionally not a reference to allow automatic cleanup. - static bool parseIncludes(const std::filesystem::path& shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set& includingFiles) + // cycleIncludeChecker is the set of files that include this file directly or indirectly, and is intentionally not a reference to allow automatic cleanup. + static bool parseIncludes(const std::filesystem::path& shaderPath, std::string& source, const std::string& fileName, int& fileNumber, std::set cycleIncludeChecker,std::set& includedFiles) { + includedFiles.insert(shaderPath / fileName); // An include is cyclic if it is being included by itself - if (includingFiles.insert(shaderPath/fileName).second == false) + if (cycleIncludeChecker.insert(shaderPath/fileName).second == false) { Log(Debug::Error) << "Shader " << fileName << " error: Detected cyclic #includes"; return false; @@ -135,7 +136,7 @@ namespace Shader buffer << includeFstream.rdbuf(); std::string stringRepresentation = buffer.str(); if (!addLineDirectivesAfterConditionalBlocks(stringRepresentation) - || !parseIncludes(shaderPath, stringRepresentation, includeFilename, fileNumber, includingFiles)) + || !parseIncludes(shaderPath, stringRepresentation, includeFilename, fileNumber, cycleIncludeChecker, includedFiles)) { Log(Debug::Error) << "In file included from " << fileName << "." << lineNumber; return false; @@ -431,7 +432,7 @@ namespace Shader int fileNumber = 1; std::string source = buffer.str(); if (!addLineDirectivesAfterConditionalBlocks(source) - || !parseIncludes(std::filesystem::path(Manager.mPath), source, templateName, fileNumber, insertedPaths)) + || !parseIncludes(std::filesystem::path(Manager.mPath), source, templateName, fileNumber, {}, insertedPaths)) { break; } @@ -478,7 +479,7 @@ namespace Shader int fileNumber = 1; std::string source = buffer.str(); if (!addLineDirectivesAfterConditionalBlocks(source) - || !parseIncludes(std::filesystem::path(mPath), source, templateName, fileNumber, insertedPaths)) + || !parseIncludes(std::filesystem::path(mPath), source, templateName, fileNumber, {}, insertedPaths)) return nullptr; templateIt = mShaderTemplates.insert(std::make_pair(templateName, source)).first; From b6d7293a12c1e59e2eb76bd9a7038a9def2f8dd5 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 09:13:25 +0200 Subject: [PATCH 09/24] Removed weird lines that I thought were necessary to please the compiler --- components/shader/shadermanager.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 336d47e68f..62b2517a1d 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -381,18 +381,7 @@ namespace Shader { for (const std::filesystem::path& file : shaderFiles) { - KeysHolder* shaderSet_ptr; - auto found = mShaderFiles.find(file.string()); - if (found != mShaderFiles.end()) //Apparently there is an issue that prevents me from using operator[] - { - shaderSet_ptr = &found->second; - } - else - { - shaderSet_ptr = &mShaderFiles.insert(std::make_pair<>(file.string(), KeysHolder())).first->second; - } - auto& shaderSet = *shaderSet_ptr; - shaderSet.insert(std::make_pair( templateName, defines )); + mShaderFiles[file.string()].insert(std::make_pair(templateName, defines)); } } From 9a475b0c977ee5ecf16be7a995022783fb923d07 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 09:19:41 +0200 Subject: [PATCH 10/24] fixed blank lines and missing breaks --- components/shader/shadermanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 62b2517a1d..7d45a0c6d1 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -365,12 +365,12 @@ namespace Shader struct HotReloadManager { - - - std::filesystem::file_time_type mLastAutoRecompileTime; using KeysHolder = std::set; + std::unordered_map mShaderFiles; + std::filesystem::file_time_type mLastAutoRecompileTime; bool mHotReloadEnabled; + HotReloadManager() { mHotReloadEnabled = false; From cdd95f78896b5ebdc1828c99c0ed6eb3059dcac1 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 09:25:25 +0200 Subject: [PATCH 11/24] replaced empty function body by default --- components/shader/shadermanager.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 7d45a0c6d1..a0b4248c55 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -22,9 +22,7 @@ namespace Shader mHotReloadManager = std::make_unique(); } - ShaderManager::~ShaderManager() - { - } + ShaderManager::~ShaderManager() = default; void ShaderManager::setShaderPath(const std::string &path) { From a1c8dc9d4503ee419250ed0fffcd13b2d19e138d Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 09:50:02 +0200 Subject: [PATCH 12/24] C++17 compat ? --- components/shader/shadermanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index a0b4248c55..5a21c67510 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -372,7 +372,7 @@ namespace Shader HotReloadManager() { mHotReloadEnabled = false; - mLastAutoRecompileTime = std::chrono::file_clock::now(); + mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now(); } void addShaderFiles(std::set& shaderFiles,const osg::ref_ptr& shader,const std::string& templateName,const ShaderManager::DefineMap& defines ) @@ -437,7 +437,7 @@ namespace Shader } } } - mLastAutoRecompileTime = std::chrono::file_clock::now(); + mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now(); } }; From 7b78bf4b668a616a4cfc9b37755f5f286d1010fc Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 12:46:39 +0200 Subject: [PATCH 13/24] Fix files with different defines weren't added to the hot reload manager --- components/shader/shadermanager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 5a21c67510..3feb9d5656 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -490,6 +490,13 @@ namespace Shader // Append shader source filename for debugging. static unsigned int counter = 0; shader->setName(Misc::StringUtils::format("%u %s", counter++, templateName)); + + if (insertedPaths.size() == 0) + { + int fileNumber = 1; + parseIncludes(std::filesystem::path(mPath), shaderSource, templateName, fileNumber, {}, insertedPaths); + } + mHotReloadManager->addShaderFiles(insertedPaths, shader, templateName, defines); lock.unlock(); From cc9d436413559379ed1a82078e3434a32f2c4145 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 13:00:32 +0200 Subject: [PATCH 14/24] includes now work when the same shader has different defines --- components/shader/shadermanager.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 3feb9d5656..44a08ddfa3 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -366,6 +366,7 @@ namespace Shader using KeysHolder = std::set; std::unordered_map mShaderFiles; + std::unordered_map> templateIncludedFiles; std::filesystem::file_time_type mLastAutoRecompileTime; bool mHotReloadEnabled; @@ -375,8 +376,9 @@ namespace Shader mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now(); } - void addShaderFiles(std::set& shaderFiles,const osg::ref_ptr& shader,const std::string& templateName,const ShaderManager::DefineMap& defines ) + void addShaderFiles(const std::string& templateName,const ShaderManager::DefineMap& defines ) { + const std::set& shaderFiles = templateIncludedFiles[templateName]; for (const std::filesystem::path& file : shaderFiles) { mShaderFiles[file.string()].insert(std::make_pair(templateName, defines)); @@ -468,7 +470,7 @@ namespace Shader if (!addLineDirectivesAfterConditionalBlocks(source) || !parseIncludes(std::filesystem::path(mPath), source, templateName, fileNumber, {}, insertedPaths)) return nullptr; - + mHotReloadManager->templateIncludedFiles[templateName] = insertedPaths; templateIt = mShaderTemplates.insert(std::make_pair(templateName, source)).first; } @@ -491,13 +493,7 @@ namespace Shader static unsigned int counter = 0; shader->setName(Misc::StringUtils::format("%u %s", counter++, templateName)); - if (insertedPaths.size() == 0) - { - int fileNumber = 1; - parseIncludes(std::filesystem::path(mPath), shaderSource, templateName, fileNumber, {}, insertedPaths); - } - - mHotReloadManager->addShaderFiles(insertedPaths, shader, templateName, defines); + mHotReloadManager->addShaderFiles(templateName, defines); lock.unlock(); getLinkedShaders(shader, linkedShaderNames, defines); From 15751c57a0e16e600146aa7b2d5a014e8a7e9cb8 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 13:36:24 +0200 Subject: [PATCH 15/24] Lua debug api doc --- files/lua_api/openmw/debug.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/files/lua_api/openmw/debug.lua b/files/lua_api/openmw/debug.lua index 1641489317..811bc4d471 100644 --- a/files/lua_api/openmw/debug.lua +++ b/files/lua_api/openmw/debug.lua @@ -41,4 +41,12 @@ -- @function [parent=#debug] setNavMeshRenderMode -- @param #NAV_MESH_RENDER_MODE value +--- +-- Enable/disable automatic reload of modified shaders +-- @function [parent=#debug] setShaderHotReloadEnabled +-- @param #bool value + +--- +-- To reload modified shaders +-- @function [parent=#debug] triggerShaderReload return nil From 3ab0a9915425e2be4da4efe59d7815f0b3a6882a Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Thu, 4 Aug 2022 13:37:12 +0200 Subject: [PATCH 16/24] Hot reload done only once every 200 ms, no point in beeing faster it may also help with bugs where the file is still locked and can't be opened --- components/shader/shadermanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 44a08ddfa3..223ca9cd02 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -387,7 +387,8 @@ namespace Shader void update(ShaderManager& Manager) { - if (mHotReloadEnabled) + auto timeSinceLastCheckMillis = std::chrono::duration_cast(std::filesystem::file_time_type::clock::now() - mLastAutoRecompileTime); + if (mHotReloadEnabled && timeSinceLastCheckMillis.count() > 200) reloadTouchedShaders(Manager); } From df69fc76597ac3c9cb6add9fea3e62d0dabc5a77 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sun, 7 Aug 2022 00:19:19 +0200 Subject: [PATCH 17/24] Post processing shaders now use the same lua commands, no more launcher option to enable live reload --- apps/launcher/advancedpage.cpp | 3 --- apps/openmw/mwlua/debugbindings.cpp | 10 ++++++++-- apps/openmw/mwrender/postprocessor.cpp | 12 ++++++++++-- apps/openmw/mwrender/postprocessor.hpp | 5 +++++ files/ui/advancedpage.ui | 13 ------------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index ff04a846ff..17ac649dce 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -152,7 +152,6 @@ bool Launcher::AdvancedPage::loadSettings() connect(postprocessEnabledCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotPostProcessToggled(bool))); loadSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing"); - loadSettingBool(postprocessLiveReloadCheckBox, "live reload", "Post Processing"); loadSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing"); postprocessHDRTimeComboBox->setValue(Settings::Manager::getDouble("auto exposure speed", "Post Processing")); @@ -309,7 +308,6 @@ void Launcher::AdvancedPage::saveSettings() saveSettingBool(nightDaySwitchesCheckBox, "day night switches", "Game"); saveSettingBool(postprocessEnabledCheckBox, "enabled", "Post Processing"); - saveSettingBool(postprocessLiveReloadCheckBox, "live reload", "Post Processing"); saveSettingBool(postprocessTransparentPostpassCheckBox, "transparent postpass", "Post Processing"); double hdrExposureTime = postprocessHDRTimeComboBox->value(); if (hdrExposureTime != Settings::Manager::getDouble("auto exposure speed", "Post Processing")) @@ -466,7 +464,6 @@ void Launcher::AdvancedPage::slotAnimSourcesToggled(bool checked) void Launcher::AdvancedPage::slotPostProcessToggled(bool checked) { - postprocessLiveReloadCheckBox->setEnabled(checked); postprocessTransparentPostpassCheckBox->setEnabled(checked); postprocessHDRTimeComboBox->setEnabled(checked); postprocessHDRTimeLabel->setEnabled(checked); diff --git a/apps/openmw/mwlua/debugbindings.cpp b/apps/openmw/mwlua/debugbindings.cpp index d8a257a032..d51ab1897b 100644 --- a/apps/openmw/mwlua/debugbindings.cpp +++ b/apps/openmw/mwlua/debugbindings.cpp @@ -5,6 +5,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwrender/renderingmanager.hpp" +#include "../mwrender/postprocessor.hpp" #include #include @@ -54,7 +55,10 @@ namespace MWLua { context.mLuaManager->addAction([] { - MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().triggerShaderReload(); + auto world = MWBase::Environment::get().getWorld(); + + world->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().triggerShaderReload(); + world->getPostProcessor()->triggerShaderReload(); }); }; @@ -62,7 +66,9 @@ namespace MWLua { context.mLuaManager->addAction([value] { - MWBase::Environment::get().getWorld()->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().setHotReloadEnabled(value); + auto world = MWBase::Environment::get().getWorld(); + world->getRenderingManager()->getResourceSystem()->getSceneManager()->getShaderManager().setHotReloadEnabled(value); + world->getPostProcessor()->mEnableLiveReload = value; }); }; diff --git a/apps/openmw/mwrender/postprocessor.cpp b/apps/openmw/mwrender/postprocessor.cpp index 4902dc8ef8..1946efb145 100644 --- a/apps/openmw/mwrender/postprocessor.cpp +++ b/apps/openmw/mwrender/postprocessor.cpp @@ -102,6 +102,7 @@ namespace MWRender { PostProcessor::PostProcessor(RenderingManager& rendering, osgViewer::Viewer* viewer, osg::Group* rootNode, const VFS::Manager* vfs) : osg::Group() + , mEnableLiveReload(false) , mRootNode(rootNode) , mSamples(Settings::Manager::getInt("antialiasing", "Video")) , mDirty(false) @@ -109,6 +110,7 @@ namespace MWRender , mRendering(rendering) , mViewer(viewer) , mVFS(vfs) + , mTriggerShaderReload(false) , mReload(false) , mEnabled(false) , mUsePostProcessing(false) @@ -370,10 +372,11 @@ namespace MWRender void PostProcessor::updateLiveReload() { - static const bool liveReload = Settings::Manager::getBool("live reload", "Post Processing"); - if (!liveReload) + if (!mEnableLiveReload && !mTriggerShaderReload) return; + mTriggerShaderReload = false;//Done only once + for (auto& technique : mTechniques) { if (technique->getStatus() == fx::Technique::Status::File_Not_exists) @@ -890,5 +893,10 @@ namespace MWRender return Stereo::Manager::instance().eyeResolution().y(); return mHeight; } + + void PostProcessor::triggerShaderReload() + { + mTriggerShaderReload = true; + } } diff --git a/apps/openmw/mwrender/postprocessor.hpp b/apps/openmw/mwrender/postprocessor.hpp index 2fa3e5622a..fc20340a29 100644 --- a/apps/openmw/mwrender/postprocessor.hpp +++ b/apps/openmw/mwrender/postprocessor.hpp @@ -180,6 +180,10 @@ namespace MWRender int renderWidth() const; int renderHeight() const; + void triggerShaderReload(); + + bool mEnableLiveReload; + private: void populateTechniqueFiles(); @@ -225,6 +229,7 @@ namespace MWRender osgViewer::Viewer* mViewer; const VFS::Manager* mVFS; + bool mTriggerShaderReload; bool mReload; bool mEnabled; bool mUsePostProcessing; diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index bcf710ffea..82add7b6b6 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -670,19 +670,6 @@ 20 - - - - false - - - <html><head/><body><p>Debug Mode. Automatically reload active shaders when they are modified on filesystem.</p></body></html> - - - Live reload - - - From c71f3508df56131774055c768019b51be5631c67 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sun, 7 Aug 2022 00:26:29 +0200 Subject: [PATCH 18/24] changed overview.rst of post processing --- docs/source/reference/postprocessing/overview.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/reference/postprocessing/overview.rst b/docs/source/reference/postprocessing/overview.rst index 275461bfd2..4384d82896 100644 --- a/docs/source/reference/postprocessing/overview.rst +++ b/docs/source/reference/postprocessing/overview.rst @@ -45,8 +45,9 @@ Hot Reloading ============= It is possible to modify a shader without restarting OpenMW, :ref:`live reload` -must be enabled in ``settings.cfg``. Whenever a file is modified and saved, the -shader will automatically reload in game. This allows shaders to be written in a -text editor you are comfortable with. The only restriction is that the VFS is not -aware of new files or changes in non-shader files, so new shaders and localization -strings can not be used. +must be enabled by using the lua command `debug.setShaderHotReloadEnabled(true)`. +Whenever a file is modified and saved, the shader will automatically reload in game. +You can also trigger a single reload using `debug.triggerShaderReload()` +This allows shaders to be written in a text editor you are comfortable with. +The only restriction is that the VFS is not aware of new files or changes in non-shader files, +so new shaders and localization strings can not be used. From 603b30e117f48e26b23618f2f79d6246bb605bed Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sun, 7 Aug 2022 22:56:32 +0200 Subject: [PATCH 19/24] Added some variable names to make it clearer what their function was avoid having lost of ->first and ->second that aren't meaningfull --- components/shader/shadermanager.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 223ca9cd02..568abd5b39 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -394,19 +394,18 @@ namespace Shader void reloadTouchedShaders(ShaderManager& Manager) { - for (auto& shader : mShaderFiles) + for (auto& [pathShaderToTest, shaderKeys]: mShaderFiles) { - std::filesystem::path pathShaderToTest = (shader.first); std::filesystem::file_time_type write_time = std::filesystem::last_write_time(pathShaderToTest); if (write_time.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch()) { - for (const ShaderManager:: MapKey& descriptor : shader.second) + for (const auto& [templateName, shaderDefines]: shaderKeys) { - const std::string& templateName = descriptor.first; - ShaderManager::ShaderMap::iterator shaderIt = Manager.mShaders.find(std::make_pair(templateName, descriptor.second)); + ShaderManager::ShaderMap::iterator shaderIt = Manager.mShaders.find(std::make_pair(templateName, shaderDefines)); ShaderManager::TemplateMap::iterator templateIt = Manager.mShaderTemplates.find(templateName); //Can't be Null, if we're here it means the template was added + std::string& shaderSource = templateIt->second; std::set insertedPaths; std::filesystem::path path = (std::filesystem::path(Manager.mPath) / templateName); std::ifstream stream; @@ -426,12 +425,10 @@ namespace Shader { break; } - templateIt->second = source; + shaderSource = source; - - std::string shaderSource = templateIt->second; std::vector linkedShaderNames; - if (!Manager.createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, descriptor.second)) + if (!Manager.createSourceFromTemplate(shaderSource, linkedShaderNames, templateName, shaderDefines)) { break; } From decfbc5387fce16194a9678a2e25eb3ef2d50fe6 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Fri, 12 Aug 2022 18:26:04 +0200 Subject: [PATCH 20/24] Fix threading issues --- apps/openmw/mwrender/renderingmanager.cpp | 4 +++- components/shader/shadermanager.cpp | 26 +++++++++++++++++------ components/shader/shadermanager.hpp | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 80003c2b7e..50ed0b56cb 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -901,7 +901,9 @@ namespace MWRender void RenderingManager::update(float dt, bool paused) { reportStats(); - mResourceSystem->getSceneManager()->getShaderManager().update(); + + mResourceSystem->getSceneManager()->getShaderManager().update(*mViewer); + float rainIntensity = mSky->getPrecipitationAlpha(); mWater->setRainIntensity(rainIntensity); diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 568abd5b39..3a3bf971e9 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -369,9 +369,11 @@ namespace Shader std::unordered_map> templateIncludedFiles; std::filesystem::file_time_type mLastAutoRecompileTime; bool mHotReloadEnabled; + bool mTriggerReload; HotReloadManager() { + mTriggerReload = false; mHotReloadEnabled = false; mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now(); } @@ -385,21 +387,29 @@ namespace Shader } } - void update(ShaderManager& Manager) + void update(ShaderManager& Manager,osgViewer::Viewer& viewer) { auto timeSinceLastCheckMillis = std::chrono::duration_cast(std::filesystem::file_time_type::clock::now() - mLastAutoRecompileTime); - if (mHotReloadEnabled && timeSinceLastCheckMillis.count() > 200) - reloadTouchedShaders(Manager); + if ((mHotReloadEnabled && timeSinceLastCheckMillis.count() > 200) || mTriggerReload == true) + { + reloadTouchedShaders(Manager, viewer); + } + mTriggerReload = false; } - void reloadTouchedShaders(ShaderManager& Manager) + void reloadTouchedShaders(ShaderManager& Manager, osgViewer::Viewer& viewer) { + bool threadsRunningTostop = false; for (auto& [pathShaderToTest, shaderKeys]: mShaderFiles) { std::filesystem::file_time_type write_time = std::filesystem::last_write_time(pathShaderToTest); if (write_time.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch()) { + threadsRunningTostop = viewer.areThreadsRunning(); + if (threadsRunningTostop) + viewer.stopThreading(); + for (const auto& [templateName, shaderDefines]: shaderKeys) { ShaderManager::ShaderMap::iterator shaderIt = Manager.mShaders.find(std::make_pair(templateName, shaderDefines)); @@ -437,6 +447,8 @@ namespace Shader } } } + if (threadsRunningTostop) + viewer.startThreading(); mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now(); } }; @@ -625,9 +637,9 @@ namespace Shader return unit; } - void ShaderManager::update() + void ShaderManager::update(osgViewer::Viewer& viewer) { - mHotReloadManager->update(*this); + mHotReloadManager->update(*this, viewer); } void ShaderManager::setHotReloadEnabled(bool value) @@ -637,7 +649,7 @@ namespace Shader void ShaderManager::triggerShaderReload() { - mHotReloadManager->reloadTouchedShaders(*this); + mHotReloadManager->mTriggerReload = true; } } diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index 50bc101ed6..8aa299c73b 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -69,7 +69,7 @@ namespace Shader int reserveGlobalTextureUnits(Slot slot); - void update(); + void update(osgViewer::Viewer& viewer); void setHotReloadEnabled(bool value); void triggerShaderReload(); private: From b14cc673bccea422f2d8bba516d3ee8457734c59 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Fri, 12 Aug 2022 18:47:29 +0200 Subject: [PATCH 21/24] adds missing decleration --- components/shader/shadermanager.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/shader/shadermanager.hpp b/components/shader/shadermanager.hpp index 8aa299c73b..50c430637e 100644 --- a/components/shader/shadermanager.hpp +++ b/components/shader/shadermanager.hpp @@ -13,6 +13,10 @@ #include #include +namespace osgViewer { + class Viewer; +} + namespace Shader { struct HotReloadManager; From 16a4b5716b70d4b4723eb77956791572538ce75f Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Fri, 12 Aug 2022 18:52:31 +0200 Subject: [PATCH 22/24] adds missing include --- components/shader/shadermanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 3a3bf971e9..64b734f526 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -9,7 +9,7 @@ #include #include #include - +#include #include #include #include From 166717d6016e1c04f826caf71a37fe45dc8a50dd Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sat, 13 Aug 2022 00:34:01 +0200 Subject: [PATCH 23/24] Makes sure threads are only stopped once ,and that they will be re-started --- components/shader/shadermanager.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 64b734f526..04b48ea4b4 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -406,9 +406,12 @@ namespace Shader std::filesystem::file_time_type write_time = std::filesystem::last_write_time(pathShaderToTest); if (write_time.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch()) { - threadsRunningTostop = viewer.areThreadsRunning(); - if (threadsRunningTostop) - viewer.stopThreading(); + if (!threadsRunningTostop) + { + threadsRunningTostop = viewer.areThreadsRunning(); + if (threadsRunningTostop) + viewer.stopThreading(); + } for (const auto& [templateName, shaderDefines]: shaderKeys) { From 25c1f0ca16c69d8e90ac8fcefcb29d272137b191 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sun, 21 Aug 2022 09:18:08 +0200 Subject: [PATCH 24/24] Renamed variable to fix case issue --- components/shader/shadermanager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 04b48ea4b4..b76a98411d 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -399,17 +399,17 @@ namespace Shader void reloadTouchedShaders(ShaderManager& Manager, osgViewer::Viewer& viewer) { - bool threadsRunningTostop = false; + bool threadsRunningToStop = false; for (auto& [pathShaderToTest, shaderKeys]: mShaderFiles) { std::filesystem::file_time_type write_time = std::filesystem::last_write_time(pathShaderToTest); if (write_time.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch()) { - if (!threadsRunningTostop) + if (!threadsRunningToStop) { - threadsRunningTostop = viewer.areThreadsRunning(); - if (threadsRunningTostop) + threadsRunningToStop = viewer.areThreadsRunning(); + if (threadsRunningToStop) viewer.stopThreading(); } @@ -450,7 +450,7 @@ namespace Shader } } } - if (threadsRunningTostop) + if (threadsRunningToStop) viewer.startThreading(); mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now(); }