From 8e5e770fd12f9c9b2cdd266846af3e84ac39da94 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sat, 19 Mar 2016 13:35:23 +0100 Subject: [PATCH] gsdx hw: Ensure GS memory is always cleared properly It will fix some issues on FMV Previous behavior can be restored with the hack "UserHacks_DisableGsMemClear" Fix #768 And maybe #855 --- plugins/GSdx/GSRendererHW.cpp | 31 +++++++++++++++++++++++++++++++ plugins/GSdx/GSRendererHW.h | 4 ++++ 2 files changed, 35 insertions(+) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 0f8a23feae..b4859d94cd 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -34,6 +34,7 @@ GSRendererHW::GSRendererHW(GSTextureCache* tc) m_userhacks_skipdraw = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_SkipDraw", 0) : 0; m_userhacks_align_sprite_X = !!theApp.GetConfig("UserHacks_align_sprite_X", 0) && !!theApp.GetConfig("UserHacks", 0); m_userhacks_round_sprite_offset = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_round_sprite_offset", 0) : 0; + m_userhacks_disable_gs_mem_clear = theApp.GetConfig("UserHacks_DisableGsMemClear", 0) && theApp.GetConfig("UserHacks", 0); if (!m_upscale_multiplier) { //Custom Resolution m_width = theApp.GetConfig("resx", m_width); @@ -488,6 +489,10 @@ void GSRendererHW::Draw() return; } + if (!m_userhacks_disable_gs_mem_clear) { + OI_GsMemClear(); + } + // skip alpha test if possible GIFRegTEST TEST = context->TEST; @@ -748,6 +753,32 @@ bool GSRendererHW::OI_DoubleHalfClear(GSTexture* rt, GSTexture* ds, GSTextureCac 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) { + // 0 clear + if (m_vt.m_eq.rgba == 0xFFFF && m_vt.m_min.c.eq(GSVector4i(0))) { + GL_INS("OI_GsMemClear"); + 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)); + + // Based on WritePixel32 + for(int y = r.top; y < r.bottom; y++) + { + uint32* RESTRICT d = &m_mem.m_vm32[off->pixel.row[y]]; + int* RESTRICT col = off->pixel.col[0]; + + for(int x = r.left; x < r.right; x++) + { + d[col[x]] = 0; // Here the constant color + } + } + } + } +} + // OI (others input?/implementation?) hacks replace current draw call bool GSRendererHW::OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) diff --git a/plugins/GSdx/GSRendererHW.h b/plugins/GSdx/GSRendererHW.h index dd5d866ac5..83272e7899 100644 --- a/plugins/GSdx/GSRendererHW.h +++ b/plugins/GSdx/GSRendererHW.h @@ -38,6 +38,7 @@ private: int m_userhacks_skipdraw; bool m_userhacks_align_sprite_X; + bool m_userhacks_disable_gs_mem_clear; #pragma region hacks @@ -45,6 +46,9 @@ private: typedef void (GSRendererHW::*OO_Ptr)(); typedef bool (GSRendererHW::*CU_Ptr)(); + // Require special argument + void OI_GsMemClear(); // always on + bool OI_DoubleHalfClear(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);