diff --git a/src/xenia/gpu/texture_cache.cc b/src/xenia/gpu/texture_cache.cc index f043c6468..357e7be99 100644 --- a/src/xenia/gpu/texture_cache.cc +++ b/src/xenia/gpu/texture_cache.cc @@ -693,6 +693,21 @@ void TextureCache::LoadTexturesData(Texture** textures, uint32_t n_textures) { } } + // Lockless pre-check: count how many textures appear outdated. + // If none appear outdated, skip the lock entirely. + uint32_t likely_outdated = 0; + for (uint32_t i = 0; i < n_textures; ++i) { + Texture* current = textures[i]; + if (current->base_outdated_lockless() || + current->mips_outdated_lockless()) { + ++likely_outdated; + } + } + if (likely_outdated == 0) { + // All textures appear up-to-date, skip lock acquisition + return; + } + uint64_t index_base_outdated = 0; uint64_t index_mips_outdated = 0; uint32_t nkept = 0; @@ -811,6 +826,13 @@ void TextureCache::LoadTexturesData(Texture** textures, uint32_t n_textures) { } } bool TextureCache::LoadTextureData(Texture& texture) { + // Lockless pre-check: if texture appears up-to-date, skip the lock. + // This is safe because worst case is a false positive (we acquire lock + // unnecessarily), never a false negative. + if (!texture.base_outdated_lockless() && !texture.mips_outdated_lockless()) { + return true; + } + // Check what needs to be uploaded. bool base_outdated, mips_outdated; { diff --git a/src/xenia/gpu/texture_cache.h b/src/xenia/gpu/texture_cache.h index a66e3af75..4ceafa5aa 100644 --- a/src/xenia/gpu/texture_cache.h +++ b/src/xenia/gpu/texture_cache.h @@ -276,6 +276,11 @@ class TextureCache { bool mips_outdated(const global_unique_lock_type& global_lock) const { return mips_outdated_; } + // Lockless accessors for pre-check optimization. + // Safe to read without lock - worst case is false positive (outdated when + // not). + bool base_outdated_lockless() const { return base_outdated_; } + bool mips_outdated_lockless() const { return mips_outdated_; } void MakeUpToDateAndWatch(const global_unique_lock_type& global_lock); void WatchCallback(const global_unique_lock_type& global_lock, bool is_mip);