mirror of
https://github.com/OpenMW/openmw.git
synced 2025-12-11 16:04:31 +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'));
|
||||
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)
|
||||
{
|
||||
|
|
@ -122,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)
|
||||
{
|
||||
|
|
@ -195,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)
|
||||
{
|
||||
|
|
@ -399,112 +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 " << 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(
|
||||
std::string templateName, const ShaderManager::DefineMap& defines, std::optional<osg::Shader::Type> type)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue