Merge branch 'master' into 'master'

Draft: RFC: texture reload debug command

See merge request OpenMW/openmw!4774
This commit is contained in:
wareya 2025-08-02 21:55:23 +00:00
commit eb32f0adb5
3 changed files with 38 additions and 6 deletions

View File

@ -10,6 +10,7 @@
#include "../mwrender/postprocessor.hpp"
#include "../mwrender/renderingmanager.hpp"
#include <components/resource/imagemanager.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/shader/shadermanager.hpp>
@ -82,6 +83,13 @@ namespace MWLua
});
};
api["triggerTextureReload"] = [context]() {
context.mLuaManager->addAction([] {
auto imageManager = MWBase::Environment::get().getResourceSystem()->getImageManager();
imageManager->attemptGlobalReload();
});
};
api["setShaderHotReloadEnabled"] = [context](bool value) {
context.mLuaManager->addAction([value] {
auto world = MWBase::Environment::get().getWorld();

View File

@ -85,12 +85,39 @@ namespace Resource
return true;
}
void ImageManager::attemptGlobalReload()
{
mCache->call([&](std::string name, osg::Object* obj) {
auto image = performLoad(VFS::Path::NormalizedView(name.data()));
image->swap(*static_cast<osg::Image*>(obj));
static_cast<osg::Image*>(obj)->dirty();
});
}
osg::ref_ptr<osg::Image> ImageManager::getImage(VFS::Path::NormalizedView path, bool disableFlip)
{
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(path);
if (obj)
return osg::ref_ptr<osg::Image>(static_cast<osg::Image*>(obj.get()));
else
{
auto image = performLoad(path, disableFlip);
// Duplicate the image we got if it's the warning image, so that we can't thrash it
if (image == mWarningImage)
{
// The warning image is like 8x8 so it's not really a problem to deeply clone it.
// We want each usage to have its own osg::Image so that assigning into the cache is safe.
auto cloned = mWarningImage.get()->clone(osg::CopyOp(osg::CopyOp::Options::DEEP_COPY_ALL));
image = static_cast<osg::Image*>(cloned); // constructs a ref_ptr during assignment
}
mCache->addEntryToObjectCache(path.value(), image);
return image;
}
}
osg::ref_ptr<osg::Image> ImageManager::performLoad(VFS::Path::NormalizedView path, bool disableFlip)
{
if (true) // for diff reduction indentation
{
Files::IStreamPtr stream;
try
@ -100,7 +127,6 @@ namespace Resource
catch (std::exception& e)
{
Log(Debug::Error) << "Failed to open image: " << e.what();
mCache->addEntryToObjectCache(path.value(), mWarningImage);
return mWarningImage;
}
@ -109,7 +135,6 @@ namespace Resource
if (!reader)
{
Log(Debug::Error) << "Error loading " << path << ": no readerwriter for '" << ext << "' found";
mCache->addEntryToObjectCache(path.value(), mWarningImage);
return mWarningImage;
}
@ -122,7 +147,6 @@ namespace Resource
if (stream->gcount() != 18)
{
Log(Debug::Error) << "Error loading " << path << ": couldn't read TGA header";
mCache->addEntryToObjectCache(path.value(), mWarningImage);
return mWarningImage;
}
int type = header[2];
@ -142,7 +166,6 @@ namespace Resource
{
Log(Debug::Error) << "Error loading " << path << ": " << result.message() << " code "
<< result.status();
mCache->addEntryToObjectCache(path.value(), mWarningImage);
return mWarningImage;
}
@ -155,7 +178,6 @@ namespace Resource
if (!uncompress)
{
Log(Debug::Error) << "Error loading " << path << ": no S3TC texture compression support installed";
mCache->addEntryToObjectCache(path.value(), mWarningImage);
return mWarningImage;
}
else
@ -186,7 +208,6 @@ namespace Resource
image = newImage;
}
mCache->addEntryToObjectCache(path.value(), image);
return image;
}
}

View File

@ -33,6 +33,8 @@ namespace Resource
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
void attemptGlobalReload();
private:
osg::ref_ptr<osg::Image> mWarningImage;
osg::ref_ptr<osgDB::Options> mOptions;
@ -40,6 +42,7 @@ namespace Resource
ImageManager(const ImageManager&);
void operator=(const ImageManager&);
osg::ref_ptr<osg::Image> performLoad(VFS::Path::NormalizedView name, bool disableFlip = false);
};
}