mirror of https://github.com/PCSX2/pcsx2.git
gsdx tc:invalidate RT when a texture is written inside it
It often happens the game try to upload the FMV directly which typically gave a black screen. Commit fix rules of roses and I hope various black screen FMV Performance impact must be tested, and I'm afraid of strange texture cache behavior. V2: check the size of the transfer too V3: add support of 16 bits format V4: avoid division by 0
This commit is contained in:
parent
9aea76b0e8
commit
d922225e69
|
@ -1417,7 +1417,7 @@ void GSState::FlushWrite()
|
|||
r.bottom = r.top + m_env.TRXREG.RRH;
|
||||
|
||||
InvalidateVideoMem(m_env.BITBLTBUF, r);
|
||||
|
||||
|
||||
//int y = m_tr.y;
|
||||
|
||||
GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
|
||||
|
|
|
@ -662,48 +662,69 @@ void GSTextureCache::InvalidateVideoMem(GSOffset* off, const GSVector4i& rect, b
|
|||
}
|
||||
|
||||
// GH: Try to detect texture write that will overlap with a target buffer
|
||||
if(GSUtil::HasSharedBits(psm, t->m_TEX0.PSM) && bp < t->m_TEX0.TBP0)
|
||||
{
|
||||
uint32 rowsize = bw * 8192;
|
||||
uint32 offset = (uint32)((t->m_TEX0.TBP0 - bp) * 256);
|
||||
|
||||
if(rowsize > 0 && offset % rowsize == 0)
|
||||
if(GSUtil::HasSharedBits(psm, t->m_TEX0.PSM)) {
|
||||
if (bp < t->m_TEX0.TBP0)
|
||||
{
|
||||
uint32 rowsize = bw * 8192;
|
||||
uint32 offset = (uint32)((t->m_TEX0.TBP0 - bp) * 256);
|
||||
|
||||
if(rowsize > 0 && offset % rowsize == 0)
|
||||
{
|
||||
int y = GSLocalMemory::m_psm[psm].pgs.y * offset / rowsize;
|
||||
|
||||
if(r.bottom > y)
|
||||
{
|
||||
GL_CACHE("TC: Dirty After Target(%s) %d (0x%x)", to_string(type),
|
||||
t->m_texture ? t->m_texture->GetID() : 0,
|
||||
t->m_TEX0.TBP0);
|
||||
// TODO: do not add this rect above too
|
||||
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top - y, r.right, r.bottom - y), psm));
|
||||
t->m_TEX0.TBW = bw;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: this code "fixes" black FMV issue with rule of rose.
|
||||
// Code is completely hardcoded so maybe not the best solution. Besides I don't
|
||||
// know the full impact of it.
|
||||
// Let's keep this code for the future
|
||||
#if 0
|
||||
if(GSUtil::HasSharedBits(psm, t->m_TEX0.PSM) && (t->m_TEX0.TBP0 + 0x200 == bp))
|
||||
{
|
||||
GL_CACHE("TC: Dirty in the middle of Target(%s) %d (0x%x)", to_string(type),
|
||||
t->m_texture ? t->m_texture->GetID() : 0,
|
||||
t->m_TEX0.TBP0);
|
||||
|
||||
uint32 rowsize = bw * 8192u;
|
||||
uint32 offset = 0x200 * 256u;
|
||||
int y = GSLocalMemory::m_psm[psm].pgs.y * offset / rowsize;
|
||||
|
||||
if(r.bottom > y)
|
||||
{
|
||||
GL_CACHE("TC: Dirty After Target(%s) %d (0x%x)", to_string(type),
|
||||
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top + y, r.right, r.bottom + y), psm));
|
||||
t->m_TEX0.TBW = bw;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
// Greg: I'm not sure the 'bw' equality is required but it won't hurt too much
|
||||
if (t->m_TEX0.TBW == bw && t->Inside(bp, psm, rect)) {
|
||||
uint32 rowsize = bw * 8192u;
|
||||
uint32 offset = (uint32)((bp - t->m_TEX0.TBP0) * 256);
|
||||
|
||||
if(rowsize > 0 && offset % rowsize == 0) {
|
||||
GL_CACHE("TC: Dirty in the middle of Target(%s) %d (0x%x)", to_string(type),
|
||||
t->m_texture ? t->m_texture->GetID() : 0,
|
||||
t->m_TEX0.TBP0);
|
||||
// TODO: do not add this rect above too
|
||||
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top - y, r.right, r.bottom - y), psm));
|
||||
|
||||
int y = GSLocalMemory::m_psm[psm].pgs.y * offset / rowsize;
|
||||
|
||||
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top + y, r.right, r.bottom + y), psm));
|
||||
t->m_TEX0.TBW = bw;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: this code "fixes" black FMV issue with rule of rose.
|
||||
// Code is completely hardcoded so maybe not the best solution. Besides I don't
|
||||
// know the full impact of it.
|
||||
// Let's keep this code for the future
|
||||
#if 0
|
||||
if(GSUtil::HasSharedBits(psm, t->m_TEX0.PSM) && (t->m_TEX0.TBP0 + 0x200 == bp))
|
||||
{
|
||||
GL_CACHE("TC: Dirty in the middle of Target(%s) %d (0x%x)", to_string(type),
|
||||
t->m_texture ? t->m_texture->GetID() : 0,
|
||||
t->m_TEX0.TBP0);
|
||||
|
||||
uint32 rowsize = bw * 8192u;
|
||||
uint32 offset = 0x200 * 256u;
|
||||
int y = GSLocalMemory::m_psm[psm].pgs.y * offset / rowsize;
|
||||
|
||||
t->m_dirty.push_back(GSDirtyRect(GSVector4i(r.left, r.top + y, r.right, r.bottom + y), psm));
|
||||
t->m_TEX0.TBW = bw;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1600,13 +1621,13 @@ void GSTextureCache::Target::Update()
|
|||
// Copy the new GS memory content into the destination texture.
|
||||
if(m_type == RenderTarget)
|
||||
{
|
||||
GL_INS("ERROR: Update RenderTarget");
|
||||
GL_INS("ERROR: Update RenderTarget 0x%x", m_TEX0.TBP0);
|
||||
|
||||
m_renderer->m_dev->StretchRect(t, m_texture, GSVector4(r) * GSVector4(m_texture->GetScale()).xyxy());
|
||||
}
|
||||
else if(m_type == DepthStencil)
|
||||
{
|
||||
GL_INS("ERROR: Update DepthStencil");
|
||||
GL_INS("ERROR: Update DepthStencil 0x%x", m_TEX0.TBP0);
|
||||
|
||||
// FIXME linear or not?
|
||||
m_renderer->m_dev->StretchRect(t, m_texture, GSVector4(r) * GSVector4(m_texture->GetScale()).xyxy(), ShaderConvert_RGBA8_TO_FLOAT32);
|
||||
|
@ -1615,16 +1636,29 @@ void GSTextureCache::Target::Update()
|
|||
m_renderer->m_dev->Recycle(t);
|
||||
}
|
||||
|
||||
void GSTextureCache::Target::UpdateValidity(const GSVector4i& r)
|
||||
void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect)
|
||||
{
|
||||
m_valid = m_valid.runion(r);
|
||||
m_valid = m_valid.runion(rect);
|
||||
|
||||
// TODO: assumption: format is 32 bits
|
||||
uint32 nb_block = m_TEX0.TBW * m_valid.height();
|
||||
if (m_TEX0.PSM == PSM_PSMCT16)
|
||||
nb_block >>= 1;
|
||||
|
||||
m_end_block = m_TEX0.TBP0 + nb_block;
|
||||
//fprintf(stderr, "S: 0x%x E:0x%x\n", m_TEX0.TBP0, m_end_block);
|
||||
}
|
||||
|
||||
bool GSTextureCache::Target::Inside(uint32 bp, uint32 psm, const GSVector4i& rect)
|
||||
{
|
||||
uint32 nb_block = rect.height() * rect.width();
|
||||
if (m_TEX0.PSM == PSM_PSMCT16)
|
||||
nb_block >>= 7;
|
||||
else
|
||||
nb_block >>= 6;
|
||||
|
||||
return bp > m_TEX0.TBP0 && (bp + nb_block) < m_end_block;
|
||||
}
|
||||
|
||||
// GSTextureCache::SourceMap
|
||||
|
||||
void GSTextureCache::SourceMap::Add(Source* s, const GIFRegTEX0& TEX0, const GSOffset* off)
|
||||
|
|
|
@ -88,7 +88,8 @@ public:
|
|||
public:
|
||||
Target(GSRenderer* r, const GIFRegTEX0& TEX0, uint8* temp, bool depth_supported);
|
||||
|
||||
void UpdateValidity(const GSVector4i& r);
|
||||
void UpdateValidity(const GSVector4i& rect);
|
||||
bool Inside(uint32 bp, uint32 psm, const GSVector4i& rect);
|
||||
|
||||
virtual void Update();
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue