mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Allow use of trilinear with shader sampling
This commit is contained in:
parent
f47b2d02cb
commit
ec8d5d1b71
|
@ -162,6 +162,7 @@ cbuffer cb1
|
||||||
uint4 FbMask;
|
uint4 FbMask;
|
||||||
float4 HalfTexel;
|
float4 HalfTexel;
|
||||||
float4 MinMax;
|
float4 MinMax;
|
||||||
|
float4 LODParams;
|
||||||
float4 STRange;
|
float4 STRange;
|
||||||
int4 ChannelShuffle;
|
int4 ChannelShuffle;
|
||||||
float2 TC_OffsetHack;
|
float2 TC_OffsetHack;
|
||||||
|
@ -207,10 +208,10 @@ float4 sample_c(float2 uv, float uv_w)
|
||||||
return Texture.Sample(TextureSampler, uv);
|
return Texture.Sample(TextureSampler, uv);
|
||||||
#elif PS_MANUAL_LOD == 1
|
#elif PS_MANUAL_LOD == 1
|
||||||
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
||||||
float K = MinMax.x;
|
float K = LODParams.x;
|
||||||
float L = MinMax.y;
|
float L = LODParams.y;
|
||||||
float bias = MinMax.z;
|
float bias = LODParams.z;
|
||||||
float max_lod = MinMax.w;
|
float max_lod = LODParams.w;
|
||||||
|
|
||||||
float gs_lod = K - log2(abs(uv_w)) * L;
|
float gs_lod = K - log2(abs(uv_w)) * L;
|
||||||
// FIXME max useful ?
|
// FIXME max useful ?
|
||||||
|
|
|
@ -44,6 +44,7 @@ layout(std140, binding = 0) uniform cb21
|
||||||
vec4 HalfTexel;
|
vec4 HalfTexel;
|
||||||
|
|
||||||
vec4 MinMax;
|
vec4 MinMax;
|
||||||
|
vec4 LODParams;
|
||||||
vec4 STRange;
|
vec4 STRange;
|
||||||
|
|
||||||
ivec4 ChannelShuffle;
|
ivec4 ChannelShuffle;
|
||||||
|
@ -159,10 +160,10 @@ vec4 sample_c(vec2 uv)
|
||||||
return texture(TextureSampler, uv);
|
return texture(TextureSampler, uv);
|
||||||
#elif PS_MANUAL_LOD == 1
|
#elif PS_MANUAL_LOD == 1
|
||||||
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
||||||
float K = MinMax.x;
|
float K = LODParams.x;
|
||||||
float L = MinMax.y;
|
float L = LODParams.y;
|
||||||
float bias = MinMax.z;
|
float bias = LODParams.z;
|
||||||
float max_lod = MinMax.w;
|
float max_lod = LODParams.w;
|
||||||
|
|
||||||
float gs_lod = K - log2(abs(PSin.t_float.w)) * L;
|
float gs_lod = K - log2(abs(PSin.t_float.w)) * L;
|
||||||
// FIXME max useful ?
|
// FIXME max useful ?
|
||||||
|
|
|
@ -316,6 +316,7 @@ layout(std140, set = 0, binding = 1) uniform cb1
|
||||||
uvec4 FbMask;
|
uvec4 FbMask;
|
||||||
vec4 HalfTexel;
|
vec4 HalfTexel;
|
||||||
vec4 MinMax;
|
vec4 MinMax;
|
||||||
|
vec4 LODParams;
|
||||||
vec4 STRange;
|
vec4 STRange;
|
||||||
ivec4 ChannelShuffle;
|
ivec4 ChannelShuffle;
|
||||||
vec2 TC_OffsetHack;
|
vec2 TC_OffsetHack;
|
||||||
|
@ -399,10 +400,10 @@ vec4 sample_c(vec2 uv)
|
||||||
return texture(Texture, uv);
|
return texture(Texture, uv);
|
||||||
#elif PS_MANUAL_LOD == 1
|
#elif PS_MANUAL_LOD == 1
|
||||||
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
||||||
float K = MinMax.x;
|
float K = LODParams.x;
|
||||||
float L = MinMax.y;
|
float L = LODParams.y;
|
||||||
float bias = MinMax.z;
|
float bias = LODParams.z;
|
||||||
float max_lod = MinMax.w;
|
float max_lod = LODParams.w;
|
||||||
|
|
||||||
float gs_lod = K - log2(abs(vsIn.t.w)) * L;
|
float gs_lod = K - log2(abs(vsIn.t.w)) * L;
|
||||||
// FIXME max useful ?
|
// FIXME max useful ?
|
||||||
|
|
|
@ -585,6 +585,7 @@ struct alignas(16) GSHWDrawConfig
|
||||||
|
|
||||||
GSVector4 HalfTexel;
|
GSVector4 HalfTexel;
|
||||||
GSVector4 MinMax;
|
GSVector4 MinMax;
|
||||||
|
GSVector4 LODParams;
|
||||||
GSVector4 STRange;
|
GSVector4 STRange;
|
||||||
GSVector4i ChannelShuffle;
|
GSVector4i ChannelShuffle;
|
||||||
GSVector2 TCOffsetHack;
|
GSVector2 TCOffsetHack;
|
||||||
|
|
|
@ -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)
|
__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.
|
// 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;
|
const u32 textent = (1u << tsize) - 1u;
|
||||||
if (clamp == CLAMP_REGION_CLAMP)
|
if (clamp == CLAMP_REGION_CLAMP)
|
||||||
return (clamp_min == 0 && clamp_max >= textent);
|
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 need_mipmap = IsMipMapDraw();
|
||||||
const bool shader_emulated_sampler = tex->m_palette || (tex->m_target && !m_conf.ps.shuffle && cpsm.fmt != 0) ||
|
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;
|
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;
|
const bool trilinear_manual = need_mipmap && GSConfig.HWMipmap;
|
||||||
|
|
||||||
bool bilinear = m_vt.IsLinear();
|
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.
|
// 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.
|
// We don't need to check for HWMipmapLevel::Off here, because forced trilinear implies forced mipmaps.
|
||||||
bilinear = true;
|
bilinear = true;
|
||||||
trilinear = static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
|
if (can_trilinear)
|
||||||
trilinear_auto = !tex->m_target && (!need_mipmap || !GSConfig.HWMipmap);
|
{
|
||||||
|
trilinear = static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Linear);
|
||||||
|
trilinear_auto = !tex->m_target && (!need_mipmap || !GSConfig.HWMipmap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -4830,7 +4833,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||||
case TriFiltering::Automatic:
|
case TriFiltering::Automatic:
|
||||||
{
|
{
|
||||||
// Can only use PS2 trilinear when mipmapping is enabled.
|
// 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 = m_context->TEX1.MMIN;
|
||||||
trilinear_auto = !tex->m_target && !GSConfig.HWMipmap;
|
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;
|
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.LODParams.x = static_cast<float>(m_context->TEX1.K) / 16.0f;
|
||||||
m_conf.cb_ps.MinMax.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.MinMax.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.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.LODParams.w = static_cast<float>(m_lod.y);
|
||||||
m_conf.cb_ps.MinMax.w = static_cast<float>(m_lod.y);
|
m_conf.ps.manual_lod = 1;
|
||||||
}
|
}
|
||||||
else if (trilinear_auto)
|
else if (trilinear_auto)
|
||||||
{
|
{
|
||||||
tex->m_texture->GenerateMipmapsIfNeeded();
|
tex->m_texture->GenerateMipmapsIfNeeded();
|
||||||
|
m_conf.ps.automatic_lod = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TC Offset Hack
|
// TC Offset Hack
|
||||||
|
@ -5063,7 +5068,11 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||||
{
|
{
|
||||||
m_conf.sampler.biln = 0;
|
m_conf.sampler.biln = 0;
|
||||||
m_conf.sampler.aniso = 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
|
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;
|
const bool anisotropic = m_vt.m_primclass == GS_TRIANGLE_CLASS && !trilinear_manual;
|
||||||
m_conf.sampler.aniso = anisotropic;
|
m_conf.sampler.aniso = anisotropic;
|
||||||
m_conf.sampler.triln = trilinear;
|
m_conf.sampler.triln = trilinear;
|
||||||
if (trilinear_manual)
|
if (anisotropic && !trilinear_manual)
|
||||||
{
|
|
||||||
m_conf.ps.manual_lod = 1;
|
|
||||||
}
|
|
||||||
else if (trilinear_auto || anisotropic)
|
|
||||||
{
|
|
||||||
m_conf.ps.automatic_lod = 1;
|
m_conf.ps.automatic_lod = 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clamp to base level if we're not providing or generating mipmaps
|
// clamp to base level if we're not providing or generating mipmaps
|
||||||
|
|
|
@ -111,6 +111,7 @@ struct GSMTLMainPSUniform
|
||||||
vector_float4 uv_min_max;
|
vector_float4 uv_min_max;
|
||||||
vector_uint4 uv_msk_fix;
|
vector_uint4 uv_msk_fix;
|
||||||
};
|
};
|
||||||
|
vector_float4 lod_params;
|
||||||
vector_float4 st_range;
|
vector_float4 st_range;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -356,10 +356,10 @@ struct PSMain
|
||||||
}
|
}
|
||||||
else if (PS_MANUAL_LOD)
|
else if (PS_MANUAL_LOD)
|
||||||
{
|
{
|
||||||
float K = cb.uv_min_max.x;
|
float K = cb.lod_params.x;
|
||||||
float L = cb.uv_min_max.y;
|
float L = cb.lod_params.y;
|
||||||
float bias = cb.uv_min_max.z;
|
float bias = cb.lod_params.z;
|
||||||
float max_lod = cb.uv_min_max.w;
|
float max_lod = cb.lod_params.w;
|
||||||
|
|
||||||
float gs_lod = K - log2(abs(in.t.w)) * L;
|
float gs_lod = K - log2(abs(in.t.w)) * L;
|
||||||
// FIXME max useful ?
|
// FIXME max useful ?
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||||
/// shaders change, to invalidate the cache.
|
/// shaders change, to invalidate the cache.
|
||||||
static constexpr u32 SHADER_CACHE_VERSION = 50;
|
static constexpr u32 SHADER_CACHE_VERSION = 51;
|
||||||
|
|
Loading…
Reference in New Issue