Merge branch 'fix_std_23' into 'master'

Fix compilation with -std=23

See merge request OpenMW/openmw!5019
This commit is contained in:
Alexei Kotov 2025-12-06 04:10:49 +03:00
commit 1223ca0228
1 changed files with 126 additions and 123 deletions

View File

@ -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;