mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
eec74fd963
commit
063d2e568a
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -36,7 +36,7 @@ protected:
|
|||
{
|
||||
}
|
||||
|
||||
GSTexture* GetOutput(int i)
|
||||
GSTexture* GetOutput(int i, int& y_offset)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -231,7 +231,7 @@ void GSRendererSW::ResetDevice()
|
|||
}
|
||||
}
|
||||
|
||||
GSTexture* GSRendererSW::GetOutput(int i)
|
||||
GSTexture* GSRendererSW::GetOutput(int i, int& y_offset)
|
||||
{
|
||||
Sync(1);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue