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();
|
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)
|
void GSRendererHW::SetGameCRC(u32 crc, int options)
|
||||||
{
|
{
|
||||||
GSRenderer::SetGameCRC(crc, 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)
|
if ((fm & fm_mask) != fm_mask && rt)
|
||||||
{
|
{
|
||||||
//rt->m_valid = rt->m_valid.runion(r);
|
//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
|
// Called by the texture cache to know if current texture is useful
|
||||||
virtual bool IsDummyTexture() const { return false; }
|
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));
|
GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, psm_str(TEX0.PSM));
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
new_source = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1165,7 +1165,7 @@ void GSTextureCache::IncAge()
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fixme: Several issues in here. Not handling depth stencil, pitch conversion doesnt work.
|
//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];
|
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||||
Source* src = new Source(m_renderer, TEX0, TEXA, false);
|
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();
|
GSVector2 scale = is_8bits ? GSVector2(1, 1) : dst->m_texture->GetScale();
|
||||||
|
|
||||||
GSVector4i sRect(0, 0, w, h);
|
|
||||||
const bool use_texture = shader == ShaderConvert::COPY;
|
const bool use_texture = shader == ShaderConvert::COPY;
|
||||||
|
GSVector4i sRect(0, 0, w, h);
|
||||||
|
int destX = 0;
|
||||||
|
int destY = 0;
|
||||||
|
|
||||||
if (half_right)
|
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);
|
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)
|
// 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)
|
// '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)
|
if (use_texture)
|
||||||
{
|
{
|
||||||
g_gs_device->CopyRect(sTex, dTex, sRect, 0, 0);
|
g_gs_device->CopyRect(sTex, dTex, sRect, destX, destY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1388,7 +1411,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||||
sRectF.z /= sTex->GetWidth();
|
sRectF.z /= sTex->GetWidth();
|
||||||
sRectF.w /= sTex->GetHeight();
|
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)
|
if (src->m_texture)
|
||||||
|
@ -2439,6 +2462,15 @@ GSTextureCache::SurfaceOffset GSTextureCache::ComputeSurfaceOffset(const Surface
|
||||||
return so;
|
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)
|
void GSTextureCache::InjectHashCacheTexture(const HashCacheKey& key, GSTexture* tex)
|
||||||
{
|
{
|
||||||
auto it = m_hash_cache.find(key);
|
auto it = m_hash_cache.find(key);
|
||||||
|
|
|
@ -285,8 +285,9 @@ protected:
|
||||||
static u8* m_temp;
|
static u8* m_temp;
|
||||||
constexpr static size_t S_SURFACE_OFFSET_CACHE_MAX_SIZE = std::numeric_limits<u16>::max();
|
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;
|
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);
|
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);
|
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 uint32_t bp, const uint32_t bw, const uint32_t psm, const GSVector4i& r, const Target* t);
|
||||||
SurfaceOffset ComputeSurfaceOffset(const SurfaceOffsetKey& sok);
|
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.
|
/// 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);
|
void InjectHashCacheTexture(const HashCacheKey& key, GSTexture* tex);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue