From cf13cccb1e7fb6a88a927792f818420daeaa8a28 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 2 Oct 2016 17:46:12 +0200 Subject: [PATCH 1/5] gsdx: avoid useless spamming of INVALID PSM in release build --- plugins/GSdx/GSState.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 1661d86f22..93b02e4ddd 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -843,7 +843,9 @@ template void GSState::ApplyTEX0(GIFRegTEX0& TEX0) TEX0.PSM = PSM_PSMT8; // International Star Soccer (menu) break; default: - fprintf(stderr, "INVALID PSM !!!\n"); +#ifdef ENABLE_OGL_DEBUG + fprintf(stderr, "%d:INVALID PSM 0x%x !!!\n", s_n, TEX0.PSM); +#endif break; } From dc365e066d3ded8afc7811581be14d9d769bde69 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 25 Sep 2016 16:19:27 +0200 Subject: [PATCH 2/5] gsdx tc: remove old plain TEXA hack It must work fine without it now. From the google code comments: It would be nice to test those games * Ar Tonelico 2 (line in sprite regression?) * breath of fire dragon quarter (overlayed user interface in the game) v2: update Dx code to use the good format --- plugins/GSdx/GSRendererDX.cpp | 8 ++++++-- plugins/GSdx/GSRendererHW.cpp | 14 -------------- plugins/GSdx/GSTextureCache.cpp | 28 ++++------------------------ 3 files changed, 10 insertions(+), 40 deletions(-) diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index d356cbdb35..a672643172 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -474,8 +474,12 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc { const GSLocalMemory::psm_t &psm = GSLocalMemory::m_psm[m_context->TEX0.PSM]; const GSLocalMemory::psm_t &cpsm = psm.pal > 0 ? GSLocalMemory::m_psm[m_context->TEX0.CPSM] : psm; + // The texture cache will handle various format conversion internally for non-target texture + // After the conversion the texture will be RGBA8 (aka 32 bits) hence the 0 below + int gpu_tex_fmt = (tex->m_target) ? cpsm.fmt : 0; + bool bilinear = m_filter == 2 ? m_vt.IsLinear() : m_filter != 0; - bool simple_sample = !tex->m_palette && cpsm.fmt == 0 && m_context->CLAMP.WMS < 3 && m_context->CLAMP.WMT < 3; + bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 3 && m_context->CLAMP.WMT < 3; // Don't force extra filtering on sprite (it creates various upscaling issue) bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear()); @@ -484,7 +488,7 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc if (ps_sel.shuffle) { ps_sel.fmt = 0; } else { - ps_sel.fmt = tex->m_palette ? cpsm.fmt | 4 : cpsm.fmt; + ps_sel.fmt = tex->m_palette ? gpu_tex_fmt | 4 : gpu_tex_fmt; } ps_sel.aem = m_env.TEXA.AEM; ps_sel.tfx = m_context->TEX0.TFX; diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index c34c69cb96..8c1edb6c13 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -548,16 +548,8 @@ void GSRendererHW::Draw() m_context->offset.tex = m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM); - /* - - // m_tc->LookupSource will mess with the palette, should not, but we do this after, until it is sorted out - if(tex_psm.pal > 0) - { m_mem.m_clut.Read32(context->TEX0, env.TEXA); - } - - */ GSVector4i r; @@ -565,12 +557,6 @@ void GSRendererHW::Draw() tex = tex_psm.depth ? m_tc->LookupDepthSource(TEX0, env.TEXA, r) : m_tc->LookupSource(TEX0, env.TEXA, r); - // FIXME: Could be removed on openGL - if(tex_psm.pal > 0) - { - m_mem.m_clut.Read32(TEX0, env.TEXA); - } - // Hypothesis: texture shuffle is used as a postprocessing effect so texture will be an old target. // Initially code also tested the RT but it gives too much false-positive // diff --git a/plugins/GSdx/GSTextureCache.cpp b/plugins/GSdx/GSTextureCache.cpp index 84695dab38..29a7715fb4 100644 --- a/plugins/GSdx/GSTextureCache.cpp +++ b/plugins/GSdx/GSTextureCache.cpp @@ -178,17 +178,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con //const GSLocalMemory::psm_t& cpsm = psm.pal > 0 ? GSLocalMemory::m_psm[TEX0.CPSM] : psm; // Until DX is fixed - if (s_IS_OPENGL) { - if(psm_s.pal > 0) - m_renderer->m_mem.m_clut.Read32(TEX0, TEXA); - } else { - GIFRegTEXA plainTEXA; - - plainTEXA.AEM = 1; - plainTEXA.TA0 = 0; - plainTEXA.TA1 = 0x80; - m_renderer->m_mem.m_clut.Read32(TEX0, plainTEXA); - } + if(psm_s.pal > 0) + m_renderer->m_mem.m_clut.Read32(TEX0, TEXA); const uint32* clut = m_renderer->m_mem.m_clut; @@ -1671,17 +1662,6 @@ void GSTextureCache::Source::Flush(uint32 count) GSLocalMemory::readTexture rtx = psm.rtx; - GIFRegTEXA plainTEXA; - - // Until DX is fixed - if (s_IS_OPENGL) { - plainTEXA = m_TEXA; - } else { - plainTEXA.AEM = 1; - plainTEXA.TA0 = 0; - plainTEXA.TA1 = 0x80; - } - if(m_palette) { pitch >>= 2; @@ -1706,13 +1686,13 @@ void GSTextureCache::Source::Flush(uint32 count) if(m_texture->Map(m, &r)) { - (mem.*rtx)(off, r, m.bits, m.pitch, plainTEXA); + (mem.*rtx)(off, r, m.bits, m.pitch, m_TEXA); m_texture->Unmap(); } else { - (mem.*rtx)(off, r, buff, pitch, plainTEXA); + (mem.*rtx)(off, r, buff, pitch, m_TEXA); m_texture->Update(r, buff, pitch); } From c3ac3ecbe7a87f7a999782c7118b126291d1d48b Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 25 Sep 2016 18:56:48 +0200 Subject: [PATCH 3/5] gsdx hw: move try alpha test at the beginning Will allow to use alpha test optimization to better optimize depth lookup Require to do clut handling before --- plugins/GSdx/GSRendererHW.cpp | 40 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 8c1edb6c13..0074317431 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -406,6 +406,27 @@ void GSRendererHW::Draw() GSDrawingEnvironment& env = m_env; GSDrawingContext* context = m_context; + const GSLocalMemory::psm_t& tex_psm = GSLocalMemory::m_psm[m_context->TEX0.PSM]; + + // skip alpha test if possible + // Note: do it first so we know if frame/depth writes are masked + + GIFRegTEST TEST = context->TEST; + GIFRegFRAME FRAME = context->FRAME; + GIFRegZBUF ZBUF = context->ZBUF; + + uint32 fm = context->FRAME.FBMSK; + uint32 zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0; + + // Note required to compute TryAlphaTest below. So do it now. + if (PRIM->TME && tex_psm.pal > 0) + m_mem.m_clut.Read32(context->TEX0, env.TEXA); + + // Test if we can optimize Alpha Test as a NOP + m_ATE = context->TEST.ATE && !GSRenderer::TryAlphaTest(fm, zm); + + context->FRAME.FBMSK = fm; + context->ZBUF.ZMSK = zm != 0; // It is allowed to use the depth and rt at the same location. However at least 1 must // be disabled. @@ -480,7 +501,6 @@ void GSRendererHW::Draw() if(PRIM->TME) { - const GSLocalMemory::psm_t& tex_psm = GSLocalMemory::m_psm[m_context->TEX0.PSM]; int lod = 0; GIFRegCLAMP MIP_CLAMP = context->CLAMP; @@ -548,9 +568,6 @@ void GSRendererHW::Draw() m_context->offset.tex = m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM); - if(tex_psm.pal > 0) - m_mem.m_clut.Read32(context->TEX0, env.TEXA); - GSVector4i r; GetTextureMinMax(r, TEX0, MIP_CLAMP, m_vt.IsLinear()); @@ -661,21 +678,6 @@ void GSRendererHW::Draw() } } - // skip alpha test if possible - - GIFRegTEST TEST = context->TEST; - GIFRegFRAME FRAME = context->FRAME; - GIFRegZBUF ZBUF = context->ZBUF; - - uint32 fm = context->FRAME.FBMSK; - uint32 zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0; - - // Test if we can optimize Alpha Test as a NOP - m_ATE = context->TEST.ATE && !GSRenderer::TryAlphaTest(fm, zm); - - context->FRAME.FBMSK = fm; - context->ZBUF.ZMSK = zm != 0; - // A couple of hack to avoid upscaling issue. So far it seems to impacts mostly sprite // Note: first hack corrects both position and texture coordinate // Note: second hack corrects only the texture coordinate From 7f4791fa853b02c2cb29cbab530b7349f6795424 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 25 Sep 2016 19:00:33 +0200 Subject: [PATCH 4/5] gsdx hw: improve no_ds detection Support ZTST_NEVER as no depth read => psx mode speed boost Use zm/fm to reduce further depth lookup --- plugins/GSdx/GSRendererHW.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 0074317431..de59b8c88f 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -429,17 +429,17 @@ void GSRendererHW::Draw() context->ZBUF.ZMSK = zm != 0; // It is allowed to use the depth and rt at the same location. However at least 1 must - // be disabled. + // be disabled. Or the written value must be the same on both channels. // 1/ GoW uses a Cd blending on a 24 bits buffer (no alpha) // 2/ SuperMan really draws (0,0,0,0) color and a (0) 32-bits depth // 3/ 50cents really draws (0,0,0,128) color and a (0) 24 bits depth // Note: FF DoC has both buffer at same location but disable the depth test (write?) with ZTE = 0 const bool no_rt = (context->ALPHA.IsCd() && PRIM->ABE && (context->FRAME.PSM == 1)); const bool no_ds = !no_rt && ( - // Depth is always pass (no read) and write are discarded (tekken 5). (Note: DATE is currently implemented with a stencil buffer) - (context->ZBUF.ZMSK && m_context->TEST.ZTST == ZTST_ALWAYS && !m_context->TEST.DATE) || + // Depth is always pass/fail (no read) and write are discarded (tekken 5). (Note: DATE is currently implemented with a stencil buffer => a depth/stencil buffer) + (zm != 0 && m_context->TEST.ZTST <= ZTST_ALWAYS && !m_context->TEST.DATE) || // Depth will be written through the RT - (context->FRAME.FBP == context->ZBUF.ZBP && !PRIM->TME && !context->ZBUF.ZMSK && !context->FRAME.FBMSK && context->TEST.ZTE) + (context->FRAME.FBP == context->ZBUF.ZBP && !PRIM->TME && zm == 0 && fm == 0 && context->TEST.ZTE) ); const bool draw_sprite_tex = PRIM->TME && (m_vt.m_primclass == GS_SPRITE_CLASS); From 49c44db6357362ddd9db99f9d9368033c926ccc2 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 2 Oct 2016 17:19:16 +0200 Subject: [PATCH 5/5] gsdx:dx: make filtering right WMS/WMT 2 is the region clamping mode. Hw unit can't emulate it right so it can give you bad filtering (Fix #1025) Note: I only did the fix because I wanted to remove the TEXA hack. Otherwise it is still recommended to use openGL --- plugins/GSdx/GSRendererDX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/GSdx/GSRendererDX.cpp b/plugins/GSdx/GSRendererDX.cpp index a672643172..e874c8bee9 100644 --- a/plugins/GSdx/GSRendererDX.cpp +++ b/plugins/GSdx/GSRendererDX.cpp @@ -479,7 +479,7 @@ void GSRendererDX::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc int gpu_tex_fmt = (tex->m_target) ? cpsm.fmt : 0; bool bilinear = m_filter == 2 ? m_vt.IsLinear() : m_filter != 0; - bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 3 && m_context->CLAMP.WMT < 3; + bool simple_sample = !tex->m_palette && gpu_tex_fmt == 0 && m_context->CLAMP.WMS < 2 && m_context->CLAMP.WMT < 2; // Don't force extra filtering on sprite (it creates various upscaling issue) bilinear &= !((m_vt.m_primclass == GS_SPRITE_CLASS) && m_userhacks_round_sprite_offset && !m_vt.IsLinear());