gsdx tc: re-implement frame lookup

Try to avoid random black screen frame

v2: don't force the preload hack on the frame
It creates a ghost image over FMV

v3: support offset within a frame
This commit is contained in:
Gregory Hainaut 2016-03-19 12:37:25 +01:00
parent eec74fd963
commit 063d2e568a
12 changed files with 73 additions and 15 deletions

View File

@ -192,19 +192,22 @@ bool GSRenderer::Merge(int field)
GSVector2i ds(0, 0);
GSTexture* tex[2] = {NULL, NULL};
int y_offset[2] = {0, 0};
if(samesrc && fr[0].bottom == fr[1].bottom)
{
tex[0] = GetOutput(0);
tex[0] = GetOutput(0, y_offset[0]);
tex[1] = tex[0]; // saves one texture fetch
y_offset[1] = y_offset[0];
}
else
{
if(en[0]) tex[0] = GetOutput(0);
if(en[1]) tex[1] = GetOutput(1);
if(en[0]) tex[0] = GetOutput(0, y_offset[0]);
if(en[1]) tex[1] = GetOutput(1, y_offset[1]);
}
GSVector4 src[2];
GSVector4 src_hw[2];
GSVector4 dst[2];
for(int i = 0; i < 2; i++)
@ -224,6 +227,7 @@ bool GSRenderer::Merge(int field)
GSVector4 scale = GSVector4(tex[i]->GetScale()).xyxy();
src[i] = GSVector4(r) * scale / GSVector4(tex[i]->GetSize()).xyxy();
src_hw[i] = (GSVector4(r) + GSVector4 (0, y_offset[i], 0, y_offset[i])) * scale / GSVector4(tex[i]->GetSize()).xyxy();
GSVector2 off(0, 0);
@ -264,7 +268,7 @@ bool GSRenderer::Merge(int field)
GSVector4 c = GSVector4((int)m_regs->BGCOLOR.R, (int)m_regs->BGCOLOR.G, (int)m_regs->BGCOLOR.B, (int)m_regs->PMODE.ALP) / 255;
m_dev->Merge(tex, src, dst, fs, slbg, mmod, c);
m_dev->Merge(tex, src_hw, dst, fs, slbg, mmod, c);
if(m_regs->SMODE2.INT && m_interlace > 0)
{

View File

@ -50,7 +50,7 @@ protected:
bool m_shadeboost;
bool m_texture_shuffle;
virtual GSTexture* GetOutput(int i) = 0;
virtual GSTexture* GetOutput(int i, int& y_offset) = 0;
public:
GSWnd* m_wnd;

View File

@ -157,7 +157,7 @@ void GSRendererCL::ResetDevice()
}
}
GSTexture* GSRendererCL::GetOutput(int i)
GSTexture* GSRendererCL::GetOutput(int i, int& y_offset)
{
const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB;

View File

@ -251,7 +251,7 @@ protected:
void Reset();
void VSync(int field);
void ResetDevice();
GSTexture* GetOutput(int i);
GSTexture* GetOutput(int i, int& y_offset);
void Draw();
void Sync(int reason);

View File

@ -338,7 +338,7 @@ void GSRendererCS::VSync(int field)
//printf("%lld\n", m_perfmon.GetFrame());
}
GSTexture* GSRendererCS::GetOutput(int i)
GSTexture* GSRendererCS::GetOutput(int i, int& y_offset)
{
// TODO: create a compute shader which unswizzles the frame from m_vm to the output texture

View File

@ -134,7 +134,7 @@ protected:
bool CreateDevice(GSDevice* dev);
void ResetDevice();
void VSync(int field);
GSTexture* GetOutput(int i);
GSTexture* GetOutput(int i, int& y_offset);
void Draw();
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut);

View File

@ -151,7 +151,7 @@ void GSRendererHW::ResetDevice()
GSRenderer::ResetDevice();
}
GSTexture* GSRendererHW::GetOutput(int i)
GSTexture* GSRendererHW::GetOutput(int i, int& y_offset)
{
const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB;
@ -169,6 +169,13 @@ GSTexture* GSRendererHW::GetOutput(int i)
{
t = rt->m_texture;
int delta = TEX0.TBP0 - rt->m_TEX0.TBP0;
if (delta > 0) {
ASSERT(DISPFB.PSM == PSM_PSMCT32 || DISPFB.PSM == PSM_PSMCT24);
y_offset = delta / DISPFB.FBW;
GL_CACHE("Frame y offset %d pixels, unit %d", y_offset, i);
}
#ifndef NDEBUG
if(s_dump)
{

View File

@ -165,7 +165,7 @@ public:
void Reset();
void VSync(int field);
void ResetDevice();
GSTexture* GetOutput(int i);
GSTexture* GetOutput(int i, int& y_offset);
void InvalidateVideoMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r);
void InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GSVector4i& r, bool clut = false);
void Draw();

View File

@ -36,7 +36,7 @@ protected:
{
}
GSTexture* GetOutput(int i)
GSTexture* GetOutput(int i, int& y_offset)
{
return NULL;
}

View File

@ -231,7 +231,7 @@ void GSRendererSW::ResetDevice()
}
}
GSTexture* GSRendererSW::GetOutput(int i)
GSTexture* GSRendererSW::GetOutput(int i, int& y_offset)
{
Sync(1);

View File

@ -78,7 +78,7 @@ protected:
void Reset();
void VSync(int field);
void ResetDevice();
GSTexture* GetOutput(int i);
GSTexture* GetOutput(int i, int& y_offset);
void Draw();
void Queue(shared_ptr<GSRasterizerData>& item);

View File

@ -416,6 +416,52 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int
Target* dst = NULL;
#if 0
// Dump the list of targets for debug
for(auto t : m_dst[RenderTarget]) {
GL_INS("TC: frame 0x%x -> 0x%x : %d (age %d)", t->m_TEX0.TBP0, t->m_end_block, t->m_texture->GetID(), t->m_age);
}
#endif
// Let's try to find a perfect frame that contains valid data
for(auto t : m_dst[RenderTarget]) {
if(bp == t->m_TEX0.TBP0 && t->m_end_block > bp) {
dst = t;
GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: %d (0x%x -> 0x%x)", w, h, dst->m_texture->GetID(), bp, t->m_end_block);
break;
}
}
// 2nd try ! Try to find a frame that include the bp
if (dst == NULL) {
for(auto t : m_dst[RenderTarget]) {
if (t->m_TEX0.TBP0 < bp && bp < t->m_end_block) {
dst = t;
GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: %d (0x%x, took 0x%x -> 0x%x)", w, h, t->m_texture->GetID(), bp, t->m_TEX0.TBP0, t->m_end_block);
break;
}
}
}
// 3rd try ! Try to find a frame that doesn't contain valid data (honestly I'm not sure we need to do it)
if (dst == NULL) {
for(auto t : m_dst[RenderTarget]) {
if(bp == t->m_TEX0.TBP0) {
dst = t;
GL_CACHE("TC: Lookup Frame %dx%d, empty hit: %d (0x%x -> 0x%x)", w, h, dst->m_texture->GetID(), bp, t->m_end_block);
break;
}
}
}
#if 0
for(list<Target*>::iterator i = m_dst[RenderTarget].begin(); i != m_dst[RenderTarget].end(); i++)
{
Target* t = *i;
@ -439,6 +485,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, int
}
}
}
#endif
if(dst == NULL)
{