mirror of https://github.com/PCSX2/pcsx2.git
GS: Only copy texture coverage area for current FRAME/Z sources
This commit is contained in:
parent
b344ee094f
commit
8181cc8528
|
@ -162,6 +162,13 @@ void GSRendererHW::PurgeTextureCache()
|
|||
m_tc->RemoveAll();
|
||||
}
|
||||
|
||||
bool GSRendererHW::IsPossibleTextureShuffle(GSTextureCache::Source* src) const
|
||||
{
|
||||
return (PRIM->TME && m_vt.m_primclass == GS_SPRITE_CLASS &&
|
||||
src->m_32_bits_fmt && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == 16 &&
|
||||
GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp == 16);
|
||||
}
|
||||
|
||||
void GSRendererHW::SetGameCRC(u32 crc, int options)
|
||||
{
|
||||
GSRenderer::SetGameCRC(crc, options);
|
||||
|
@ -1711,6 +1718,11 @@ void GSRendererHW::Draw()
|
|||
|
||||
//
|
||||
|
||||
// Temporary source *must* be invalidated before normal, because otherwise it'll be double freed.
|
||||
m_tc->InvalidateTemporarySource();
|
||||
|
||||
//
|
||||
|
||||
if ((fm & fm_mask) != fm_mask && rt)
|
||||
{
|
||||
//rt->m_valid = rt->m_valid.runion(r);
|
||||
|
|
|
@ -186,4 +186,7 @@ public:
|
|||
|
||||
// Called by the texture cache to know if current texture is useful
|
||||
virtual bool IsDummyTexture() const { return false; }
|
||||
|
||||
// Called by the texture cache when optimizing the copy range for sources
|
||||
bool IsPossibleTextureShuffle(GSTextureCache::Source* src) const;
|
||||
};
|
||||
|
|
|
@ -391,7 +391,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con
|
|||
GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, psm_str(TEX0.PSM));
|
||||
}
|
||||
#endif
|
||||
src = CreateSource(TEX0, TEXA, dst, half_right, x_offset, y_offset, lod);
|
||||
src = CreateSource(TEX0, TEXA, dst, half_right, x_offset, y_offset, lod, &r);
|
||||
new_source = true;
|
||||
}
|
||||
else
|
||||
|
@ -1165,7 +1165,7 @@ void GSTextureCache::IncAge()
|
|||
}
|
||||
|
||||
//Fixme: Several issues in here. Not handling depth stencil, pitch conversion doesnt work.
|
||||
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, bool half_right, int x_offset, int y_offset, const GSVector2i* lod)
|
||||
GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* dst, bool half_right, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range)
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
Source* src = new Source(m_renderer, TEX0, TEXA, false);
|
||||
|
@ -1340,8 +1340,10 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
|
||||
GSVector2 scale = is_8bits ? GSVector2(1, 1) : dst->m_texture->GetScale();
|
||||
|
||||
GSVector4i sRect(0, 0, w, h);
|
||||
const bool use_texture = shader == ShaderConvert::COPY;
|
||||
GSVector4i sRect(0, 0, w, h);
|
||||
int destX = 0;
|
||||
int destY = 0;
|
||||
|
||||
if (half_right)
|
||||
{
|
||||
|
@ -1361,6 +1363,27 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
DevCon.Error("Invalid half-right copy with width %d from %dx%d texture", half_width * 2, w, h);
|
||||
}
|
||||
}
|
||||
else if (src_range && dst->m_TEX0.TBW == TEX0.TBW && !is_8bits)
|
||||
{
|
||||
// optimization for TBP == FRAME
|
||||
const GSDrawingContext* const context = m_renderer->m_context;
|
||||
if (context->FRAME.Block() == TEX0.TBP0 || context->ZBUF.Block() == TEX0.TBP0)
|
||||
{
|
||||
// if it looks like a texture shuffle, we might read up to +/- 8 pixels on either side.
|
||||
GSVector4 adjusted_src_range(*src_range);
|
||||
if (static_cast<GSRendererHW*>(m_renderer)->IsPossibleTextureShuffle(src))
|
||||
adjusted_src_range += GSVector4(-8.0f, 0.0f, 8.0f, 0.0f);
|
||||
|
||||
// don't forget to scale the copy range
|
||||
adjusted_src_range = adjusted_src_range * GSVector4(scale).xyxy();
|
||||
sRect = sRect.rintersect(GSVector4i(adjusted_src_range));
|
||||
destX = sRect.x;
|
||||
destY = sRect.y;
|
||||
|
||||
// clean up immediately afterwards
|
||||
m_temporary_source = src;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't be fooled by the name. 'dst' is the old target (hence the input)
|
||||
// 'src' is the new texture cache entry (hence the output)
|
||||
|
@ -1380,7 +1403,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
|
||||
if (use_texture)
|
||||
{
|
||||
g_gs_device->CopyRect(sTex, dTex, sRect, 0, 0);
|
||||
g_gs_device->CopyRect(sTex, dTex, sRect, destX, destY);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1388,7 +1411,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
|||
sRectF.z /= sTex->GetWidth();
|
||||
sRectF.w /= sTex->GetHeight();
|
||||
|
||||
g_gs_device->StretchRect(sTex, sRectF, dTex, GSVector4(0, 0, w, h), shader, false);
|
||||
g_gs_device->StretchRect(sTex, sRectF, dTex, GSVector4(destX, destY, w, h), shader, false);
|
||||
}
|
||||
|
||||
if (src->m_texture)
|
||||
|
@ -2439,6 +2462,15 @@ GSTextureCache::SurfaceOffset GSTextureCache::ComputeSurfaceOffset(const Surface
|
|||
return so;
|
||||
}
|
||||
|
||||
void GSTextureCache::InvalidateTemporarySource()
|
||||
{
|
||||
if (!m_temporary_source)
|
||||
return;
|
||||
|
||||
m_src.RemoveAt(m_temporary_source);
|
||||
m_temporary_source = nullptr;
|
||||
}
|
||||
|
||||
void GSTextureCache::InjectHashCacheTexture(const HashCacheKey& key, GSTexture* tex)
|
||||
{
|
||||
auto it = m_hash_cache.find(key);
|
||||
|
|
|
@ -285,8 +285,9 @@ protected:
|
|||
static u8* m_temp;
|
||||
constexpr static size_t S_SURFACE_OFFSET_CACHE_MAX_SIZE = std::numeric_limits<u16>::max();
|
||||
std::unordered_map<SurfaceOffsetKey, SurfaceOffset, SurfaceOffsetKeyHash, SurfaceOffsetKeyEqual> m_surface_offset_cache;
|
||||
Source* m_temporary_source = nullptr; // invalidated after the draw
|
||||
|
||||
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0, const GSVector2i* lod = nullptr);
|
||||
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t = NULL, bool half_right = false, int x_offset = 0, int y_offset = 0, const GSVector2i* lod = nullptr, const GSVector4i* src_range = nullptr);
|
||||
Target* CreateTarget(const GIFRegTEX0& TEX0, int w, int h, int type, const bool clear);
|
||||
|
||||
HashCacheEntry* LookupHashCache(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool& paltex, const u32* clut, const GSVector2i* lod);
|
||||
|
@ -333,6 +334,9 @@ public:
|
|||
SurfaceOffset ComputeSurfaceOffset(const uint32_t bp, const uint32_t bw, const uint32_t psm, const GSVector4i& r, const Target* t);
|
||||
SurfaceOffset ComputeSurfaceOffset(const SurfaceOffsetKey& sok);
|
||||
|
||||
/// Invalidates a temporary source, a partial copy only created from the current RT/DS for the current draw.
|
||||
void InvalidateTemporarySource();
|
||||
|
||||
/// Injects a texture into the hash cache, by using GSTexture::Swap(), transitively applying to all sources. Ownership of tex is transferred.
|
||||
void InjectHashCacheTexture(const HashCacheKey& key, GSTexture* tex);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue