mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-12-03 11:11:25 +00:00
Replacement: Move IO checks to saving thread.
This will spin up more threads that might not actually save, but it will remember this in savedCache.
This commit is contained in:
parent
39d6dc1740
commit
e0e3223c19
@ -512,20 +512,50 @@ public:
|
||||
int h = 0;
|
||||
int pitch = 0; // bytes
|
||||
|
||||
Path path;
|
||||
Path basePath;
|
||||
std::string hashfile;
|
||||
u32 replacedInfoHash;
|
||||
|
||||
bool skipIfExists = false;
|
||||
|
||||
TextureSaveTask(SimpleBuf<u32> _data) : data(std::move(_data)) {}
|
||||
|
||||
TaskType Type() const override { return TaskType::CPU_COMPUTE; } // Also I/O blocking but dominated by compute
|
||||
void Run() override {
|
||||
const Path filename = basePath / hashfile;
|
||||
const Path saveFilename = basePath / NEW_TEXTURE_DIR / hashfile;
|
||||
|
||||
// Should we skip writing if the newly saved data already exists?
|
||||
// We do this on the thread due to slow IO.
|
||||
if (skipIfExists && File::Exists(saveFilename))
|
||||
return;
|
||||
|
||||
// And we always skip if the replace file already exists.
|
||||
if (hashfile.empty() || File::Exists(filename))
|
||||
return;
|
||||
|
||||
// Create subfolder as needed.
|
||||
#ifdef _WIN32
|
||||
size_t slash = hashfile.find_last_of("/\\");
|
||||
#else
|
||||
size_t slash = hashfile.find_last_of("/");
|
||||
#endif
|
||||
if (slash != hashfile.npos) {
|
||||
// Create any directory structure as needed.
|
||||
const Path saveDirectory = basePath / NEW_TEXTURE_DIR / hashfile.substr(0, slash);
|
||||
if (!File::Exists(saveDirectory)) {
|
||||
File::CreateFullPath(saveDirectory);
|
||||
File::CreateEmptyFile(saveDirectory / ".nomedia");
|
||||
}
|
||||
}
|
||||
|
||||
png_image png;
|
||||
memset(&png, 0, sizeof(png));
|
||||
png.version = PNG_IMAGE_VERSION;
|
||||
png.format = PNG_FORMAT_RGBA;
|
||||
png.width = w;
|
||||
png.height = h;
|
||||
bool success = WriteTextureToPNG(&png, path, 0, data.data(), pitch, nullptr);
|
||||
bool success = WriteTextureToPNG(&png, saveFilename, 0, data.data(), pitch, nullptr);
|
||||
png_image_free(&png);
|
||||
if (png.warning_or_error >= 2) {
|
||||
ERROR_LOG(COMMON, "Saving screenshot to PNG produced errors.");
|
||||
@ -535,58 +565,50 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
bool TextureReplacer::WillSave(const ReplacedTextureDecodeInfo &replacedInfo) {
|
||||
_assert_msg_(enabled_, "Replacement not enabled");
|
||||
if (!g_Config.bSaveNewTextures)
|
||||
return false;
|
||||
// Don't save the PPGe texture.
|
||||
if (replacedInfo.addr > 0x05000000 && replacedInfo.addr < PSP_GetKernelMemoryEnd())
|
||||
return false;
|
||||
if (replacedInfo.isVideo && !allowVideo_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h) {
|
||||
_assert_msg_(enabled_, "Replacement not enabled");
|
||||
if (!g_Config.bSaveNewTextures) {
|
||||
if (!WillSave(replacedInfo)) {
|
||||
// Ignore.
|
||||
return;
|
||||
}
|
||||
if (replacedInfo.addr > 0x05000000 && replacedInfo.addr < PSP_GetKernelMemoryEnd()) {
|
||||
// Don't save the PPGe texture.
|
||||
return;
|
||||
}
|
||||
if (replacedInfo.isVideo && !allowVideo_) {
|
||||
return;
|
||||
}
|
||||
u64 cachekey = replacedInfo.cachekey;
|
||||
if (ignoreAddress_) {
|
||||
cachekey = cachekey & 0xFFFFFFFFULL;
|
||||
}
|
||||
if (ignoreMipmap_ && level > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
u64 cachekey = replacedInfo.cachekey;
|
||||
if (ignoreAddress_) {
|
||||
cachekey = cachekey & 0xFFFFFFFFULL;
|
||||
}
|
||||
|
||||
std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level);
|
||||
const Path filename = basePath_ / hashfile;
|
||||
const Path saveFilename = basePath_ / NEW_TEXTURE_DIR / hashfile;
|
||||
|
||||
// If it's empty, it's an ignored hash, we intentionally don't save.
|
||||
if (hashfile.empty() || File::Exists(filename)) {
|
||||
if (hashfile.empty()) {
|
||||
// If it exists, must've been decoded and saved as a new texture already.
|
||||
return;
|
||||
}
|
||||
|
||||
ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash);
|
||||
auto it = savedCache_.find(replacementKey);
|
||||
if (it != savedCache_.end() && File::Exists(saveFilename)) {
|
||||
bool skipIfExists = false;
|
||||
if (it != savedCache_.end()) {
|
||||
// We've already saved this texture. Let's only save if it's bigger (e.g. scaled now.)
|
||||
if (it->second.w >= w && it->second.h >= h) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
size_t slash = hashfile.find_last_of("/\\");
|
||||
#else
|
||||
size_t slash = hashfile.find_last_of("/");
|
||||
#endif
|
||||
if (slash != hashfile.npos) {
|
||||
// Create any directory structure as needed.
|
||||
const Path saveDirectory = basePath_ / NEW_TEXTURE_DIR / hashfile.substr(0, slash);
|
||||
if (!File::Exists(saveDirectory)) {
|
||||
File::CreateFullPath(saveDirectory);
|
||||
File::CreateEmptyFile(saveDirectory / ".nomedia");
|
||||
skipIfExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,8 +673,10 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
|
||||
task->w = w;
|
||||
task->h = h;
|
||||
task->pitch = pitch;
|
||||
task->path = saveFilename;
|
||||
task->basePath = basePath_;
|
||||
task->hashfile = hashfile;
|
||||
task->replacedInfoHash = replacedInfo.hash;
|
||||
task->skipIfExists = skipIfExists;
|
||||
g_threadManager.EnqueueTask(task); // We don't care about waiting for the task. It'll be fine.
|
||||
|
||||
// Remember that we've saved this for next time.
|
||||
|
@ -208,6 +208,9 @@ public:
|
||||
return none_;
|
||||
}
|
||||
|
||||
// Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.)
|
||||
bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo);
|
||||
|
||||
// Notify that a new texture was decoded. May already be upscaled, saves the data passed.
|
||||
void NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user