diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 3a62b92b86..18a73bee91 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -1610,6 +1610,9 @@ GSTextureCache::Source::Source(GSRenderer* r, const GIFRegTEX0& TEX0, const GIFR { m_p2t = r->m_mem.GetPage2TileMap(m_TEX0); } + + // will be useless with texture page coverage + m_erase_it.fill(list::iterator(0)); } } @@ -1982,8 +1985,10 @@ void GSTextureCache::SourceMap::Add(Source* s, const GIFRegTEX0& TEX0, GSOffset* // TODO // GH: I don't know why but it seems we only consider the first page for a render target + size_t page = TEX0.TBP0 >> 5; - m_map[TEX0.TBP0 >> 5].push_front(s); + m_map[page].push_front(s); + s->m_erase_it[page] = m_map[page].begin(); return; } @@ -1997,6 +2002,7 @@ void GSTextureCache::SourceMap::Add(Source* s, const GIFRegTEX0& TEX0, GSOffset* if(uint32 p = pages[i]) { list* m = &m_map[i << 5]; + auto* e = &s->m_erase_it[i << 5]; unsigned long j; @@ -2008,6 +2014,7 @@ void GSTextureCache::SourceMap::Add(Source* s, const GIFRegTEX0& TEX0, GSOffset* p ^= 1 << j; m[j].push_front(s); + e[j] = m[j].begin(); } } } @@ -2083,16 +2090,22 @@ void GSTextureCache::SourceMap::RemoveAt(Source* s) s->m_texture ? s->m_texture->GetID() : 0, s->m_TEX0.TBP0); - // Source (except render target) is duplicated for each page they use. - for(size_t start = s->m_TEX0.TBP0 >> 5, end = s->m_target ? start : countof(m_map) - 1; start <= end; start++) + if (s->m_target) { - list& m = m_map[start]; + size_t page = s->m_TEX0.TBP0 >> 5; + ASSERT(*s->m_erase_it[page] == s); + m_map[page].erase(s->m_erase_it[page]); - for(list::iterator i = m.begin(); i != m.end(); ) + } + else + { + // Source is duplicated for each page they use. + for(size_t page = s->m_TEX0.TBP0 >> 5, end = countof(m_map) - 1; page <= end; page++) { - list::iterator j = i++; - - if(*j == s) {m.erase(j); break;} + if (s->m_erase_it[page] != list::iterator(0)) { + ASSERT(*s->m_erase_it[page] == s); + m_map[page].erase(s->m_erase_it[page]); + } } } diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index f36f8a5641..3847dc6591 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -72,6 +72,8 @@ public: // so it can be used to access un-converted data for the current draw call. GSTexture* m_from_target; GIFRegTEX0 m_layer_TEX0[7]; // Detect already loaded value + // Keep an GSTextureCache::m_map iterator to allow fast erase + std::array::iterator, MAX_PAGES> m_erase_it; public: Source(GSRenderer* r, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, uint8* temp, bool dummy_container = false); @@ -106,7 +108,7 @@ public: public: hash_set m_surfaces; hash_map m_pages_coverage; - list m_map[MAX_PAGES]; + std::list m_map[MAX_PAGES]; uint32 m_pages[16]; // bitmap of all pages bool m_used; @@ -123,7 +125,7 @@ public: protected: GSRenderer* m_renderer; SourceMap m_src; - list m_dst[2]; + std::list m_dst[2]; bool m_paltex; int m_spritehack; bool m_preload_frame; diff --git a/plugins/GSdx/stdafx.h b/plugins/GSdx/stdafx.h index a1e0312e28..bbbe80ab65 100644 --- a/plugins/GSdx/stdafx.h +++ b/plugins/GSdx/stdafx.h @@ -102,6 +102,7 @@ typedef int64 sint64; #include #include +#include #include #include #include