mirror of https://github.com/PCSX2/pcsx2.git
GS-HW: Adjust clear detection for clears with FBMSK
This commit is contained in:
parent
c05743b7b9
commit
80b0bc0869
|
@ -563,6 +563,16 @@ int GSState::GetFramebufferHeight()
|
||||||
return frame_memory_height;
|
return frame_memory_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GSState::GetFramebufferBitDepth()
|
||||||
|
{
|
||||||
|
if (IsEnabled(0))
|
||||||
|
return GSLocalMemory::m_psm[m_regs->DISP[0].DISPFB.PSM].bpp;
|
||||||
|
else if (IsEnabled(1))
|
||||||
|
return GSLocalMemory::m_psm[m_regs->DISP[1].DISPFB.PSM].bpp;
|
||||||
|
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
int GSState::GetFramebufferWidth()
|
int GSState::GetFramebufferWidth()
|
||||||
{
|
{
|
||||||
const GSVector4i disp1_rect = GetFrameRect(0, true);
|
const GSVector4i disp1_rect = GetFrameRect(0, true);
|
||||||
|
|
|
@ -329,6 +329,7 @@ public:
|
||||||
|
|
||||||
int GetFramebufferHeight();
|
int GetFramebufferHeight();
|
||||||
int GetFramebufferWidth();
|
int GetFramebufferWidth();
|
||||||
|
int GetFramebufferBitDepth();
|
||||||
int GetDisplayHMagnification();
|
int GetDisplayHMagnification();
|
||||||
GSVector4i GetDisplayRect(int i = -1);
|
GSVector4i GetDisplayRect(int i = -1);
|
||||||
GSVector4i GetFrameMagnifiedRect(int i = -1);
|
GSVector4i GetFrameMagnifiedRect(int i = -1);
|
||||||
|
|
|
@ -1671,17 +1671,20 @@ void GSRendererHW::Draw()
|
||||||
|
|
||||||
if (!GSConfig.UserHacks_DisableSafeFeatures)
|
if (!GSConfig.UserHacks_DisableSafeFeatures)
|
||||||
{
|
{
|
||||||
if (IsConstantDirectWriteMemClear())
|
if (IsConstantDirectWriteMemClear(true))
|
||||||
{
|
{
|
||||||
// Likely doing a huge single page width clear, which never goes well. (Superman)
|
// Likely doing a huge single page width clear, which never goes well. (Superman)
|
||||||
// Burnout 3 does a 32x1024 double width clear on its reflection targets.
|
// Burnout 3 does a 32x1024 double width clear on its reflection targets.
|
||||||
const bool clear_height_valid = (m_r.w >= 1024);
|
const bool clear_height_valid = (m_r.w >= 1024);
|
||||||
if (clear_height_valid && context->FRAME.FBW == 1)
|
if (clear_height_valid && context->FRAME.FBW == 1)
|
||||||
{
|
{
|
||||||
|
u32 width = ceil(static_cast<float>(m_r.w) / GetFramebufferHeight()) * 64;
|
||||||
|
// Framebuffer is likely to be read as 16bit later, so we will need to double the width if the write is 32bit.
|
||||||
|
const bool double_width = GSLocalMemory::m_psm[context->FRAME.PSM].bpp == 32 && GetFramebufferBitDepth() == 16;
|
||||||
m_r.x = 0;
|
m_r.x = 0;
|
||||||
m_r.y = 0;
|
m_r.y = 0;
|
||||||
m_r.w = GetFramebufferHeight();
|
m_r.w = GetFramebufferHeight();
|
||||||
m_r.z = GetFramebufferWidth();
|
m_r.z = std::max((width * (double_width ? 2 : 1)), static_cast<u32>(GetFramebufferWidth()));
|
||||||
context->FRAME.FBW = (m_r.z + 63) / 64;
|
context->FRAME.FBW = (m_r.z + 63) / 64;
|
||||||
m_context->scissor.in.z = context->FRAME.FBW * 64;
|
m_context->scissor.in.z = context->FRAME.FBW * 64;
|
||||||
|
|
||||||
|
@ -1700,7 +1703,7 @@ void GSRendererHW::Draw()
|
||||||
// on. So, instead, let the draw go through with the expanded rectangle, and copy color->depth.
|
// on. So, instead, let the draw go through with the expanded rectangle, and copy color->depth.
|
||||||
const bool is_zero_clear = (((GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt == 0) ?
|
const bool is_zero_clear = (((GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt == 0) ?
|
||||||
m_vertex.buff[1].RGBAQ.U32[0] :
|
m_vertex.buff[1].RGBAQ.U32[0] :
|
||||||
(m_vertex.buff[1].RGBAQ.U32[0] & ~0xFF000000)) == 0);
|
(m_vertex.buff[1].RGBAQ.U32[0] & ~0xFF000000)) == 0) && m_context->FRAME.FBMSK == 0;
|
||||||
|
|
||||||
if (is_zero_clear && OI_GsMemClear() && clear_height_valid)
|
if (is_zero_clear && OI_GsMemClear() && clear_height_valid)
|
||||||
{
|
{
|
||||||
|
@ -1829,7 +1832,7 @@ void GSRendererHW::Draw()
|
||||||
|
|
||||||
if (!GSConfig.UserHacks_DisableSafeFeatures)
|
if (!GSConfig.UserHacks_DisableSafeFeatures)
|
||||||
{
|
{
|
||||||
if (IsConstantDirectWriteMemClear())
|
if (IsConstantDirectWriteMemClear(false))
|
||||||
OI_DoubleHalfClear(rt, ds);
|
OI_DoubleHalfClear(rt, ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4251,7 +4254,7 @@ bool GSRendererHW::OI_GsMemClear()
|
||||||
&& (m_context->FRAME.PSM & 0xF) == (m_context->ZBUF.PSM & 0xF) && m_vt.m_eq.z == 1 && m_vertex.buff[1].XYZ.Z == m_vertex.buff[1].RGBAQ.U32[0];
|
&& (m_context->FRAME.PSM & 0xF) == (m_context->ZBUF.PSM & 0xF) && m_vt.m_eq.z == 1 && m_vertex.buff[1].XYZ.Z == m_vertex.buff[1].RGBAQ.U32[0];
|
||||||
|
|
||||||
// Limit it further to a full screen 0 write
|
// Limit it further to a full screen 0 write
|
||||||
if (((m_vertex.next == 4) || (m_vertex.next == 2) || ZisFrame) && m_vt.m_eq.rgba == 0xFFFF)
|
if (((m_vertex.next == 2) || ZisFrame) && m_vt.m_eq.rgba == 0xFFFF)
|
||||||
{
|
{
|
||||||
const GSOffset& off = m_context->offset.fb;
|
const GSOffset& off = m_context->offset.fb;
|
||||||
GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
||||||
|
@ -4382,16 +4385,16 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSRendererHW::IsConstantDirectWriteMemClear()
|
bool GSRendererHW::IsConstantDirectWriteMemClear(bool include_zero)
|
||||||
{
|
{
|
||||||
// Constant Direct Write without texture/test/blending (aka a GS mem clear)
|
// Constant Direct Write without texture/test/blending (aka a GS mem clear)
|
||||||
if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME // Direct write
|
if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME // Direct write
|
||||||
&& (!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsCdOutput()) // No transparency
|
&& (!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsCdOutput()) // No transparency
|
||||||
&& (m_context->FRAME.FBMSK == 0) // no color mask
|
&& (m_context->FRAME.FBMSK == 0 || (include_zero && m_vt.m_max.c.eq(GSVector4i(0)))) // no color mask
|
||||||
&& !(m_env.SCANMSK.MSK & 2)
|
&& !(m_env.SCANMSK.MSK & 2)
|
||||||
&& !m_context->TEST.ATE // no alpha test
|
&& !m_context->TEST.ATE // no alpha test
|
||||||
&& (!m_context->TEST.ZTE || m_context->TEST.ZTST == ZTST_ALWAYS) // no depth test
|
&& (!m_context->TEST.ZTE || m_context->TEST.ZTST == ZTST_ALWAYS) // no depth test
|
||||||
&& (m_vt.m_eq.rgba == 0xFFFF) // constant color write
|
&& (m_vt.m_eq.rgba == 0xFFFF || m_vertex.next == 2) // constant color write
|
||||||
&& m_r.x == 0 && m_r.y == 0) // Likely full buffer write
|
&& m_r.x == 0 && m_r.y == 0) // Likely full buffer write
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ private:
|
||||||
float alpha1(int L, int X0, int X1);
|
float alpha1(int L, int X0, int X1);
|
||||||
void SwSpriteRender();
|
void SwSpriteRender();
|
||||||
bool CanUseSwSpriteRender();
|
bool CanUseSwSpriteRender();
|
||||||
bool IsConstantDirectWriteMemClear();
|
bool IsConstantDirectWriteMemClear(bool include_zero);
|
||||||
|
|
||||||
enum class CLUTDrawTestResult
|
enum class CLUTDrawTestResult
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue