gsdx: lupin 3 fix, texture addressing outside the limits, only for sw and opencl yet

This commit is contained in:
gabest11 2015-08-04 13:27:08 +02:00
parent d631030608
commit 42f51591df
7 changed files with 115 additions and 14 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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()

View File

@ -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;