mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Move channel shuffle test to top of Draw()
This commit is contained in:
parent
f77a5c23fc
commit
72802aa125
|
@ -800,8 +800,11 @@ bool GSRendererHW::IsPossibleChannelShuffle() const
|
||||||
|
|
||||||
// WRC 4 does channel shuffles in vertical strips. So check for page alignment.
|
// WRC 4 does channel shuffles in vertical strips. So check for page alignment.
|
||||||
// Texture TBW should also be twice the framebuffer FBW, because the page is twice as wide.
|
// Texture TBW should also be twice the framebuffer FBW, because the page is twice as wide.
|
||||||
if (m_cached_ctx.TEX0.TBW == (m_cached_ctx.FRAME.FBW * 2) && GSLocalMemory::IsPageAligned(m_cached_ctx.FRAME.PSM, m_r))
|
if (m_cached_ctx.TEX0.TBW == (m_cached_ctx.FRAME.FBW * 2) &&
|
||||||
|
GSLocalMemory::IsPageAligned(m_cached_ctx.FRAME.PSM, GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p))))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1422,6 +1425,10 @@ void GSRendererHW::Draw()
|
||||||
DumpVertices(s);
|
DumpVertices(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_OGL_DEBUG
|
||||||
|
static u32 num_skipped_channel_shuffle_draws = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// We mess with this state as an optimization, so take a copy and use that instead.
|
// We mess with this state as an optimization, so take a copy and use that instead.
|
||||||
const GSDrawingContext* context = m_context;
|
const GSDrawingContext* context = m_context;
|
||||||
m_cached_ctx.TEX0 = context->TEX0;
|
m_cached_ctx.TEX0 = context->TEX0;
|
||||||
|
@ -1435,6 +1442,30 @@ void GSRendererHW::Draw()
|
||||||
GL_INS("Warning skipping a draw call (%d)", s_n);
|
GL_INS("Warning skipping a draw call (%d)", s_n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Channel shuffles repeat lots of draws. Get out early if we can.
|
||||||
|
if (m_channel_shuffle)
|
||||||
|
{
|
||||||
|
// NFSU2 does consecutive channel shuffles with blending, reducing the alpha channel over time.
|
||||||
|
// Fortunately, it seems to change the FBMSK along the way, so this check alone is sufficient.
|
||||||
|
m_channel_shuffle = IsPossibleChannelShuffle() && m_last_channel_shuffle_fbmsk == m_context->FRAME.FBMSK;
|
||||||
|
|
||||||
|
#ifdef ENABLE_OGL_DEBUG
|
||||||
|
if (m_channel_shuffle)
|
||||||
|
{
|
||||||
|
num_skipped_channel_shuffle_draws++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_skipped_channel_shuffle_draws > 0)
|
||||||
|
GL_INS("Skipped %u channel shuffle draws", num_skipped_channel_shuffle_draws);
|
||||||
|
num_skipped_channel_shuffle_draws = 0;
|
||||||
|
#else
|
||||||
|
if (m_channel_shuffle)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
GL_PUSH("HW Draw %d", s_n);
|
GL_PUSH("HW Draw %d", s_n);
|
||||||
|
|
||||||
// When the format is 24bit (Z or C), DATE ceases to function.
|
// When the format is 24bit (Z or C), DATE ceases to function.
|
||||||
|
@ -1576,27 +1607,13 @@ void GSRendererHW::Draw()
|
||||||
const GSVector4 rect = m_vt.m_min.p.xyxy(m_vt.m_max.p) + GSVector4(0.0f, 0.0f, 0.5f, 0.5f);
|
const GSVector4 rect = m_vt.m_min.p.xyxy(m_vt.m_max.p) + GSVector4(0.0f, 0.0f, 0.5f, 0.5f);
|
||||||
m_r = GSVector4i(rect).rintersect(GSVector4i(context->scissor.in));
|
m_r = GSVector4i(rect).rintersect(GSVector4i(context->scissor.in));
|
||||||
|
|
||||||
if (m_channel_shuffle)
|
if (!m_channel_shuffle && m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 &&
|
||||||
{
|
IsPossibleChannelShuffle())
|
||||||
// NFSU2 does consecutive channel shuffles with blending, reducing the alpha channel over time.
|
|
||||||
// Fortunately, it seems to change the FBMSK along the way, so this check alone is sufficient.
|
|
||||||
m_channel_shuffle = IsPossibleChannelShuffle() && m_last_channel_shuffle_fbmsk == m_cached_ctx.FRAME.FBMSK;
|
|
||||||
if (m_channel_shuffle)
|
|
||||||
{
|
|
||||||
GL_CACHE("Channel shuffle effect detected SKIP");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 && IsPossibleChannelShuffle())
|
|
||||||
{
|
{
|
||||||
// Special post-processing effect
|
// Special post-processing effect
|
||||||
GL_INS("Possible channel shuffle effect detected");
|
GL_INS("Possible channel shuffle effect detected");
|
||||||
m_channel_shuffle = true;
|
m_channel_shuffle = true;
|
||||||
m_last_channel_shuffle_fbmsk = m_cached_ctx.FRAME.FBMSK;
|
m_last_channel_shuffle_fbmsk = m_context->FRAME.FBMSK;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_channel_shuffle = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_texture_shuffle = false;
|
m_texture_shuffle = false;
|
||||||
|
@ -1932,7 +1949,7 @@ void GSRendererHW::Draw()
|
||||||
{
|
{
|
||||||
GL_INS("Channel shuffle effect detected (2nd shot)");
|
GL_INS("Channel shuffle effect detected (2nd shot)");
|
||||||
m_channel_shuffle = true;
|
m_channel_shuffle = true;
|
||||||
m_last_channel_shuffle_fbmsk = m_cached_ctx.FRAME.FBMSK;
|
m_last_channel_shuffle_fbmsk = m_context->FRAME.FBMSK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2762,10 +2779,7 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask()
|
||||||
bool GSRendererHW::TestChannelShuffle(GSTextureCache::Target* src)
|
bool GSRendererHW::TestChannelShuffle(GSTextureCache::Target* src)
|
||||||
{
|
{
|
||||||
// We have to do the second test early here, because it might be a different source.
|
// We have to do the second test early here, because it might be a different source.
|
||||||
const bool shuffle = m_channel_shuffle || (
|
const bool shuffle = m_channel_shuffle || IsPossibleChannelShuffle();
|
||||||
PRIM->TME && m_cached_ctx.TEX0.PSM == PSM_PSMT8 && // 8-bit texture draw
|
|
||||||
m_vt.m_primclass == GS_SPRITE_CLASS && // draw_sprite_tex
|
|
||||||
(((m_vt.m_max.p - m_vt.m_min.p) <= GSVector4(64.0f)).mask() & 0x3) == 0x3); // single_page
|
|
||||||
|
|
||||||
// This is a little redundant since it'll get called twice, but the only way to stop us wasting time on copies.
|
// This is a little redundant since it'll get called twice, but the only way to stop us wasting time on copies.
|
||||||
m_channel_shuffle = (shuffle && EmulateChannelShuffle(src, true));
|
m_channel_shuffle = (shuffle && EmulateChannelShuffle(src, true));
|
||||||
|
|
Loading…
Reference in New Issue