mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Allow strip channel shuffles to be detected
Fixes fog wall in WRC 4.
This commit is contained in:
parent
a1c99f3e7a
commit
2b94cfe782
|
@ -446,6 +446,13 @@ std::vector<GSVector2i>* GSLocalMemory::GetPage2TileMap(const GIFRegTEX0& TEX0)
|
||||||
return p2t;
|
return p2t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GSLocalMemory::IsPageAligned(u32 psm, const GSVector4i& rc)
|
||||||
|
{
|
||||||
|
const psm_t& psm_s = m_psm[psm];
|
||||||
|
const GSVector4i pgmsk = GSVector4i(psm_s.pgs).xyxy() - GSVector4i(1);
|
||||||
|
return (rc & pgmsk).eq(GSVector4i::zero());
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
void GSLocalMemory::ReadTexture(const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
void GSLocalMemory::ReadTexture(const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA)
|
||||||
|
|
|
@ -541,6 +541,7 @@ public:
|
||||||
GSPixelOffset* GetPixelOffset(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
GSPixelOffset* GetPixelOffset(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
||||||
GSPixelOffset4* GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
GSPixelOffset4* GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
||||||
std::vector<GSVector2i>* GetPage2TileMap(const GIFRegTEX0& TEX0);
|
std::vector<GSVector2i>* GetPage2TileMap(const GIFRegTEX0& TEX0);
|
||||||
|
static bool IsPageAligned(u32 psm, const GSVector4i& rc);
|
||||||
|
|
||||||
// address
|
// address
|
||||||
|
|
||||||
|
|
|
@ -822,6 +822,28 @@ GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex)
|
||||||
return GSVector2i(width, height);
|
return GSVector2i(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GSRendererHW::IsPossibleChannelShuffle() const
|
||||||
|
{
|
||||||
|
if (!PRIM->TME || m_context->TEX0.PSM != PSM_PSMT8 || // 8-bit texture draw
|
||||||
|
m_vt.m_primclass != GS_SPRITE_CLASS) // draw_sprite_tex
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int mask = (((m_vt.m_max.p - m_vt.m_min.p) <= GSVector4(64.0f)).mask() & 0x3);
|
||||||
|
if (mask == 0x3) // single_page
|
||||||
|
return true;
|
||||||
|
else if (mask != 0x1) // Not a single page in width.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
if (m_context->TEX0.TBW == (m_context->FRAME.FBW * 2) && GSLocalMemory::IsPageAligned(m_context->FRAME.PSM, m_r))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GSRendererHW::IsSplitTextureShuffle()
|
bool GSRendererHW::IsSplitTextureShuffle()
|
||||||
{
|
{
|
||||||
// For this to work, we're peeking into the next draw, therefore we need dirty registers.
|
// For this to work, we're peeking into the next draw, therefore we need dirty registers.
|
||||||
|
@ -1552,6 +1574,9 @@ void GSRendererHW::Draw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The rectangle of the draw
|
||||||
|
m_r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(context->scissor.in));
|
||||||
|
|
||||||
if (m_channel_shuffle)
|
if (m_channel_shuffle)
|
||||||
{
|
{
|
||||||
// NFSU2 does consecutive channel shuffles with blending, reducing the alpha channel over time.
|
// NFSU2 does consecutive channel shuffles with blending, reducing the alpha channel over time.
|
||||||
|
@ -1564,20 +1589,12 @@ void GSRendererHW::Draw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (draw_sprite_tex && m_context->FRAME.Block() == m_context->TEX0.TBP0)
|
else if (m_context->FRAME.Block() == m_context->TEX0.TBP0 && IsPossibleChannelShuffle())
|
||||||
{
|
{
|
||||||
// Special post-processing effect
|
// Special post-processing effect
|
||||||
if ((m_context->TEX0.PSM == PSM_PSMT8) && single_page)
|
GL_INS("Possible channel shuffle effect detected");
|
||||||
{
|
m_channel_shuffle = true;
|
||||||
GL_INS("Channel shuffle effect detected");
|
m_last_channel_shuffle_fbmsk = m_context->FRAME.FBMSK;
|
||||||
m_channel_shuffle = true;
|
|
||||||
m_last_channel_shuffle_fbmsk = m_context->FRAME.FBMSK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GL_DBG("Special post-processing effect not supported");
|
|
||||||
m_channel_shuffle = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1591,9 +1608,6 @@ void GSRendererHW::Draw()
|
||||||
m_copy_16bit_to_target_shuffle = false;
|
m_copy_16bit_to_target_shuffle = false;
|
||||||
m_tex_is_fb = false;
|
m_tex_is_fb = false;
|
||||||
|
|
||||||
// The rectangle of the draw
|
|
||||||
m_r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(context->scissor.in));
|
|
||||||
|
|
||||||
const bool is_split_texture_shuffle = (m_split_texture_shuffle_pages > 0);
|
const bool is_split_texture_shuffle = (m_split_texture_shuffle_pages > 0);
|
||||||
if (is_split_texture_shuffle)
|
if (is_split_texture_shuffle)
|
||||||
{
|
{
|
||||||
|
@ -1887,7 +1901,7 @@ void GSRendererHW::Draw()
|
||||||
// Texture shuffle is not yet supported with strange clamp mode
|
// Texture shuffle is not yet supported with strange clamp mode
|
||||||
ASSERT(!m_texture_shuffle || (context->CLAMP.WMS < 3 && context->CLAMP.WMT < 3));
|
ASSERT(!m_texture_shuffle || (context->CLAMP.WMS < 3 && context->CLAMP.WMT < 3));
|
||||||
|
|
||||||
if (m_src->m_target && m_context->TEX0.PSM == PSM_PSMT8 && single_page && draw_sprite_tex)
|
if (m_src->m_target && IsPossibleChannelShuffle())
|
||||||
{
|
{
|
||||||
GL_INS("Channel shuffle effect detected (2nd shot)");
|
GL_INS("Channel shuffle effect detected (2nd shot)");
|
||||||
m_channel_shuffle = true;
|
m_channel_shuffle = true;
|
||||||
|
|
|
@ -97,6 +97,7 @@ private:
|
||||||
|
|
||||||
void SetTCOffset();
|
void SetTCOffset();
|
||||||
|
|
||||||
|
bool IsPossibleChannelShuffle() const;
|
||||||
bool IsSplitTextureShuffle();
|
bool IsSplitTextureShuffle();
|
||||||
GSVector4i GetSplitTextureShuffleDrawRect() const;
|
GSVector4i GetSplitTextureShuffleDrawRect() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue