mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Replacement: Save textures even if already replaced, if the png is missing.
Fixes #17182 Not exactly sure what behavior we really want, but I think this one is OK, and at least more similar to the old one. Now we save already-replaced textures if the named replacement texture is missing, and there isn't already a hash-named one in new or the "root".
This commit is contained in:
parent
668a6d63cb
commit
4e41233bb7
@ -220,6 +220,12 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) {
|
|||||||
|
|
||||||
VFSFileReference *fileRef = vfs_->GetFile(desc_.filenames[i].c_str());
|
VFSFileReference *fileRef = vfs_->GetFile(desc_.filenames[i].c_str());
|
||||||
if (!fileRef) {
|
if (!fileRef) {
|
||||||
|
if (i == 0) {
|
||||||
|
WARN_LOG(G3D, "Texture replacement file '%s' not found", desc_.filenames[i].c_str());
|
||||||
|
// No file at all. Mark as NOT_FOUND.
|
||||||
|
SetState(ReplacementState::NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// If the file doesn't exist, let's just bail immediately here.
|
// If the file doesn't exist, let's just bail immediately here.
|
||||||
// Mark as DONE, not error.
|
// Mark as DONE, not error.
|
||||||
result = LoadLevelResult::DONE;
|
result = LoadLevelResult::DONE;
|
||||||
@ -276,8 +282,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) {
|
|||||||
|
|
||||||
SetState(ReplacementState::ACTIVE);
|
SetState(ReplacementState::ACTIVE);
|
||||||
|
|
||||||
if (threadWaitable_)
|
// the caller calls threadWaitable->notify().
|
||||||
threadWaitable_->Notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if Prepare should keep calling this to load more levels.
|
// Returns true if Prepare should keep calling this to load more levels.
|
||||||
|
@ -2967,7 +2967,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, s
|
|||||||
replacedInfo.fmt = dstFmt;
|
replacedInfo.fmt = dstFmt;
|
||||||
|
|
||||||
// NOTE: Reading the decoded texture here may be very slow, if we just wrote it to write-combined memory.
|
// NOTE: Reading the decoded texture here may be very slow, if we just wrote it to write-combined memory.
|
||||||
replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h, scaledW, scaledH);
|
replacer_.NotifyTextureDecoded(plan.replaced, replacedInfo, pixelData, decPitch, srcLevel, w, h, scaledW, scaledH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,6 +582,7 @@ public:
|
|||||||
|
|
||||||
Path filename;
|
Path filename;
|
||||||
Path saveFilename;
|
Path saveFilename;
|
||||||
|
Path alreadyReplacedFilename; // if the texture was already replaced
|
||||||
bool createSaveDirectory = false;
|
bool createSaveDirectory = false;
|
||||||
Path saveDirectory;
|
Path saveDirectory;
|
||||||
|
|
||||||
@ -604,9 +605,15 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// And we always skip if the replace file already exists.
|
// And we always skip if the auto-hash-named replace file already exists.
|
||||||
if (File::Exists(filename))
|
if (File::Exists(filename)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also, if a named replacement already exists, don't save.
|
||||||
|
if (File::Exists(alreadyReplacedFilename)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (createSaveDirectory && !File::Exists(saveDirectory)) {
|
if (createSaveDirectory && !File::Exists(saveDirectory)) {
|
||||||
File::CreateFullPath(saveDirectory);
|
File::CreateFullPath(saveDirectory);
|
||||||
@ -643,8 +650,9 @@ bool TextureReplacer::WillSave(const ReplacedTextureDecodeInfo &replacedInfo) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int origW, int origH, int scaledW, int scaledH) {
|
void TextureReplacer::NotifyTextureDecoded(ReplacedTexture *texture, const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int origW, int origH, int scaledW, int scaledH) {
|
||||||
_assert_msg_(enabled_, "Replacement not enabled");
|
_assert_msg_(enabled_, "Replacement not enabled");
|
||||||
|
|
||||||
if (!WillSave(replacedInfo)) {
|
if (!WillSave(replacedInfo)) {
|
||||||
// Ignore.
|
// Ignore.
|
||||||
return;
|
return;
|
||||||
@ -659,20 +667,24 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool foundAlias = false, ignored = false;
|
bool foundAlias = false, ignored = false;
|
||||||
std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &foundAlias, &ignored);
|
std::string replacedLevelNames = LookupHashFile(cachekey, replacedInfo.hash, &foundAlias, &ignored);
|
||||||
|
std::vector<std::string> names;
|
||||||
|
SplitString(replacedLevelNames, '|', names);
|
||||||
|
std::string replacedLevelName = names[std::min(level, (int)(names.size() - 1))];
|
||||||
|
|
||||||
// If it's empty, it's an ignored hash, we intentionally don't save.
|
if (ignored) {
|
||||||
if (foundAlias || ignored) {
|
// If it's empty, it's an ignored hash, we intentionally don't save.
|
||||||
// If it exists, must've been decoded and saved as a new texture already.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do push other textures on a thread for saving.
|
||||||
|
|
||||||
// Generate a new PNG filename, complete with level.
|
// Generate a new PNG filename, complete with level.
|
||||||
hashfile = HashName(cachekey, replacedInfo.hash, level) + ".png";
|
// TODO: If we already have a filename but it's missing, should we use that filename or a generated one?
|
||||||
|
std::string hashfile = HashName(cachekey, replacedInfo.hash, level) + ".png";
|
||||||
|
|
||||||
ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash);
|
ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash);
|
||||||
auto it = savedCache_.find(replacementKey);
|
auto it = savedCache_.find(replacementKey);
|
||||||
bool skipIfExists = false;
|
|
||||||
double now = time_now_d();
|
double now = time_now_d();
|
||||||
if (it != savedCache_.end()) {
|
if (it != savedCache_.end()) {
|
||||||
// We've already saved this texture. Ignore it.
|
// We've already saved this texture. Ignore it.
|
||||||
@ -706,6 +718,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
|
|||||||
|
|
||||||
task->filename = basePath_ / hashfile;
|
task->filename = basePath_ / hashfile;
|
||||||
task->saveFilename = newTextureDir_ / hashfile;
|
task->saveFilename = newTextureDir_ / hashfile;
|
||||||
|
task->alreadyReplacedFilename = basePath_ / replacedLevelName;
|
||||||
task->createSaveDirectory = false;
|
task->createSaveDirectory = false;
|
||||||
|
|
||||||
// Create subfolder as needed.
|
// Create subfolder as needed.
|
||||||
@ -728,7 +741,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
|
|||||||
task->h = h;
|
task->h = h;
|
||||||
task->pitch = pitch;
|
task->pitch = pitch;
|
||||||
task->replacedInfoHash = replacedInfo.hash;
|
task->replacedInfoHash = replacedInfo.hash;
|
||||||
task->skipIfExists = skipIfExists;
|
task->skipIfExists = true; // if already in the "new" folder, don't bother writing.
|
||||||
g_threadManager.EnqueueTask(task); // We don't care about waiting for the task. It'll be fine.
|
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.
|
// Remember that we've saved this for next time.
|
||||||
|
@ -111,7 +111,8 @@ public:
|
|||||||
bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo);
|
bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo);
|
||||||
|
|
||||||
// Notify that a new texture was decoded. May already be upscaled, saves the data passed.
|
// 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 origW, int origH, int scaledW, int scaledH);
|
// If the replacer knows about this one already, texture will be passed in, otherwise nullptr.
|
||||||
|
void NotifyTextureDecoded(ReplacedTexture *texture, const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int origW, int origH, int scaledW, int scaledH);
|
||||||
|
|
||||||
void Decimate(ReplacerDecimateMode mode);
|
void Decimate(ReplacerDecimateMode mode);
|
||||||
|
|
||||||
|
@ -1636,7 +1636,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) {
|
|||||||
"FBOs active: %d (evaluations: %d)\n"
|
"FBOs active: %d (evaluations: %d)\n"
|
||||||
"Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n"
|
"Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n"
|
||||||
"readbacks %d (%d non-block), uploads %d, depal %d\n"
|
"readbacks %d (%d non-block), uploads %d, depal %d\n"
|
||||||
"replacer: tracks %d textures, %d unique loaded\n"
|
"replacer: tracks %d references, %d unique textures\n"
|
||||||
"Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n"
|
"Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n"
|
||||||
"GPU cycles executed: %d (%f per vertex)\n",
|
"GPU cycles executed: %d (%f per vertex)\n",
|
||||||
gpuStats.msProcessingDisplayLists * 1000.0f,
|
gpuStats.msProcessingDisplayLists * 1000.0f,
|
||||||
|
@ -648,7 +648,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
|||||||
replacedInfo.isVideo = IsVideo(entry->addr);
|
replacedInfo.isVideo = IsVideo(entry->addr);
|
||||||
replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0;
|
replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0;
|
||||||
replacedInfo.fmt = FromVulkanFormat(actualFmt);
|
replacedInfo.fmt = FromVulkanFormat(actualFmt);
|
||||||
replacer_.NotifyTextureDecoded(replacedInfo, data, byteStride, plan.baseLevelSrc + i, mipUnscaledWidth, mipUnscaledHeight, w, h);
|
replacer_.NotifyTextureDecoded(plan.replaced, replacedInfo, data, byteStride, plan.baseLevelSrc + i, mipUnscaledWidth, mipUnscaledHeight, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user