GS/HW: Improve full dirty rect clears. Remember new EE draws.

Rocky Legends transfers the new frame sometimes just before vsync, and it was getting lost.
This commit is contained in:
refractionpcsx2 2023-06-21 17:44:22 +01:00
parent 261b3f7e5c
commit e2a4657777
4 changed files with 25 additions and 3 deletions

View File

@ -26,6 +26,7 @@
#include <iomanip> // Dump Verticles
int GSState::s_n = 0;
int GSState::s_last_transfer_draw_n = 0;
int GSState::s_transfer_n = 0;
static __fi bool IsAutoFlushEnabled()
@ -1780,6 +1781,7 @@ void GSState::Write(const u8* mem, int len)
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = r.top + m_env.TRXREG.RRH;
s_last_transfer_draw_n = s_n;
// Store the transfer for preloading new RT's.
if ((m_draw_transfers.size() > 0 && blit.DBP == m_draw_transfers.back().blit.DBP))
{
@ -1982,6 +1984,8 @@ void GSState::Move()
r.top = m_env.TRXPOS.DSAY;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = r.top + m_env.TRXREG.RRH;
s_last_transfer_draw_n = s_n;
// Store the transfer for preloading new RT's.
if ((m_draw_transfers.size() > 0 && m_env.BITBLTBUF.DBP == m_draw_transfers.back().blit.DBP))
{

View File

@ -237,6 +237,7 @@ public:
std::vector<GSUploadQueue> m_draw_transfers;
static int s_n;
static int s_last_transfer_draw_n;
static int s_transfer_n;
static constexpr u32 STATE_VERSION = 8;

View File

@ -130,8 +130,25 @@ void GSRendererHW::VSync(u32 field, bool registers_written, bool idle_frame)
}
}
}
else
m_draw_transfers.clear();
else if (!idle_frame)
{
// If it did draws very recently, we should keep the recent stuff in case it hasn't been preloaded/used yet.
// Rocky Legend does this with the main menu FMV's.
if (s_last_transfer_draw_n == s_n)
{
for (auto iter = m_draw_transfers.begin(); iter != m_draw_transfers.end();)
{
if ((s_n - iter->draw) > 5)
iter = m_draw_transfers.erase(iter);
else
{
iter++;
}
}
}
else
m_draw_transfers.clear();
}
if (GSConfig.LoadTextureReplacements)
GSTextureReplacements::ProcessAsyncLoadedTextures();

View File

@ -99,7 +99,7 @@ bool GSTextureCache::FullRectDirty(Target* target)
RGBAMask rgba;
rgba._u32 = GSUtil::GetChannelMask(target->m_TEX0.PSM);
// One complete dirty rect, not pieces (Add dirty rect function should be able to join these all together).
if (target->m_age > 2 && target->m_dirty.size() == 1 && rgba._u32 == target->m_dirty[0].rgba._u32 && target->m_valid.rintersect(target->m_dirty[0].r).eq(target->m_valid))
if (target->m_age != 0 && target->m_dirty.size() == 1 && rgba._u32 == target->m_dirty[0].rgba._u32 && target->m_valid.rintersect(target->m_dirty[0].r).eq(target->m_valid))
{
return true;
}