From 1e343084e23bdee07b38e9fb69526c755a210d16 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Tue, 20 Sep 2016 18:57:07 +0200 Subject: [PATCH] gsdx hw: group the double half clear with gs mem clear hack It avoid redundant check of the GS context You can disable the extra clear with UserHacks_DisableGsMemClear = 1 --- plugins/GSdx/GSRendererHW.cpp | 59 +++++++++++++++-------------------- plugins/GSdx/GSRendererHW.h | 2 +- plugins/GSdx/GSdx.cpp | 1 - 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 68d0a5564d..fd5e8cb41f 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -692,7 +692,18 @@ void GSRendererHW::Draw() } if (!m_userhacks_disable_gs_mem_clear) { - OI_GsMemClear(); + // Constant Direct Write without texture/test/blending (aka a GS mem clear) + if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME && !PRIM->ABE // Direct write + && (m_context->FRAME.FBMSK == 0) // no color mask + && !m_context->TEST.ATE // no alpha test + && (!m_context->TEST.ZTE || m_context->TEST.ZTST == ZTST_ALWAYS) // no depth test + && (m_vt.m_eq.rgba == 0xFFFF) // constant color write + && r.x == 0 && r.y == 0) { // Likely full buffer write + + OI_GsMemClear(); + + OI_DoubleHalfClear(rt_tex, ds_tex); + } } // skip alpha test if possible @@ -875,11 +886,6 @@ GSRendererHW::Hacks::Hacks() m_oi_list.push_back(HackEntry(CRC::SuperManReturns, CRC::RegionCount, &GSRendererHW::OI_SuperManReturns)); m_oi_list.push_back(HackEntry(CRC::ArTonelico2, CRC::RegionCount, &GSRendererHW::OI_ArTonelico2)); m_oi_list.push_back(HackEntry(CRC::ItadakiStreet, CRC::RegionCount, &GSRendererHW::OI_ItadakiStreet)); - // Enable it by default in the future (hack ought to be safe enough) - m_oi_list.push_back(HackEntry(CRC::SimpsonsGame, CRC::RegionCount, &GSRendererHW::OI_DoubleHalfClear)); - m_oi_list.push_back(HackEntry(CRC::TyTasmanianTiger, CRC::RegionCount, &GSRendererHW::OI_DoubleHalfClear)); - m_oi_list.push_back(HackEntry(CRC::TyTasmanianTiger2, CRC::RegionCount, &GSRendererHW::OI_DoubleHalfClear)); - m_oi_list.push_back(HackEntry(CRC::FFVIIDoC, CRC::RegionCount, &GSRendererHW::OI_DoubleHalfClear)); if (!can_handle_depth) m_oi_list.push_back(HackEntry(CRC::SMTNocturne, CRC::RegionCount, &GSRendererHW::OI_SMTNocturne)); @@ -905,34 +911,28 @@ void GSRendererHW::Hacks::SetGameCRC(const CRC::Game& game) m_oi = &GSRendererHW::OI_PointListPalette; } - - bool hack = theApp.GetConfigB("UserHacks_ColorDepthClearOverlap") && theApp.GetConfigB("UserHacks"); - if (hack && !m_oi) { - // FIXME: Enable this code in the future. I think it could replace - // most of the "old" OI hack. So far code was tested on GoW2 & SimpsonsGame with - // success - m_oi = &GSRendererHW::OI_DoubleHalfClear; - } } -// Handle case where the frame buffer and the Z buffer overlap -bool GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) +// Trick to do a fast clear on the GS +// Set frame buffer pointer on the start of the buffer. Set depth buffer pointer on the half buffer +// FB + depth write will fill the full buffer. +void GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds) { - // Trick to do a fast clear on the GS - // Set frame buffer pointer on the start of the buffer. Set depth buffer pointer on the half buffer - // FB + depth write will fill the full buffer. - if ((m_vt.m_primclass == GS_SPRITE_CLASS) && !PRIM->TME && !m_context->ZBUF.ZMSK && rt && ds) { + // Note gs mem clear must be tested before calling this function + + // Limit further to unmask Z write + if (!m_context->ZBUF.ZMSK && rt && ds) { const GSVertex* v = &m_vertex.buff[0]; const GSLocalMemory::psm_t& frame_psm = GSLocalMemory::m_psm[m_context->FRAME.PSM]; const GSLocalMemory::psm_t& depth_psm = GSLocalMemory::m_psm[m_context->ZBUF.PSM]; // Z and color must be constant and the same if (m_vt.m_eq.rgba != 0xFFFF || !m_vt.m_eq.z || v[1].XYZ.Z != v[1].RGBAQ.u32[0]) - return true; + return; // Format doesn't have the same size. It smells fishy if (frame_psm.trbpp != depth_psm.trbpp) - return true; + return; // Size of the current draw uint32 w_pages = roundf(m_vt.m_max.p.x / frame_psm.pgs.x); @@ -963,24 +963,17 @@ bool GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCac } else { m_dev->ClearRenderTarget(rt, color); } - - // warning: draw call mustn't be skipped to keep correct invalidation. Don't return false } } - - return true; } // Note: hack is safe, but it could impact the perf a little (normally games do only a couple of clear by frame) void GSRendererHW::OI_GsMemClear() { - // Rectangle draw without texture - if ((m_vt.m_primclass == GS_SPRITE_CLASS) && (m_vertex.next == 2) && !PRIM->TME && !PRIM->ABE // Direct write - && (m_context->FRAME.FBMSK == 0) - && !m_context->TEST.ATE // no alpha test - && (!m_context->TEST.ZTE || m_context->TEST.ZTST == ZTST_ALWAYS) // no depth test - && (m_vt.m_eq.rgba == 0xFFFF && m_vt.m_min.c.eq(GSVector4i(0))) // Constant 0 write - ) { + // Note gs mem clear must be tested before calling this function + + // Limit it further to a full screen 0 write + if ((m_vertex.next == 2) && m_vt.m_min.c.eq(GSVector4i(0))) { 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)); // Limit the hack to a single fullscreen clear. Some games might use severals column to clear a screen diff --git a/plugins/GSdx/GSRendererHW.h b/plugins/GSdx/GSRendererHW.h index 9f69533831..688d4feb32 100644 --- a/plugins/GSdx/GSRendererHW.h +++ b/plugins/GSdx/GSRendererHW.h @@ -50,8 +50,8 @@ private: // Require special argument bool OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Source* t, const GSVector4i& r_draw); void OI_GsMemClear(); // always on + void OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds); // always on - bool OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_DoubleHalfClear_Vertical(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp index bb027d00bd..b3aaa04858 100644 --- a/plugins/GSdx/GSdx.cpp +++ b/plugins/GSdx/GSdx.cpp @@ -337,7 +337,6 @@ void GSdxApp::Init() m_default_configuration["UserHacks_AlphaHack"] = "0"; m_default_configuration["UserHacks_AlphaStencil"] = "0"; m_default_configuration["UserHacks_AutoFlush"] = "0"; - m_default_configuration["UserHacks_ColorDepthClearOverlap"] = "0"; m_default_configuration["UserHacks_DisableDepthSupport"] = "0"; m_default_configuration["UserHacks_DisableGsMemClear"] = "0"; m_default_configuration["UserHacks_DisablePartialInvalidation"] = "0";