Skip to content

Commit

Permalink
GS/HW: Compute source alpha min/max based on texture instead of CLUT
Browse files Browse the repository at this point in the history
Stops alpha from unused CLUT colours from leaking into the alpha range,
saves a good number of draw calls on many games, and some RTA
conversions.
  • Loading branch information
stenzek committed Apr 1, 2024
1 parent 64a471b commit fce8317
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 27 deletions.
18 changes: 13 additions & 5 deletions pcsx2/GS/GSState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3916,17 +3916,25 @@ void GSState::CalcAlphaMinMax(const int tex_alpha_min, const int tex_alpha_max)
case 1:
// If we're using the alpha from the texture, not the whole range, we can just use tex_alpha_min/max.
// AEM and TA0 re precomputed with GSBlock::ReadAndExpandBlock24, so already worked out for tex_alpha.
a.y = (tex_alpha_max < 500) ? min : (env.TEXA.AEM ? 0 : env.TEXA.TA0);
a.w = (tex_alpha_max < 500) ? max : env.TEXA.TA0;
a.y = (tex_alpha_max < INVALID_ALPHA_MINMAX) ? min : (env.TEXA.AEM ? 0 : env.TEXA.TA0);
a.w = (tex_alpha_max < INVALID_ALPHA_MINMAX) ? max : env.TEXA.TA0;
break;
case 2:
// If we're using the alpha from the texture, not the whole range, we can just use tex_alpha_min/max.
// AEM, TA0 and TA1 are precomputed with GSBlock::ReadAndExpandBlock16, so already worked out for tex_alpha.
a.y = (tex_alpha_max < 500) ? min : (env.TEXA.AEM ? 0 : std::min(env.TEXA.TA0, env.TEXA.TA1));
a.w = (tex_alpha_max < 500) ? max : std::max(env.TEXA.TA0, env.TEXA.TA1);
a.y = (tex_alpha_max < INVALID_ALPHA_MINMAX) ? min : (env.TEXA.AEM ? 0 : std::min(env.TEXA.TA0, env.TEXA.TA1));
a.w = (tex_alpha_max < INVALID_ALPHA_MINMAX) ? max : std::max(env.TEXA.TA0, env.TEXA.TA1);
break;
case 3:
m_mem.m_clut.GetAlphaMinMax32(a.y, a.w);
if (tex_alpha_max < INVALID_ALPHA_MINMAX)
{
a.y = min;
a.w = max;
}
else
{
m_mem.m_clut.GetAlphaMinMax32(a.y, a.w);
}
break;
default:
ASSUME(0);
Expand Down
4 changes: 3 additions & 1 deletion pcsx2/GS/GSState.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class GSState : public GSAlignedClass<32>
} m_tr;

protected:
static constexpr int INVALID_ALPHA_MINMAX = 500;

GSVertex m_v = {};
float m_q = 1.0f;
GSVector4i m_scissor_cull_min = {};
Expand Down Expand Up @@ -163,7 +165,7 @@ class GSState : public GSAlignedClass<32>
GSVertexTrace::VertexAlpha& GetAlphaMinMax()
{
if (!m_vt.m_alpha.valid)
CalcAlphaMinMax(0, 500);
CalcAlphaMinMax(0, INVALID_ALPHA_MINMAX);
return m_vt.m_alpha;
}
struct TextureMinMaxResult
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2489,7 +2489,7 @@ void GSRendererHW::Draw()
// We don't know the alpha range of direct sources when we first tried to optimize the alpha test.
// Moving the texture lookup before the ATST optimization complicates things a lot, so instead,
// recompute it, and everything derived from it again if it changes.
if (GSLocalMemory::m_psm[src->m_TEX0.PSM].pal == 0)
if (src->m_valid_alpha_minmax)
{
CalcAlphaMinMax(src->m_alpha_minmax.first, src->m_alpha_minmax.second);

Expand Down
51 changes: 32 additions & 19 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c

if (palette)
{
AttachPaletteToSource(src, psm_s.pal, true);
AttachPaletteToSource(src, psm_s.pal, true, true);
}
}
else
Expand Down Expand Up @@ -1645,7 +1645,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (TEX0.PSM == PSMT8H)
{
// Attach palette for GPU texture conversion
AttachPaletteToSource(src, psm_s.pal, true);
AttachPaletteToSource(src, psm_s.pal, true, true);
}

return src;
Expand All @@ -1666,7 +1666,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (TEX0.PSM == PSMT8H)
{
// Attach palette for GPU texture conversion
AttachPaletteToSource(src, psm_s.pal, true);
AttachPaletteToSource(src, psm_s.pal, true, true);
}

return src;
Expand Down Expand Up @@ -1715,6 +1715,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
// Guard against merged targets which don't actually link.
if (src->m_target && src->m_from_target)
{
src->m_valid_alpha_minmax = true;

if ((src->m_TEX0.PSM & 0xf) == PSMCT24)
{
src->m_alpha_minmax.first = TEXA.AEM ? 0 : TEXA.TA0;
Expand All @@ -1739,7 +1741,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (gpu_clut)
AttachPaletteToSource(src, gpu_clut);
else if (src->m_palette && (!src->m_palette_obj || !src->ClutMatch({clut, psm_s.pal})))
AttachPaletteToSource(src, psm_s.pal, true);
AttachPaletteToSource(src, psm_s.pal, true, true);
}

src->Update(r);
Expand Down Expand Up @@ -4375,6 +4377,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
src->m_from_target = dst;
src->m_from_target_TEX0 = dst->m_TEX0;

src->m_valid_alpha_minmax = true;
if ((src->m_TEX0.PSM & 0xf) == PSMCT24)
{
src->m_alpha_minmax.first = TEXA.AEM ? 0 : TEXA.TA0;
Expand All @@ -4399,7 +4402,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (psm.pal > 0)
{
// Attach palette for GPU texture conversion
AttachPaletteToSource(src, psm.pal, true);
AttachPaletteToSource(src, psm.pal, true, true);
}

#ifdef PCSX2_DEVBUILD
Expand Down Expand Up @@ -4455,6 +4458,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
// Do this first as we could be adding in alpha from an upgraded 24bit target.
dst->Update();

src->m_valid_alpha_minmax = true;
if ((src->m_TEX0.PSM & 0xf) == PSMCT24)
{
src->m_alpha_minmax.first = TEXA.AEM ? 0 : TEXA.TA0;
Expand Down Expand Up @@ -4710,7 +4714,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
// Because the texture is already on the GPU, CPU can't convert it.
if (psm.pal > 0)
{
AttachPaletteToSource(src, psm.pal, true);
AttachPaletteToSource(src, psm.pal, true, true);
}

// Offset hack. Can be enabled via GS options.
Expand Down Expand Up @@ -4742,11 +4746,12 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
{
src->m_texture = src->m_from_hash_cache->texture;
src->m_alpha_minmax = src->m_from_hash_cache->alpha_minmax;
src->m_valid_alpha_minmax = src->m_from_hash_cache->valid_alpha_minmax;

if (gpu_clut)
AttachPaletteToSource(src, gpu_clut);
else if (psm.pal > 0)
AttachPaletteToSource(src, psm.pal, paltex);
AttachPaletteToSource(src, psm.pal, paltex, false);
}
else if (paltex)
{
Expand All @@ -4762,7 +4767,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (gpu_clut)
AttachPaletteToSource(src, gpu_clut);
else
AttachPaletteToSource(src, psm.pal, true);
AttachPaletteToSource(src, psm.pal, true, true);
}
else
{
Expand All @@ -4778,7 +4783,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (gpu_clut)
AttachPaletteToSource(src, gpu_clut);
else if (psm.pal > 0)
AttachPaletteToSource(src, psm.pal, false);
AttachPaletteToSource(src, psm.pal, false, true);
}

#ifdef PCSX2_DEVBUILD
Expand Down Expand Up @@ -5231,10 +5236,12 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
return nullptr;
}

// upload base level
const bool is_direct = (GSLocalMemory::m_psm[TEX0.PSM].pal == 0);
// compute alpha minmax on all textures, unless paltex is on, because not all CLUT colors are used.
const bool compute_alpha_minmax = !paltex;
std::pair<u8, u8> alpha_minmax = {0u, 255u};
PreloadTexture(TEX0, TEXA, region, g_gs_renderer->m_mem, paltex, tex, 0, is_direct ? &alpha_minmax : nullptr);

// upload base level
PreloadTexture(TEX0, TEXA, region, g_gs_renderer->m_mem, paltex, tex, 0, compute_alpha_minmax ? &alpha_minmax : nullptr);

// upload mips if present
if (lod)
Expand All @@ -5246,8 +5253,8 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
const GIFRegTEX0 MIP_TEX0{g_gs_renderer->GetTex0Layer(basemip + mip)};
std::pair<u8, u8> mip_alpha_minmax;
PreloadTexture(MIP_TEX0, TEXA, region.AdjustForMipmap(mip), g_gs_renderer->m_mem, paltex, tex, mip,
is_direct ? &mip_alpha_minmax : nullptr);
if (!is_direct)
compute_alpha_minmax ? &mip_alpha_minmax : nullptr);
if (compute_alpha_minmax)
{
alpha_minmax.first = std::min(alpha_minmax.first, mip_alpha_minmax.first);
alpha_minmax.second = std::max(alpha_minmax.second, mip_alpha_minmax.second);
Expand All @@ -5260,7 +5267,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
key.RemoveCLUTHash();

// insert into the cache cache, and we're done
const HashCacheEntry entry{tex, 1u, 0u, alpha_minmax, false};
const HashCacheEntry entry{tex, 1u, 0u, alpha_minmax, compute_alpha_minmax, false};
m_hash_cache_memory_usage += tex->GetMemUsage();
return &m_hash_cache.emplace(key, entry).first->second;
}
Expand Down Expand Up @@ -5916,7 +5923,7 @@ void GSTextureCache::Source::PreloadLevel(int level)
m_layer_hash[level] = hash;

// And upload the texture.
if (IsPaletteFormat())
if (!m_valid_alpha_minmax)
{
PreloadTexture(m_TEX0, m_TEXA, m_region.AdjustForMipmap(level), g_gs_renderer->m_mem, m_palette != nullptr,
m_texture, level, nullptr);
Expand Down Expand Up @@ -6435,11 +6442,15 @@ void GSTextureCache::SourceMap::RemoveAt(Source* s)
delete s;
}

void GSTextureCache::AttachPaletteToSource(Source* s, u16 pal, bool need_gs_texture)
void GSTextureCache::AttachPaletteToSource(Source* s, u16 pal, bool need_gs_texture, bool update_alpha_minmax)
{
s->m_palette_obj = m_palette_map.LookupPalette(pal, need_gs_texture);
s->m_palette = need_gs_texture ? s->m_palette_obj->GetPaletteGSTexture() : nullptr;
s->m_alpha_minmax = s->m_palette_obj->GetAlphaMinMax();
if (update_alpha_minmax)
{
s->m_alpha_minmax = s->m_palette_obj->GetAlphaMinMax();
s->m_valid_alpha_minmax = true;
}
}

void GSTextureCache::AttachPaletteToSource(Source* s, GSTexture* gpu_clut)
Expand All @@ -6448,6 +6459,7 @@ void GSTextureCache::AttachPaletteToSource(Source* s, GSTexture* gpu_clut)
s->m_palette = gpu_clut;

// Unknown.
s->m_valid_alpha_minmax = false;
s->m_alpha_minmax.first = 0;
s->m_alpha_minmax.second = 255;
}
Expand Down Expand Up @@ -6657,14 +6669,15 @@ void GSTextureCache::InjectHashCacheTexture(const HashCacheKey& key, GSTexture*
{
// We must've got evicted before we finished loading. No matter, add it in there anyway;
// if it's not used again, it'll get tossed out later.
const HashCacheEntry entry{tex, 1u, 0u, alpha_minmax, true};
const HashCacheEntry entry{tex, 1u, 0u, alpha_minmax, true, true};
m_hash_cache.emplace(key, entry);
return;
}

// Reset age so we don't get thrown out too early.
it->second.age = 0;
it->second.alpha_minmax = alpha_minmax;
it->second.valid_alpha_minmax = true;

// Update memory usage, swap the textures, and recycle the old one for reuse.
if (!it->second.is_replacement)
Expand Down
4 changes: 3 additions & 1 deletion pcsx2/GS/Renderers/HW/GSTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class GSTextureCache
u32 refcount;
u16 age;
std::pair<u8, u8> alpha_minmax;
bool valid_alpha_minmax;
bool is_replacement;
};

Expand Down Expand Up @@ -286,6 +287,7 @@ class GSTextureCache
bool m_target = false;
bool m_target_direct = false;
bool m_repeating = false;
bool m_valid_alpha_minmax = false;
std::pair<u8, u8> m_alpha_minmax = {0u, 255u};
std::vector<GSVector2i>* m_p2t = nullptr;
// Keep a trace of the target origin. There is no guarantee that pointer will
Expand Down Expand Up @@ -537,7 +539,7 @@ class GSTextureCache
return (type == DepthStencil) ? "Depth" : "Color";
}

void AttachPaletteToSource(Source* s, u16 pal, bool need_gs_texture);
void AttachPaletteToSource(Source* s, u16 pal, bool need_gs_texture, bool update_alpha_minmax);
void AttachPaletteToSource(Source* s, GSTexture* gpu_clut);
SurfaceOffset ComputeSurfaceOffset(const GSOffset& off, 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);
Expand Down

0 comments on commit fce8317

Please sign in to comment.