diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 8265f19e82..4206734dfb 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -101,21 +101,21 @@ bool ReplacedTexture::IsReady(double budget) { return false; } -void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { - logId_ = desc.logId; - levelData_ = desc.cache; +void ReplacedTexture::FinishPopulate(ReplacementDesc *desc) { + logId_ = desc->logId; + levelData_ = desc->cache; // TODO: The rest can be done on the thread. - for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc.filenames.size()); ++i) { - if (desc.filenames[i].empty()) { + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc->filenames.size()); ++i) { + if (desc->filenames[i].empty()) { // Out of valid mip levels. Bail out. break; } - const Path filename = desc.basePath / desc.filenames[i]; + const Path filename = desc->basePath / desc->filenames[i]; - VFSFileReference *fileRef = vfs_->GetFile(desc.filenames[i].c_str()); + VFSFileReference *fileRef = vfs_->GetFile(desc->filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. break; @@ -136,8 +136,8 @@ void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { good = PopulateLevel(level, false); // We pad files that have been hashrange'd so they are the same texture size. - level.w = (level.w * desc.w) / desc.newW; - level.h = (level.h * desc.h) / desc.newH; + level.w = (level.w * desc->w) / desc->newW; + level.h = (level.h * desc->h) / desc->newH; if (good && i != 0) { // Check that the mipmap size is correct. Can't load mips of the wrong size. @@ -154,6 +154,8 @@ void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { break; } + delete desc; + if (levels_.empty()) { // Bad. SetState(ReplacementState::NOT_FOUND); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 2911c5fef1..5ec3950b72 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -129,7 +129,7 @@ struct ReplacedTexture { bool IsReady(double budget); bool CopyLevelTo(int level, void *out, int rowPitch); - void FinishPopulate(const ReplacementDesc &desc); + void FinishPopulate(ReplacementDesc *desc); std::string logId_; private: @@ -148,7 +148,7 @@ private: std::mutex mutex_; Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. - ReplacementState state_ = ReplacementState::UNINITIALIZED; + std::atomic state_ = ReplacementState::UNINITIALIZED; VFSBackend *vfs_ = nullptr; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index ebe7bb4f25..1ce1fd62ca 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -498,23 +498,24 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, } void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey, u32 hash, int w, int h) { - ReplacementDesc desc; - desc.newW = w; - desc.newH = h; - desc.w = w; - desc.h = h; - desc.cachekey = cachekey; - desc.hash = hash; - desc.basePath = basePath_; - LookupHashRange(cachekey >> 32, desc.newW, desc.newH); + // We pass this to a thread, so can't keep it on the stack. + ReplacementDesc *desc = new ReplacementDesc(); + desc->newW = w; + desc->newH = h; + desc->w = w; + desc->h = h; + desc->cachekey = cachekey; + desc->hash = hash; + desc->basePath = basePath_; + LookupHashRange(cachekey >> 32, desc->newW, desc->newH); if (ignoreAddress_) { cachekey = cachekey & 0xFFFFFFFFULL; } - desc.foundAlias = false; + desc->foundAlias = false; bool ignored = false; - desc.hashfiles = LookupHashFile(cachekey, hash, &desc.foundAlias, &ignored); + desc->hashfiles = LookupHashFile(cachekey, hash, &desc->foundAlias, &ignored); // Early-out for ignored textures, let's not bother even starting a thread task. if (ignored) { @@ -524,22 +525,22 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey return; } - if (!desc.foundAlias) { + if (!desc->foundAlias) { // We'll just need to generate the names for each level. // By default, we look for png since that's also what's dumped. // For other file formats, use the ini to create aliases. - desc.filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); - for (int level = 0; level < desc.filenames.size(); level++) { - desc.filenames[level] = TextureReplacer::HashName(desc.cachekey, desc.hash, level) + ".png"; + desc->filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); + for (int level = 0; level < desc->filenames.size(); level++) { + desc->filenames[level] = TextureReplacer::HashName(desc->cachekey, desc->hash, level) + ".png"; } - desc.logId = desc.filenames[0]; - desc.hashfiles = desc.filenames[0]; // This is used as the key in the data cache. + desc->logId = desc->filenames[0]; + desc->hashfiles = desc->filenames[0]; // This is used as the key in the data cache. } else { - desc.logId = desc.hashfiles; - SplitString(desc.hashfiles, '|', desc.filenames); + desc->logId = desc->hashfiles; + SplitString(desc->hashfiles, '|', desc->filenames); } - desc.cache = &levelCache_[desc.hashfiles]; + desc->cache = &levelCache_[desc->hashfiles]; texture->FinishPopulate(desc); }