GS/HW: Avoid tex-is-fb when incompatible clamp is used

This commit is contained in:
Stenzek 2023-07-10 19:57:41 +10:00 committed by Connor McLaughlin
parent 4ded2caa0b
commit 9c4788432d
2 changed files with 35 additions and 3 deletions

View File

@ -4291,7 +4291,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
if (m_conf.tex == m_conf.rt)
{
// Can we read the framebuffer directly? (i.e. sample location matches up).
if (CanUseTexIsFB(rt, tex))
if (CanUseTexIsFB(rt, tex, tmm))
{
m_conf.tex = nullptr;
m_conf.ps.tex_is_fb = true;
@ -4438,7 +4438,8 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
m_conf.tex = src_copy;
}
bool GSRendererHW::CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextureCache::Source* tex) const
bool GSRendererHW::CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextureCache::Source* tex,
const TextureMinMaxResult& tmm) const
{
// Minimum blending or no barriers -> we can't use tex-is-fb.
if (GSConfig.AccurateBlendingUnit == AccBlendLevel::Minimum || !g_gs_device->Features().texture_barrier)
@ -4454,6 +4455,36 @@ bool GSRendererHW::CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextu
return true;
}
static constexpr auto check_clamp = [](u32 clamp, u32 min, u32 max, s32 tmin, s32 tmax) {
if (clamp == CLAMP_REGION_CLAMP)
{
if (tmin < static_cast<s32>(min) || tmax > static_cast<s32>(max + 1))
{
GL_CACHE("Can't use tex-is-fb because of REGION_CLAMP [%d, %d] with TMM of [%d, %d]", min, max, tmin, tmax);
return false;
}
}
else if (clamp == CLAMP_REGION_REPEAT)
{
const u32 req_tbits = (tmax > 1) ? static_cast<u32>(Common::NextPow2(tmax - 1) - 1) : 0x1;
if ((min & req_tbits) != req_tbits)
{
GL_CACHE("Can't use tex-is-fb because of REGION_REPEAT [%d, %d] with TMM of [%d, %d] and tbits of %d",
min, max, tmin, tmax, req_tbits);
return false;
}
}
return true;
};
if (!check_clamp(
m_cached_ctx.CLAMP.WMS, m_cached_ctx.CLAMP.MINU, m_cached_ctx.CLAMP.MAXU, tmm.coverage.x, tmm.coverage.z) ||
!check_clamp(
m_cached_ctx.CLAMP.WMT, m_cached_ctx.CLAMP.MINV, m_cached_ctx.CLAMP.MAXV, tmm.coverage.y, tmm.coverage.w))
{
return false;
}
// Texture is actually the frame buffer. Stencil emulation to compute shadow (Jak series/tri-ace game)
// Will hit the "m_ps_sel.tex_is_fb = 1" path in the draw
if (m_vt.m_primclass == GS_TRIANGLE_CLASS)

View File

@ -93,7 +93,8 @@ private:
void HandleTextureHazards(const GSTextureCache::Target* rt, const GSTextureCache::Target* ds,
const GSTextureCache::Source* tex, const TextureMinMaxResult& tmm, GSTextureCache::SourceRegion& source_region,
bool& target_region, GSVector2i& unscaled_size, float& scale, GSTexture*& src_copy);
bool CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextureCache::Source* tex) const;
bool CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextureCache::Source* tex,
const TextureMinMaxResult& tmm) const;
void EmulateZbuffer(const GSTextureCache::Target* ds);
void EmulateATST(float& AREF, GSHWDrawConfig::PSSelector& ps, bool pass_2);