mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-13 16:13:06 +00:00
Fix compilation with -std=23
/usr/include/c++/15.2.1/bits/unique_ptr.h: In instantiation of ‘constexpr std::__detail::__unique_ptr_t<_Tp> std::make_unique(_Args&& ...) [with _Tp = Shader::HotReloadManager; _Args = {}; __detail::__unique_ptr_t<_Tp> = __detail::__unique_ptr_t<Shader::HotReloadManager>]’:
/home/elsid/dev/openmw/components/shader/shadermanager.cpp:83:63: required from here
83 | mHotReloadManager = std::make_unique<HotReloadManager>();
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
/usr/include/c++/15.2.1/bits/unique_ptr.h:1085:30: error: invalid use of incomplete type ‘struct Shader::HotReloadManager’
1085 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
components/shader/shadermanager.hpp:24:12: note: forward declaration of ‘struct Shader::HotReloadManager’
24 | struct HotReloadManager;
| ^~~~~~~~~~~~~~~~
This commit is contained in:
parent
cef1bb1219
commit
402e1b3096
1 changed files with 122 additions and 123 deletions
|
|
@ -74,22 +74,6 @@ namespace
|
||||||
+= static_cast<int>(std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n'));
|
+= static_cast<int>(std::count(source.begin() + lineDirectivePosition, source.begin() + foundPos, '\n'));
|
||||||
return lineNumber;
|
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)
|
bool addLineDirectivesAfterConditionalBlocks(std::string& source)
|
||||||
{
|
{
|
||||||
|
|
@ -122,7 +106,7 @@ namespace Shader
|
||||||
// Adjusts #line statements accordingly and detects cyclic includes.
|
// 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
|
// cycleIncludeChecker is the set of files that include this file directly or indirectly, and is intentionally not a
|
||||||
// reference to allow automatic cleanup.
|
// 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,
|
int& fileNumber, std::set<std::filesystem::path> cycleIncludeChecker,
|
||||||
std::set<std::filesystem::path>& includedFiles)
|
std::set<std::filesystem::path>& includedFiles)
|
||||||
{
|
{
|
||||||
|
|
@ -195,6 +179,127 @@ namespace Shader
|
||||||
}
|
}
|
||||||
return true;
|
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)
|
bool parseForeachDirective(std::string& source, const std::string& templateName, size_t foundPos)
|
||||||
{
|
{
|
||||||
|
|
@ -399,112 +504,6 @@ namespace Shader
|
||||||
return true;
|
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 " << 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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Shader> ShaderManager::getShader(
|
osg::ref_ptr<osg::Shader> ShaderManager::getShader(
|
||||||
std::string templateName, const ShaderManager::DefineMap& defines, std::optional<osg::Shader::Type> type)
|
std::string templateName, const ShaderManager::DefineMap& defines, std::optional<osg::Shader::Type> type)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue