mirror of https://github.com/OpenMW/openmw
Merge branch 'fix_std_23' into 'master'
Fix compilation with -std=23 See merge request OpenMW/openmw!5019
This commit is contained in:
commit
1223ca0228
|
|
@ -9,6 +9,7 @@
|
|||
#include <regex>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <system_error>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <osg/Program>
|
||||
|
|
@ -73,22 +74,6 @@ namespace
|
|||
+= static_cast<int>(std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n'));
|
||||
return lineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
|
||||
ShaderManager::ShaderManager()
|
||||
{
|
||||
mHotReloadManager = std::make_unique<HotReloadManager>();
|
||||
}
|
||||
|
||||
ShaderManager::~ShaderManager() = default;
|
||||
|
||||
void ShaderManager::setShaderPath(const std::filesystem::path& path)
|
||||
{
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
bool addLineDirectivesAfterConditionalBlocks(std::string& source)
|
||||
{
|
||||
|
|
@ -121,7 +106,7 @@ namespace Shader
|
|||
// Adjusts #line statements accordingly and detects cyclic includes.
|
||||
// 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,
|
||||
bool parseIncludes(const std::filesystem::path& shaderPath, std::string& source, const std::string& fileName,
|
||||
int& fileNumber, std::set<std::filesystem::path> cycleIncludeChecker,
|
||||
std::set<std::filesystem::path>& includedFiles)
|
||||
{
|
||||
|
|
@ -169,7 +154,8 @@ namespace Shader
|
|||
includeFstream.open(includePath);
|
||||
if (includeFstream.fail())
|
||||
{
|
||||
Log(Debug::Error) << "Shader " << fileName << " error: Failed to open include " << includePath;
|
||||
Log(Debug::Error) << "Shader " << fileName << " error: Failed to open include " << includePath << ": "
|
||||
<< std::generic_category().message(errno);
|
||||
return false;
|
||||
}
|
||||
int includedFileNumber = fileNumber++;
|
||||
|
|
@ -193,6 +179,127 @@ namespace Shader
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
struct HotReloadManager
|
||||
{
|
||||
using KeysHolder = std::set<ShaderManager::MapKey>;
|
||||
|
||||
std::unordered_map<std::string, KeysHolder> mShaderFiles;
|
||||
std::unordered_map<std::string, std::set<std::filesystem::path>> templateIncludedFiles;
|
||||
std::filesystem::file_time_type mLastAutoRecompileTime;
|
||||
bool mHotReloadEnabled;
|
||||
bool mTriggerReload;
|
||||
|
||||
HotReloadManager()
|
||||
{
|
||||
mTriggerReload = false;
|
||||
mHotReloadEnabled = false;
|
||||
mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now();
|
||||
}
|
||||
|
||||
void addShaderFiles(const std::string& templateName, const ShaderManager::DefineMap& defines)
|
||||
{
|
||||
const std::set<std::filesystem::path>& shaderFiles = templateIncludedFiles[templateName];
|
||||
for (const std::filesystem::path& file : shaderFiles)
|
||||
{
|
||||
mShaderFiles[Files::pathToUnicodeString(file)].insert(std::make_pair(templateName, defines));
|
||||
}
|
||||
}
|
||||
|
||||
void update(ShaderManager& manager, osgViewer::Viewer& viewer)
|
||||
{
|
||||
auto timeSinceLastCheckMillis = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::filesystem::file_time_type::clock::now() - mLastAutoRecompileTime);
|
||||
if ((mHotReloadEnabled && timeSinceLastCheckMillis.count() > 200) || mTriggerReload == true)
|
||||
{
|
||||
reloadTouchedShaders(manager, viewer);
|
||||
}
|
||||
mTriggerReload = false;
|
||||
}
|
||||
|
||||
void reloadTouchedShaders(ShaderManager& manager, osgViewer::Viewer& viewer)
|
||||
{
|
||||
bool threadsRunningToStop = false;
|
||||
for (auto& [pathShaderToTest, shaderKeys] : mShaderFiles)
|
||||
{
|
||||
const std::filesystem::file_time_type writeTime = std::filesystem::last_write_time(pathShaderToTest);
|
||||
if (writeTime.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch())
|
||||
{
|
||||
if (!threadsRunningToStop)
|
||||
{
|
||||
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));
|
||||
if (shaderIt == manager.mShaders.end())
|
||||
{
|
||||
Log(Debug::Error) << "Failed to find shader " << templateName;
|
||||
continue;
|
||||
}
|
||||
|
||||
ShaderManager::TemplateMap::iterator templateIt = manager.mShaderTemplates.find(
|
||||
templateName); // Can't be Null, if we're here it means the template was added
|
||||
assert(templateIt != manager.mShaderTemplates.end());
|
||||
std::string& shaderSource = templateIt->second;
|
||||
std::set<std::filesystem::path> 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 << ": " << std::generic_category().message(errno);
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
shaderSource = std::move(source);
|
||||
|
||||
std::vector<std::string> linkedShaderNames;
|
||||
if (!manager.createSourceFromTemplate(
|
||||
shaderSource, linkedShaderNames, templateName, shaderDefines))
|
||||
{
|
||||
break;
|
||||
}
|
||||
shaderIt->second->setShaderSource(shaderSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (threadsRunningToStop)
|
||||
viewer.startThreading();
|
||||
mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now();
|
||||
}
|
||||
};
|
||||
|
||||
ShaderManager::ShaderManager()
|
||||
{
|
||||
mHotReloadManager = std::make_unique<HotReloadManager>();
|
||||
}
|
||||
|
||||
ShaderManager::~ShaderManager() = default;
|
||||
|
||||
void ShaderManager::setShaderPath(const std::filesystem::path& path)
|
||||
{
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos)
|
||||
{
|
||||
|
|
@ -397,110 +504,6 @@ namespace Shader
|
|||
return true;
|
||||
}
|
||||
|
||||
struct HotReloadManager
|
||||
{
|
||||
using KeysHolder = std::set<ShaderManager::MapKey>;
|
||||
|
||||
std::unordered_map<std::string, KeysHolder> mShaderFiles;
|
||||
std::unordered_map<std::string, std::set<std::filesystem::path>> templateIncludedFiles;
|
||||
std::filesystem::file_time_type mLastAutoRecompileTime;
|
||||
bool mHotReloadEnabled;
|
||||
bool mTriggerReload;
|
||||
|
||||
HotReloadManager()
|
||||
{
|
||||
mTriggerReload = false;
|
||||
mHotReloadEnabled = false;
|
||||
mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now();
|
||||
}
|
||||
|
||||
void addShaderFiles(const std::string& templateName, const ShaderManager::DefineMap& defines)
|
||||
{
|
||||
const std::set<std::filesystem::path>& shaderFiles = templateIncludedFiles[templateName];
|
||||
for (const std::filesystem::path& file : shaderFiles)
|
||||
{
|
||||
mShaderFiles[Files::pathToUnicodeString(file)].insert(std::make_pair(templateName, defines));
|
||||
}
|
||||
}
|
||||
|
||||
void update(ShaderManager& manager, osgViewer::Viewer& viewer)
|
||||
{
|
||||
auto timeSinceLastCheckMillis = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::filesystem::file_time_type::clock::now() - mLastAutoRecompileTime);
|
||||
if ((mHotReloadEnabled && timeSinceLastCheckMillis.count() > 200) || mTriggerReload == true)
|
||||
{
|
||||
reloadTouchedShaders(manager, viewer);
|
||||
}
|
||||
mTriggerReload = false;
|
||||
}
|
||||
|
||||
void reloadTouchedShaders(ShaderManager& manager, osgViewer::Viewer& viewer)
|
||||
{
|
||||
bool threadsRunningToStop = false;
|
||||
for (auto& [pathShaderToTest, shaderKeys] : mShaderFiles)
|
||||
{
|
||||
const std::filesystem::file_time_type writeTime = std::filesystem::last_write_time(pathShaderToTest);
|
||||
if (writeTime.time_since_epoch() > mLastAutoRecompileTime.time_since_epoch())
|
||||
{
|
||||
if (!threadsRunningToStop)
|
||||
{
|
||||
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));
|
||||
if (shaderIt == manager.mShaders.end())
|
||||
{
|
||||
Log(Debug::Error) << "Failed to find shader " << templateName;
|
||||
continue;
|
||||
}
|
||||
|
||||
ShaderManager::TemplateMap::iterator templateIt = manager.mShaderTemplates.find(
|
||||
templateName); // Can't be Null, if we're here it means the template was added
|
||||
assert(templateIt != manager.mShaderTemplates.end());
|
||||
std::string& shaderSource = templateIt->second;
|
||||
std::set<std::filesystem::path> 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 " << Files::pathToUnicodeString(path);
|
||||
}
|
||||
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;
|
||||
}
|
||||
shaderSource = std::move(source);
|
||||
|
||||
std::vector<std::string> linkedShaderNames;
|
||||
if (!manager.createSourceFromTemplate(
|
||||
shaderSource, linkedShaderNames, templateName, shaderDefines))
|
||||
{
|
||||
break;
|
||||
}
|
||||
shaderIt->second->setShaderSource(shaderSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (threadsRunningToStop)
|
||||
viewer.startThreading();
|
||||
mLastAutoRecompileTime = std::filesystem::file_time_type::clock::now();
|
||||
}
|
||||
};
|
||||
|
||||
osg::ref_ptr<osg::Shader> ShaderManager::getShader(
|
||||
std::string templateName, const ShaderManager::DefineMap& defines, std::optional<osg::Shader::Type> type)
|
||||
{
|
||||
|
|
@ -522,7 +525,7 @@ namespace Shader
|
|||
stream.open(path);
|
||||
if (stream.fail())
|
||||
{
|
||||
Log(Debug::Error) << "Failed to open " << path;
|
||||
Log(Debug::Error) << "Failed to open shader " << path << ": " << std::generic_category().message(errno);
|
||||
return nullptr;
|
||||
}
|
||||
std::stringstream buffer;
|
||||
|
|
|
|||
Loading…
Reference in New Issue