From 029d74f8552127cc34c456d1b6f3a7a768c76db9 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 8 Sep 2016 17:25:59 +0200 Subject: [PATCH] gsdx: add an auto flush hack to implement a Read Write GS effect. It impacts all renderers. It ought to fix issue in GTA radiosity, Shadows in Jak series. (note shadows will suck in upscaling) Implementation is really brutal. Expect a massive slow down, but at least we can test the effect easily. Normally perf impact will remain reasonable if the game doesn't use a Read-Write effect Performances number are welcomes (my guess is really awful in HW mode, slow in SW mode). You can enable it with "UserHacks_AutoFlush = 1" --- plugins/GSdx/GSState.cpp | 79 ++++++++++++++++++++++++---------------- plugins/GSdx/GSState.h | 15 ++++---- plugins/GSdx/GSdx.cpp | 1 + 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 14dc9e9dd8..0f47612033 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -47,6 +47,7 @@ GSState::GSState() m_mipmap = theApp.GetConfigB("mipmap"); m_NTSC_Saturation = theApp.GetConfigB("NTSC_Saturation"); m_userhacks_skipdraw = theApp.GetConfigB("UserHacks") ? theApp.GetConfigI("UserHacks_SkipDraw") : 0; + m_userhacks_auto_flush = theApp.GetConfigB("UserHacks") ? theApp.GetConfigB("UserHacks_AutoFlush") : 0; s_n = 0; s_dump = theApp.GetConfigB("dump"); @@ -271,26 +272,37 @@ void GSState::ResetHandlers() m_fpGIFPackedRegHandlers[GIF_REG_A_D] = &GSState::GIFPackedRegHandlerA_D; m_fpGIFPackedRegHandlers[GIF_REG_NOP] = &GSState::GIFPackedRegHandlerNOP; - #define SetHandlerXYZ(P) \ - m_fpGIFPackedRegHandlerXYZ[P][0] = &GSState::GIFPackedRegHandlerXYZF2; \ - m_fpGIFPackedRegHandlerXYZ[P][1] = &GSState::GIFPackedRegHandlerXYZF2; \ - m_fpGIFPackedRegHandlerXYZ[P][2] = &GSState::GIFPackedRegHandlerXYZ2; \ - m_fpGIFPackedRegHandlerXYZ[P][3] = &GSState::GIFPackedRegHandlerXYZ2; \ - m_fpGIFRegHandlerXYZ[P][0] = &GSState::GIFRegHandlerXYZF2; \ - m_fpGIFRegHandlerXYZ[P][1] = &GSState::GIFRegHandlerXYZF2; \ - m_fpGIFRegHandlerXYZ[P][2] = &GSState::GIFRegHandlerXYZ2; \ - m_fpGIFRegHandlerXYZ[P][3] = &GSState::GIFRegHandlerXYZ2; \ - m_fpGIFPackedRegHandlerSTQRGBAXYZF2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZF2

; \ - m_fpGIFPackedRegHandlerSTQRGBAXYZ2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZ2

; \ + #define SetHandlerXYZ(P, auto_flush) \ + m_fpGIFPackedRegHandlerXYZ[P][0] = &GSState::GIFPackedRegHandlerXYZF2; \ + m_fpGIFPackedRegHandlerXYZ[P][1] = &GSState::GIFPackedRegHandlerXYZF2; \ + m_fpGIFPackedRegHandlerXYZ[P][2] = &GSState::GIFPackedRegHandlerXYZ2; \ + m_fpGIFPackedRegHandlerXYZ[P][3] = &GSState::GIFPackedRegHandlerXYZ2; \ + m_fpGIFRegHandlerXYZ[P][0] = &GSState::GIFRegHandlerXYZF2; \ + m_fpGIFRegHandlerXYZ[P][1] = &GSState::GIFRegHandlerXYZF2; \ + m_fpGIFRegHandlerXYZ[P][2] = &GSState::GIFRegHandlerXYZ2; \ + m_fpGIFRegHandlerXYZ[P][3] = &GSState::GIFRegHandlerXYZ2; \ + m_fpGIFPackedRegHandlerSTQRGBAXYZF2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZF2; \ + m_fpGIFPackedRegHandlerSTQRGBAXYZ2[P] = &GSState::GIFPackedRegHandlerSTQRGBAXYZ2; \ - SetHandlerXYZ(GS_POINTLIST); - SetHandlerXYZ(GS_LINELIST); - SetHandlerXYZ(GS_LINESTRIP); - SetHandlerXYZ(GS_TRIANGLELIST); - SetHandlerXYZ(GS_TRIANGLESTRIP); - SetHandlerXYZ(GS_TRIANGLEFAN); - SetHandlerXYZ(GS_SPRITE); - SetHandlerXYZ(GS_INVALID); + if (m_userhacks_auto_flush) { + SetHandlerXYZ(GS_POINTLIST, true); + SetHandlerXYZ(GS_LINELIST, true); + SetHandlerXYZ(GS_LINESTRIP, true); + SetHandlerXYZ(GS_TRIANGLELIST, true); + SetHandlerXYZ(GS_TRIANGLESTRIP, true); + SetHandlerXYZ(GS_TRIANGLEFAN, true); + SetHandlerXYZ(GS_SPRITE, true); + SetHandlerXYZ(GS_INVALID, true); + } else { + SetHandlerXYZ(GS_POINTLIST, false); + SetHandlerXYZ(GS_LINELIST, false); + SetHandlerXYZ(GS_LINESTRIP, false); + SetHandlerXYZ(GS_TRIANGLELIST, false); + SetHandlerXYZ(GS_TRIANGLESTRIP, false); + SetHandlerXYZ(GS_TRIANGLEFAN, false); + SetHandlerXYZ(GS_SPRITE, false); + SetHandlerXYZ(GS_INVALID, false); + } for(size_t i = 0; i < countof(m_fpGIFRegHandlers); i++) { @@ -558,7 +570,7 @@ void GSState::GIFPackedRegHandlerUV_Hack(const GIFPackedReg* RESTRICT r) isPackedUV_HackFlag = true; } -template +template void GSState::GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r) { /* @@ -574,10 +586,10 @@ void GSState::GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r) m_v.m[1] = xy.upl32(zf); - VertexKick(adc ? 1 : r->XYZF2.Skip()); + VertexKick(adc ? 1 : r->XYZF2.Skip()); } -template +template void GSState::GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r) { /* @@ -591,7 +603,7 @@ void GSState::GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r) m_v.m[1] = xyz.upl64(GSVector4i::loadl(&m_v.UV)); - VertexKick(adc ? 1 : r->XYZ2.Skip()); + VertexKick(adc ? 1 : r->XYZ2.Skip()); } void GSState::GIFPackedRegHandlerFOG(const GIFPackedReg* RESTRICT r) @@ -608,7 +620,7 @@ void GSState::GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r) { } -template +template void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, uint32 size) { ASSERT(size > 0 && size % 3 == 0); @@ -637,7 +649,7 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, ui m_v.m[1] = xy.upl32(zf); // TODO: only store the last one - VertexKick(r[2].XYZF2.Skip()); + VertexKick(r[2].XYZF2.Skip()); r += 3; } @@ -645,7 +657,7 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, ui m_q = r[-3].STQ.Q; // remember the last one, STQ outputs this to the temp Q each time } -template +template void GSState::GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uint32 size) { ASSERT(size > 0 && size % 3 == 0); @@ -673,7 +685,7 @@ void GSState::GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uin m_v.m[1] = xyz.upl64(GSVector4i::loadl(&m_v.UV)); // TODO: only store the last one - VertexKick(r[2].XYZ2.Skip()); + VertexKick(r[2].XYZ2.Skip()); r += 3; } @@ -772,7 +784,7 @@ void GSState::GIFRegHandlerUV_Hack(const GIFReg* RESTRICT r) isPackedUV_HackFlag = false; } -template +template void GSState::GIFRegHandlerXYZF2(const GIFReg* RESTRICT r) { /* @@ -794,17 +806,17 @@ void GSState::GIFRegHandlerXYZF2(const GIFReg* RESTRICT r) m_v.m[1] = xyz.upl64(uvf); - VertexKick(adc); + VertexKick(adc); } -template +template void GSState::GIFRegHandlerXYZ2(const GIFReg* RESTRICT r) { // m_v.XYZ = (GSVector4i)r->XYZ; m_v.m[1] = GSVector4i::load(&r->XYZ, &m_v.UV); - VertexKick(adc); + VertexKick(adc); } template void GSState::ApplyTEX0(GIFRegTEX0& TEX0) @@ -2455,7 +2467,7 @@ void GSState::GrowVertexBuffer() m_index.buff = index; } -template +template __forceinline void GSState::VertexKick(uint32 skip) { ASSERT(m_vertex.tail < m_vertex.maxcount + 3); @@ -2688,6 +2700,9 @@ __forceinline void GSState::VertexKick(uint32 skip) default: __assume(0); } + + if (auto_flush && PRIM->TME && (m_context->FRAME.Block() == m_context->TEX0.TBP0)) + FlushPrim(); } void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFRegCLAMP& CLAMP, bool linear) diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index 90d8206bb5..b6d824fae4 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -62,8 +62,8 @@ class GSState : public GSAlignedClass<32> void GIFPackedRegHandlerSTQ(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerUV(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerUV_Hack(const GIFPackedReg* RESTRICT r); - template void GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r); - template void GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r); + template void GIFPackedRegHandlerXYZF2(const GIFPackedReg* RESTRICT r); + template void GIFPackedRegHandlerXYZ2(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerFOG(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerA_D(const GIFPackedReg* RESTRICT r); void GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r); @@ -79,8 +79,8 @@ class GSState : public GSAlignedClass<32> GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZF2[8]; GIFPackedRegHandlerC m_fpGIFPackedRegHandlerSTQRGBAXYZ2[8]; - template void GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, uint32 size); - template void GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uint32 size); + template void GIFPackedRegHandlerSTQRGBAXYZF2(const GIFPackedReg* RESTRICT r, uint32 size); + template void GIFPackedRegHandlerSTQRGBAXYZ2(const GIFPackedReg* RESTRICT r, uint32 size); void GIFPackedRegHandlerNOP(const GIFPackedReg* RESTRICT r, uint32 size); template void ApplyTEX0(GIFRegTEX0& TEX0); @@ -92,8 +92,8 @@ class GSState : public GSAlignedClass<32> void GIFRegHandlerST(const GIFReg* RESTRICT r); void GIFRegHandlerUV(const GIFReg* RESTRICT r); void GIFRegHandlerUV_Hack(const GIFReg* RESTRICT r); - template void GIFRegHandlerXYZF2(const GIFReg* RESTRICT r); - template void GIFRegHandlerXYZ2(const GIFReg* RESTRICT r); + template void GIFRegHandlerXYZF2(const GIFReg* RESTRICT r); + template void GIFRegHandlerXYZ2(const GIFReg* RESTRICT r); template void GIFRegHandlerTEX0(const GIFReg* RESTRICT r); template void GIFRegHandlerCLAMP(const GIFReg* RESTRICT r); void GIFRegHandlerFOG(const GIFReg* RESTRICT r); @@ -163,6 +163,7 @@ protected: GetSkipCount m_gsc; int m_skip; int m_userhacks_skipdraw; + bool m_userhacks_auto_flush; GSVertex m_v; float m_q; @@ -191,7 +192,7 @@ protected: void GrowVertexBuffer(); - template + template void VertexKick(uint32 skip); // following functions need m_vt to be initialized diff --git a/plugins/GSdx/GSdx.cpp b/plugins/GSdx/GSdx.cpp index 2014b377d0..a14fc4a68b 100644 --- a/plugins/GSdx/GSdx.cpp +++ b/plugins/GSdx/GSdx.cpp @@ -336,6 +336,7 @@ void GSdxApp::Init() m_default_configuration["UserHacks_align_sprite_X"] = "0"; 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";