GS/HW: Allow use of trilinear with shader sampling

This commit is contained in:
Stenzek 2024-06-23 07:10:42 +10:00 committed by Connor McLaughlin
parent f47b2d02cb
commit ec8d5d1b71
8 changed files with 43 additions and 35 deletions

View File

@ -162,6 +162,7 @@ cbuffer cb1
uint4 FbMask;
float4 HalfTexel;
float4 MinMax;
float4 LODParams;
float4 STRange;
int4 ChannelShuffle;
float2 TC_OffsetHack;
@ -207,10 +208,10 @@ float4 sample_c(float2 uv, float uv_w)
return Texture.Sample(TextureSampler, uv);
#elif PS_MANUAL_LOD == 1
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = MinMax.x;
float L = MinMax.y;
float bias = MinMax.z;
float max_lod = MinMax.w;
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(uv_w)) * L;
// FIXME max useful ?

View File

@ -44,6 +44,7 @@ layout(std140, binding = 0) uniform cb21
vec4 HalfTexel;
vec4 MinMax;
vec4 LODParams;
vec4 STRange;
ivec4 ChannelShuffle;
@ -159,10 +160,10 @@ vec4 sample_c(vec2 uv)
return texture(TextureSampler, uv);
#elif PS_MANUAL_LOD == 1
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = MinMax.x;
float L = MinMax.y;
float bias = MinMax.z;
float max_lod = MinMax.w;
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(PSin.t_float.w)) * L;
// FIXME max useful ?

View File

@ -316,6 +316,7 @@ layout(std140, set = 0, binding = 1) uniform cb1
uvec4 FbMask;
vec4 HalfTexel;
vec4 MinMax;
vec4 LODParams;
vec4 STRange;
ivec4 ChannelShuffle;
vec2 TC_OffsetHack;
@ -399,10 +400,10 @@ vec4 sample_c(vec2 uv)
return texture(Texture, uv);
#elif PS_MANUAL_LOD == 1
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = MinMax.x;
float L = MinMax.y;
float bias = MinMax.z;
float max_lod = MinMax.w;
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(vsIn.t.w)) * L;
// FIXME max useful ?

View File

@ -585,6 +585,7 @@ struct alignas(16) GSHWDrawConfig
GSVector4 HalfTexel;
GSVector4 MinMax;
GSVector4 LODParams;
GSVector4 STRange;
GSVector4i ChannelShuffle;
GSVector2 TCOffsetHack;

View File

@ -4743,7 +4743,6 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
__ri static constexpr bool IsRedundantClamp(u8 clamp, u32 clamp_min, u32 clamp_max, u32 tsize)
{
// Don't shader sample when the clamp/repeat is configured to the texture size.
// That way trilinear etc still works.
const u32 textent = (1u << tsize) - 1u;
if (clamp == CLAMP_REGION_CLAMP)
return (clamp_min == 0 && clamp_max >= textent);
@ -4809,6 +4808,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
const bool need_mipmap = IsMipMapDraw();
const bool shader_emulated_sampler = tex->m_palette || (tex->m_target && !m_conf.ps.shuffle && cpsm.fmt != 0) ||
complex_wms_wmt || psm.depth || target_region;
const bool can_trilinear = !tex->m_palette && !tex->m_target && !m_conf.ps.shuffle;
const bool trilinear_manual = need_mipmap && GSConfig.HWMipmap;
bool bilinear = m_vt.IsLinear();
@ -4821,8 +4821,11 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
// Force bilinear otherwise we can end up with min/mag nearest and mip linear.
// We don't need to check for HWMipmapLevel::Off here, because forced trilinear implies forced mipmaps.
bilinear = true;
trilinear = static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
trilinear_auto = !tex->m_target && (!need_mipmap || !GSConfig.HWMipmap);
if (can_trilinear)
{
trilinear = static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
trilinear_auto = !tex->m_target && (!need_mipmap || !GSConfig.HWMipmap);
}
}
break;
@ -4830,7 +4833,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
case TriFiltering::Automatic:
{
// Can only use PS2 trilinear when mipmapping is enabled.
if (need_mipmap && GSConfig.HWMipmap)
if (need_mipmap && GSConfig.HWMipmap && can_trilinear)
{
trilinear = m_context->TEX1.MMIN;
trilinear_auto = !tex->m_target && !GSConfig.HWMipmap;
@ -5037,17 +5040,19 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
m_conf.cb_ps.MinMax.w = (wmt == CLAMP_REGION_CLAMP && !m_conf.ps.depth_fmt) ? region_clamp.w : region_repeat.w;
}
}
else if (trilinear_manual)
if (trilinear_manual)
{
// Reuse uv_min_max for mipmap parameter to avoid an extension of the UBO
m_conf.cb_ps.MinMax.x = static_cast<float>(m_context->TEX1.K) / 16.0f;
m_conf.cb_ps.MinMax.y = static_cast<float>(1 << m_context->TEX1.L);
m_conf.cb_ps.MinMax.z = static_cast<float>(m_lod.x); // Offset because first layer is m_lod, dunno if we can do better
m_conf.cb_ps.MinMax.w = static_cast<float>(m_lod.y);
m_conf.cb_ps.LODParams.x = static_cast<float>(m_context->TEX1.K) / 16.0f;
m_conf.cb_ps.LODParams.y = static_cast<float>(1 << m_context->TEX1.L);
m_conf.cb_ps.LODParams.z = static_cast<float>(m_lod.x); // Offset because first layer is m_lod, dunno if we can do better
m_conf.cb_ps.LODParams.w = static_cast<float>(m_lod.y);
m_conf.ps.manual_lod = 1;
}
else if (trilinear_auto)
{
tex->m_texture->GenerateMipmapsIfNeeded();
m_conf.ps.automatic_lod = 1;
}
// TC Offset Hack
@ -5063,7 +5068,11 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
{
m_conf.sampler.biln = 0;
m_conf.sampler.aniso = 0;
m_conf.sampler.triln = 0;
// Remove linear from trilinear, since we're doing the bilinear in the shader, and we only want this for mip selection.
m_conf.sampler.triln = (trilinear >= static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Nearest)) ?
(trilinear - static_cast<u8>(GS_MIN_FILTER::Nearest_Mipmap_Nearest)) :
0;
}
else
{
@ -5073,14 +5082,8 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
const bool anisotropic = m_vt.m_primclass == GS_TRIANGLE_CLASS && !trilinear_manual;
m_conf.sampler.aniso = anisotropic;
m_conf.sampler.triln = trilinear;
if (trilinear_manual)
{
m_conf.ps.manual_lod = 1;
}
else if (trilinear_auto || anisotropic)
{
if (anisotropic && !trilinear_manual)
m_conf.ps.automatic_lod = 1;
}
}
// clamp to base level if we're not providing or generating mipmaps

View File

@ -111,6 +111,7 @@ struct GSMTLMainPSUniform
vector_float4 uv_min_max;
vector_uint4 uv_msk_fix;
};
vector_float4 lod_params;
vector_float4 st_range;
struct
{

View File

@ -356,10 +356,10 @@ struct PSMain
}
else if (PS_MANUAL_LOD)
{
float K = cb.uv_min_max.x;
float L = cb.uv_min_max.y;
float bias = cb.uv_min_max.z;
float max_lod = cb.uv_min_max.w;
float K = cb.lod_params.x;
float L = cb.lod_params.y;
float bias = cb.lod_params.z;
float max_lod = cb.lod_params.w;
float gs_lod = K - log2(abs(in.t.w)) * L;
// FIXME max useful ?

View File

@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 50;
static constexpr u32 SHADER_CACHE_VERSION = 51;