diff --git a/pcsx2/GS/Renderers/Common/GSFastList.h b/pcsx2/GS/Renderers/Common/GSFastList.h index df1ac8cbbf..a852805933 100644 --- a/pcsx2/GS/Renderers/Common/GSFastList.h +++ b/pcsx2/GS/Renderers/Common/GSFastList.h @@ -26,11 +26,14 @@ struct Element template class FastListIterator; +template +class FastListReverseIterator; + template class FastList { friend class FastListIterator; - + friend class FastListReverseIterator; private: // The index of the first element of the list is m_buffer[0].next_index // The first Element of the list has prev_index equal to 0 @@ -159,6 +162,14 @@ public: return ++i; } + __forceinline const FastListReverseIterator rbegin() const { + return FastListReverseIterator(this, LastIndex()); + } + + __forceinline const FastListReverseIterator rend() const { + return FastListReverseIterator(this, 0); + } + private: // Accessed by FastListIterator using class friendship __forceinline const T& Data(const u16 index) const @@ -308,3 +319,60 @@ public: return m_index; } }; + +template +// This iterator is const_iterator +class FastListReverseIterator +{ +private: + const FastList* m_fastlist; + u16 m_index; + +public: + __forceinline FastListReverseIterator(const FastList* fastlist, const u16 index) { + m_fastlist = fastlist; + m_index = index; + } + + __forceinline bool operator!=(const FastListReverseIterator& other) const { + return (m_index != other.m_index); + } + + __forceinline bool operator==(const FastListReverseIterator& other) const { + return (m_index == other.m_index); + } + + // Prefix increment + __forceinline const FastListReverseIterator& operator++() { + m_index = m_fastlist->PrevIndex(m_index); + return *this; + } + + // Postfix increment + __forceinline const FastListReverseIterator operator++(int) { + FastListReverseIterator copy(*this); + ++(*this); + return copy; + } + + // Prefix decrement + __forceinline const FastListReverseIterator& operator--() { + m_index = m_fastlist->NextIndex(m_index); + return *this; + } + + // Postfix decrement + __forceinline const FastListReverseIterator operator--(int) { + FastListReverseIterator copy(*this); + --(*this); + return copy; + } + + __forceinline const T& operator*() const { + return m_fastlist->Data(m_index); + } + + __forceinline u16 Index() const { + return m_index; + } +}; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 791496e519..4d6edc6484 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -976,8 +976,10 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r GL_INS("ERROR: InvalidateLocalMem depth format isn't supported (%d,%d to %d,%d)", r.x, r.y, r.z, r.w); if (m_can_convert_depth) { - for (auto t : m_dst[DepthStencil]) + auto& dss = m_dst[DepthStencil]; + for (auto it = dss.rbegin(); it != dss.rend(); ++it) // Iterate targets from LRU to MRU. { + Target* t = *it; if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t->m_TEX0.PSM)) { if (GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM)) @@ -992,8 +994,10 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r // It works for all the games mentioned below and fixes a couple of other ones as well // (Busen0: Wizardry and Chaos Legion). // Also in a few games the below code ran the Grandia3 case when it shouldn't :p - for (auto t : m_dst[RenderTarget]) + auto& rts = m_dst[RenderTarget]; + for (auto it = rts.rbegin(); it != rts.rend(); ++it) // Iterate targets from LRU to MRU. { + Target* t = *it; if (t->m_TEX0.PSM != PSM_PSMZ32 && t->m_TEX0.PSM != PSM_PSMZ24 && t->m_TEX0.PSM != PSM_PSMZ16 && t->m_TEX0.PSM != PSM_PSMZ16S) { if (GSUtil::HasSharedBits(bp, psm, t->m_TEX0.TBP0, t->m_TEX0.PSM))