From 3b127f663bc899235fcefb47a7cbd2c8e1fd6534 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Wed, 17 Jun 2015 20:02:03 +0200 Subject: [PATCH] gsdx-tc: trace the texture format to detect texture shuffling It fixes games that uses 16 bits RT (like snow engine games) --- plugins/GSdx/GSRenderer.h | 1 + plugins/GSdx/GSRendererDX.cpp | 2 +- plugins/GSdx/GSRendererHW.cpp | 7 +++++++ plugins/GSdx/GSRendererOGL.cpp | 2 +- plugins/GSdx/GSRendererSW.cpp | 4 +++- plugins/GSdx/GSTextureCache.cpp | 12 +++++------- plugins/GSdx/GSTextureCache.h | 1 + 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h index ad4eb22e64..64f82e3d37 100644 --- a/plugins/GSdx/GSRenderer.h +++ b/plugins/GSdx/GSRenderer.h @@ -50,6 +50,7 @@ protected: bool m_shaderfx; bool m_fxaa; bool m_shadeboost; + bool m_texture_shuffle; virtual GSTexture* GetOutput(int i) = 0; diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index d3559ad6d8..a1d976289a 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -225,7 +225,7 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc GSDeviceDX::PSSamplerSelector ps_ssel; GSDeviceDX::PSConstantBuffer ps_cb; - if ((context->FRAME.PSM == 0x2) && ((context->TEX0.PSM & 3) == 2) && (m_vt.m_primclass == GS_SPRITE_CLASS)) { + if (m_texture_shuffle) { ps_sel.shuffle = 1; ps_sel.fmt = 0; diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index d84bc6ba5d..6242005bb7 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -361,6 +361,7 @@ void GSRendererHW::Draw() } GSTextureCache::Source* tex = NULL; + m_texture_shuffle = false; if(PRIM->TME) { @@ -395,6 +396,12 @@ void GSRendererHW::Draw() { m_mem.m_clut.Read32(context->TEX0, env.TEXA); } + + if (rt) { + rt->m_32_bits_fmt |= tex->m_32_bits_fmt; + } + // Both input and output are 16 bits but texture was initially 32 bits! + m_texture_shuffle = ((context->FRAME.PSM & 0x2) && ((context->TEX0.PSM & 3) == 2) && (m_vt.m_primclass == GS_SPRITE_CLASS) && tex->m_32_bits_fmt); } if(s_dump) diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index 3a2a411075..0e3b82f070 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -247,7 +247,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour GSDeviceOGL::OMColorMaskSelector om_csel; GSDeviceOGL::OMDepthStencilSelector om_dssel; - if ((context->FRAME.PSM & 0x2) && ((context->TEX0.PSM & 3) == 2) && (m_vt.m_primclass == GS_SPRITE_CLASS)) { + if (m_texture_shuffle) { ps_sel.shuffle = 1; ps_sel.dfmt = 0; diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index 23474ab176..38cab98da7 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -516,6 +516,8 @@ void GSRendererSW::Draw() Sync(2); uint64 frame = m_perfmon.GetFrame(); + // Dump the texture in 32 bits format. It helps to debug texture shuffle effect + // It will breaks the few games that really uses 16 bits RT bool texture_shuffle = ((context->FRAME.PSM & 0x2) && ((context->TEX0.PSM & 3) == 2) && (m_vt.m_primclass == GS_SPRITE_CLASS)); string s; @@ -531,7 +533,7 @@ void GSRendererSW::Draw() if(s_savet && s_n >= s_saven && PRIM->TME) { if (texture_shuffle) { - // Dump the texture in 32 bits format. It helps to debug texture shuffle effect + // Dump the RT in 32 bits format. It helps to debug texture shuffle effect s = format("%05d_f%lld_tex_%05x_32bits.bmp", s_n, frame, (int)m_context->TEX0.TBP0); m_mem.SaveBMP(root_sw+s, m_context->TEX0.TBP0, m_context->TEX0.TBW, 0, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH); diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 9b3a4e5dad..6985d0a581 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -223,13 +223,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int dst = t; -#if 0 - // Likely the root cause of tons and tons of bug - if (dst->m_TEX0.PSM != TEX0.PSM) { - GL_INS("TC: ERROR: use a target with format 0x%x as 0x%x without any conversion", dst->m_TEX0.PSM, TEX0.PSM); - } -#endif - + dst->m_32_bits_fmt |= !(TEX0.PSM & 2); dst->m_TEX0 = TEX0; break; @@ -256,6 +250,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int if(!t->m_age && bp == t->m_TEX0.TBP0) { dst = CreateTarget(TEX0, w, h, type); + if (type == DepthStencil) { GL_CACHE("TC: Lookup Target(Depth) %dx%d, hit Color (0x%x, F:0x%x)", w, h, bp, TEX0.PSM); int shader = (TEX0.PSM & 1) ? 13 : 12; @@ -753,6 +748,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con if (dst) { // TODO: clean up this mess + src->m_32_bits_fmt = dst->m_32_bits_fmt; src->m_target = true; @@ -1011,6 +1007,7 @@ GSTextureCache::Surface::Surface(GSRenderer* r, uint8* temp) , m_texture(NULL) , m_age(0) , m_temp(temp) + , m_32_bits_fmt(false) { m_TEX0.TBP0 = 0x3fff; } @@ -1270,6 +1267,7 @@ GSTextureCache::Target::Target(GSRenderer* r, const GIFRegTEX0& TEX0, uint8* tem , m_depth_supported(depth_supported) { m_TEX0 = TEX0; + m_32_bits_fmt |= !(TEX0.PSM & 2); m_valid = GSVector4i::zero(); } diff --git a/plugins/GSdx/GSTextureCache.h b/plugins/GSdx/GSTextureCache.h index 5cbb8d5681..dc679bf345 100644 --- a/plugins/GSdx/GSTextureCache.h +++ b/plugins/GSdx/GSTextureCache.h @@ -40,6 +40,7 @@ public: GIFRegTEXA m_TEXA; int m_age; uint8* m_temp; + bool m_32_bits_fmt; // Allow to detect the casting of 32 bits as 16 bits texture public: Surface(GSRenderer* r, uint8* temp);