Skip to content

Commit

Permalink
GS/HW: Allow use of trilinear with shader sampling
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Jun 22, 2024
1 parent 27e2138 commit 74fd913
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 35 deletions.
9 changes: 5 additions & 4 deletions bin/resources/shaders/dx11/tfx.fx
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ cbuffer cb1
uint4 FbMask;
float4 HalfTexel;
float4 MinMax;
float4 LODParams;
float4 STRange;
int4 ChannelShuffle;
float2 TC_OffsetHack;
Expand Down Expand Up @@ -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 ?
Expand Down
9 changes: 5 additions & 4 deletions bin/resources/shaders/opengl/tfx_fs.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ layout(std140, binding = 0) uniform cb21
vec4 HalfTexel;

vec4 MinMax;
vec4 LODParams;
vec4 STRange;

ivec4 ChannelShuffle;
Expand Down Expand Up @@ -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 ?
Expand Down
9 changes: 5 additions & 4 deletions bin/resources/shaders/vulkan/tfx.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 ?
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/Common/GSDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,7 @@ struct alignas(16) GSHWDrawConfig

GSVector4 HalfTexel;
GSVector4 MinMax;
GSVector4 LODParams;
GSVector4 STRange;
GSVector4i ChannelShuffle;
GSVector2 TCOffsetHack;
Expand Down
39 changes: 21 additions & 18 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4739,7 +4739,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);
Expand Down Expand Up @@ -4805,6 +4804,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();
Expand All @@ -4817,16 +4817,19 @@ __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;

case TriFiltering::PS2:
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;
Expand Down Expand Up @@ -5033,17 +5036,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
Expand All @@ -5059,7 +5064,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
{
Expand All @@ -5069,14 +5078,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
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/Metal/GSMTLSharedHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
8 changes: 4 additions & 4 deletions pcsx2/GS/Renderers/Metal/tfx.metal
Original file line number Diff line number Diff line change
Expand Up @@ -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 ?
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/ShaderCacheVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

0 comments on commit 74fd913

Please sign in to comment.