From 42f51591df66c3b82d353dc6bb6aad7e14d1127d Mon Sep 17 00:00:00 2001 From: gabest11 Date: Tue, 4 Aug 2015 13:27:08 +0200 Subject: [PATCH] gsdx: lupin 3 fix, texture addressing outside the limits, only for sw and opencl yet --- plugins/GSdx/GSDrawingContext.h | 82 +++++++++++++++++++++++++++++++++ plugins/GSdx/GSRenderer.cpp | 1 - plugins/GSdx/GSRenderer.h | 1 - plugins/GSdx/GSRendererCL.cpp | 16 +++++-- plugins/GSdx/GSRendererSW.cpp | 20 +++++--- plugins/GSdx/GSState.cpp | 7 +++ plugins/GSdx/GSState.h | 2 + 7 files changed, 115 insertions(+), 14 deletions(-) diff --git a/plugins/GSdx/GSDrawingContext.h b/plugins/GSdx/GSDrawingContext.h index ef54e543d6..7f76434278 100644 --- a/plugins/GSdx/GSDrawingContext.h +++ b/plugins/GSdx/GSDrawingContext.h @@ -125,6 +125,88 @@ public: return ZBUF.ZMSK == 0 && TEST.ZTE != 0; // ZTE == 0 is bug on the real hardware, write is blocked then } + GIFRegTEX0 GetSizeFixedTEX0(const GSVector4i& uvmax, bool mipmap) + { + // find max value for TW/TH by analyzing vertex trace and clamp values, only for region clamp modes, no mipmaping allowed + + if(mipmap) return TEX0; + + int tw = TEX0.TW; + int th = TEX0.TH; + + int wms = (int)CLAMP.WMS; + int wmt = (int)CLAMP.WMT; + + int minu = (int)CLAMP.MINU; + int minv = (int)CLAMP.MINV; + int maxu = (int)CLAMP.MAXU; + int maxv = (int)CLAMP.MAXV; + + GSVector4i uv = uvmax;// GSVector4i(m_vt.m_max.t.ceil()); + + if(wms == CLAMP_REGION_CLAMP) + { + int x = uv.x; + + if(x < minu) x = minu; + if(x > maxu + 1) x = maxu + 1; + + while(tw < 10 && (1 << tw) < x) + { + tw++; + } + } + else if(wms == CLAMP_REGION_REPEAT) + { + int x = maxu + (minu + 1); + + while(tw < 10 && (1 << tw) < x) + { + tw++; + } + } + + if(wmt == CLAMP_REGION_CLAMP) + { + int y = uv.y; + + if(y < minv) y = minv; + if(y > maxv + 1) y = maxv + 1; + + while(th < 10 && (1 << th) < y) + { + th++; + } + } + else if(wmt == CLAMP_REGION_REPEAT) + { + int y = maxv + (minv + 1); + + while(th < 10 && (1 << th) < y) + { + th++; + } + } + +#ifdef _DEBUG + if(TEX0.TW != tw || TEX0.TH != th) + { + printf("FixedTEX0 %05x %d %d tw %d=>%d th %d=>%d uvmax %d,%d wm %d,%d (%d,%d,%d,%d)\n", + (int)TEX0.TBP0, (int)TEX0.TBW, (int)TEX0.PSM, + (int)TEX0.TW, tw, (int)TEX0.TH, th, + uv.x, uv.y, + wms, wmt, minu, maxu, minv, maxv); + } +#endif + + GIFRegTEX0 res = TEX0; + + res.TW = tw; + res.TH = th; + + return res; + } + void Dump(const std::string& filename) { // Append on purpose so env + context are merged into a single file diff --git a/plugins/GSdx/GSRenderer.cpp b/plugins/GSdx/GSRenderer.cpp index 64a9b8f027..a246ad472a 100644 --- a/plugins/GSdx/GSRenderer.cpp +++ b/plugins/GSdx/GSRenderer.cpp @@ -40,7 +40,6 @@ GSRenderer::GSRenderer() m_filter = theApp.GetConfig("filter", 1); m_vsync = !!theApp.GetConfig("vsync", 0); m_aa1 = !!theApp.GetConfig("aa1", 0); - m_mipmap = !!theApp.GetConfig("mipmap", 1); m_fxaa = !!theApp.GetConfig("fxaa", 0); m_shaderfx = !!theApp.GetConfig("shaderfx", 0); m_shadeboost = !!theApp.GetConfig("ShadeBoost", 0); diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h index 64f82e3d37..332a7aa0b5 100644 --- a/plugins/GSdx/GSRenderer.h +++ b/plugins/GSdx/GSRenderer.h @@ -45,7 +45,6 @@ protected: int m_filter; bool m_vsync; bool m_aa1; - bool m_mipmap; bool m_framelimit; bool m_shaderfx; bool m_fxaa; diff --git a/plugins/GSdx/GSRendererCL.cpp b/plugins/GSdx/GSRendererCL.cpp index e3e4224803..960bf657c7 100644 --- a/plugins/GSdx/GSRendererCL.cpp +++ b/plugins/GSdx/GSRendererCL.cpp @@ -1440,9 +1440,15 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver sel.tfx = TFX_DECAL; } + GSVector4i uvmax = GSVector4i(m_vt.m_max.t.ceil()); + + bool mipmap = IsMipMapActive(); + + GIFRegTEX0 TEX0 = m_context->GetSizeFixedTEX0(uvmax, mipmap); + GSVector4i r; - GetTextureMinMax(r, context->TEX0, context->CLAMP, sel.ltf); + GetTextureMinMax(r, TEX0, context->CLAMP, sel.ltf); GSVector4i* src_pages = job->GetSrcPages(); @@ -1455,7 +1461,7 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver src_pages[i] |= m_tmp_pages[i]; } - if(m_mipmap && context->TEX1.MXL > 0 && context->TEX1.MMIN >= 2 && context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0) + if(mipmap) { // TEX1.MMIN // 000 p @@ -1521,7 +1527,7 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver pb->k = (float)k; } - GIFRegTEX0 MIP_TEX0 = context->TEX0; + GIFRegTEX0 MIP_TEX0 = TEX0; GIFRegCLAMP MIP_CLAMP = context->CLAMP; GSVector4 tmin = m_vt.m_min.t; @@ -1638,8 +1644,8 @@ bool GSRendererCL::SetupParameter(TFXJob* job, TFXParameter* pb, GSVertexCL* ver } } - int tw = 1 << context->TEX0.TW; - int th = 1 << context->TEX0.TH; + int tw = 1 << TEX0.TW; + int th = 1 << TEX0.TH; switch(context->CLAMP.WMS) { diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index 43bc1d5db9..44bde051a1 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -1121,19 +1121,25 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data) gd.sel.tfx = TFX_DECAL; } - GSTextureCacheSW::Texture* t = m_tc->Lookup(context->TEX0, env.TEXA); + GSVector4i uvmax = GSVector4i(m_vt.m_max.t.ceil()); - if(t == NULL) {ASSERT(0); return false;} + bool mipmap = IsMipMapActive(); + + GIFRegTEX0 TEX0 = m_context->GetSizeFixedTEX0(uvmax, mipmap); GSVector4i r; - GetTextureMinMax(r, context->TEX0, context->CLAMP, gd.sel.ltf); + GetTextureMinMax(r, TEX0, context->CLAMP, gd.sel.ltf); + + GSTextureCacheSW::Texture* t = m_tc->Lookup(TEX0, env.TEXA); + + if(t == NULL) {ASSERT(0); return false;} data->SetSource(t, r, 0); gd.sel.tw = t->m_tw - 3; - if(m_mipmap && context->TEX1.MXL > 0 && context->TEX1.MMIN >= 2 && context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0) + if(mipmap) { // TEX1.MMIN // 000 p @@ -1200,7 +1206,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data) gd.k = GSVector4((float)k); } - GIFRegTEX0 MIP_TEX0 = context->TEX0; + GIFRegTEX0 MIP_TEX0 = TEX0; GIFRegCLAMP MIP_CLAMP = context->CLAMP; GSVector4 tmin = m_vt.m_min.t; @@ -1329,8 +1335,8 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data) } } - uint16 tw = 1u << context->TEX0.TW; - uint16 th = 1u << context->TEX0.TH; + uint16 tw = 1u << TEX0.TW; + uint16 th = 1u << TEX0.TH; switch(context->CLAMP.WMS) { diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index be60ef2b97..f14186b3cf 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -47,6 +47,7 @@ GSState::GSState() , m_crcinited(false) { m_nativeres = !!theApp.GetConfig("nativeres", 1); + m_mipmap = !!theApp.GetConfig("mipmap", 1); s_n = 0; s_dump = !!theApp.GetConfig("dump", 0); @@ -2713,6 +2714,7 @@ void GSState::GetTextureMinMax(GSVector4i& r, const GIFRegTEX0& TEX0, const GIFR int mask = 0; // See commented code below for the meaning of mask + if(wms == CLAMP_REPEAT || wmt == CLAMP_REPEAT) { u = uv & GSVector4i::xffffffff().srl32(32 - tw); @@ -2985,6 +2987,11 @@ bool GSState::IsOpaque() return context->ALPHA.IsOpaque(amin, amax); } +bool GSState::IsMipMapActive() +{ + return m_mipmap && m_context->TEX1.MXL > 0 && m_context->TEX1.MMIN >= 2 && m_context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0; +} + // GSTransferBuffer GSState::GSTransferBuffer::GSTransferBuffer() diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index 9c155a739c..6a9954464a 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -184,6 +184,7 @@ protected: void GetAlphaMinMax(); bool TryAlphaTest(uint32& fm, uint32& zm); bool IsOpaque(); + bool IsMipMapActive(); public: GIFPath m_path[4]; @@ -201,6 +202,7 @@ public: CRC::Game m_game; GSDump m_dump; bool m_nativeres; + bool m_mipmap; int s_n; bool s_dump;