1
0
Fork 0
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:
elsid 2025-11-23 22:22:01 +01:00
parent cef1bb1219
commit 402e1b3096
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40

View file

@ -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)
{