GS: Sample LOD 0 explicitly in interlace shaders

Can't use normal sampling because the derivates are undefined in
non-uniform control flow (in MAD).
This commit is contained in:
Stenzek 2023-03-19 16:39:57 +10:00 committed by refractionpcsx2
parent 76e8bfe42f
commit b26acad721
5 changed files with 56 additions and 52 deletions

View File

@ -23,7 +23,7 @@ float4 ps_main0(PS_INPUT input) : SV_Target0
const int vpos = int(input.p.y); // vertical position of destination texture const int vpos = int(input.p.y); // vertical position of destination texture
if ((vpos & 1) == field) if ((vpos & 1) == field)
return Texture.Sample(Sampler, input.t); return Texture.SampleLevel(Sampler, input.t, 0);
else else
discard; discard;
@ -34,7 +34,7 @@ float4 ps_main0(PS_INPUT input) : SV_Target0
// Bob shader // Bob shader
float4 ps_main1(PS_INPUT input) : SV_Target0 float4 ps_main1(PS_INPUT input) : SV_Target0
{ {
return Texture.Sample(Sampler, input.t); return Texture.SampleLevel(Sampler, input.t, 0);
} }
@ -42,9 +42,9 @@ float4 ps_main1(PS_INPUT input) : SV_Target0
float4 ps_main2(PS_INPUT input) : SV_Target0 float4 ps_main2(PS_INPUT input) : SV_Target0
{ {
float2 vstep = float2(0.0f, ZrH.y); float2 vstep = float2(0.0f, ZrH.y);
float4 c0 = Texture.Sample(Sampler, input.t - vstep); float4 c0 = Texture.SampleLevel(Sampler, input.t - vstep, 0);
float4 c1 = Texture.Sample(Sampler, input.t); float4 c1 = Texture.SampleLevel(Sampler, input.t, 0);
float4 c2 = Texture.Sample(Sampler, input.t + vstep); float4 c2 = Texture.SampleLevel(Sampler, input.t + vstep, 0);
return (c0 + c1 * 2 + c2) / 4; return (c0 + c1 * 2 + c2) / 4;
} }
@ -74,7 +74,7 @@ float4 ps_main3(PS_INPUT input) : SV_Target0
// if the index of current destination line belongs to the current fiels we update it, otherwise // if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer // we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field)) if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
return Texture.Sample(Sampler, iptr); return Texture.SampleLevel(Sampler, iptr, 0);
else else
discard; discard;
@ -133,13 +133,13 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1 // calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
float4 hn = Texture.Sample(Sampler, p_t0 - lofs); // new high pixel float4 hn = Texture.SampleLevel(Sampler, p_t0 - lofs, 0); // new high pixel
float4 cn = Texture.Sample(Sampler, p_t1); // new center pixel float4 cn = Texture.SampleLevel(Sampler, p_t1, 0); // new center pixel
float4 ln = Texture.Sample(Sampler, p_t0 + lofs); // new low pixel float4 ln = Texture.SampleLevel(Sampler, p_t0 + lofs, 0); // new low pixel
float4 ho = Texture.Sample(Sampler, p_t2 - lofs); // old high pixel float4 ho = Texture.SampleLevel(Sampler, p_t2 - lofs, 0); // old high pixel
float4 co = Texture.Sample(Sampler, p_t3); // old center pixel float4 co = Texture.SampleLevel(Sampler, p_t3, 0); // old center pixel
float4 lo = Texture.Sample(Sampler, p_t2 + lofs); // old low pixel float4 lo = Texture.SampleLevel(Sampler, p_t2 + lofs, 0); // old low pixel
float3 mh = hn.rgb - ho.rgb; // high pixel motion float3 mh = hn.rgb - ho.rgb; // high pixel motion
float3 mc = cn.rgb - co.rgb; // center pixel motion float3 mc = cn.rgb - co.rgb; // center pixel motion
@ -164,7 +164,7 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
if ((vpos & 1) == field) if ((vpos & 1) == field)
{ {
// output coordinate present on current field // output coordinate present on current field
return Texture.Sample(Sampler, p_t0); return Texture.SampleLevel(Sampler, p_t0, 0);
} }
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y)) else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{ {

View File

@ -19,7 +19,7 @@ void ps_main0()
int vpos = int(gl_FragCoord.y); // vertical position of destination texture int vpos = int(gl_FragCoord.y); // vertical position of destination texture
if ((vpos & 1) == field) if ((vpos & 1) == field)
SV_Target0 = texture(TextureSampler, PSin_t); SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
else else
discard; discard;
} }
@ -28,7 +28,7 @@ void ps_main0()
// Bob shader // Bob shader
void ps_main1() void ps_main1()
{ {
SV_Target0 = texture(TextureSampler, PSin_t); SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
} }
@ -36,9 +36,9 @@ void ps_main1()
void ps_main2() void ps_main2()
{ {
vec2 vstep = vec2(0.0f, ZrH.y); vec2 vstep = vec2(0.0f, ZrH.y);
vec4 c0 = texture(TextureSampler, PSin_t - vstep); vec4 c0 = textureLod(TextureSampler, PSin_t - vstep, 0);
vec4 c1 = texture(TextureSampler, PSin_t); vec4 c1 = textureLod(TextureSampler, PSin_t, 0);
vec4 c2 = texture(TextureSampler, PSin_t + vstep); vec4 c2 = textureLod(TextureSampler, PSin_t + vstep, 0);
SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f; SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f;
} }
@ -68,7 +68,7 @@ void ps_main3()
// if the index of current destination line belongs to the current fiels we update it, otherwise // if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer // we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field)) if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
SV_Target0 = texture(TextureSampler, iptr); SV_Target0 = textureLod(TextureSampler, iptr, 0);
else else
discard; discard;
} }
@ -126,13 +126,13 @@ void ps_main4()
// calculating motion, only relevant for missing lines where the "center line" is pointed // calculating motion, only relevant for missing lines where the "center line" is pointed
// by p_t1 // by p_t1
vec4 hn = texture(TextureSampler, p_t0 - lofs); // new high pixel vec4 hn = textureLod(TextureSampler, p_t0 - lofs, 0); // new high pixel
vec4 cn = texture(TextureSampler, p_t1); // new center pixel vec4 cn = textureLod(TextureSampler, p_t1, 0); // new center pixel
vec4 ln = texture(TextureSampler, p_t0 + lofs); // new low pixel vec4 ln = textureLod(TextureSampler, p_t0 + lofs, 0); // new low pixel
vec4 ho = texture(TextureSampler, p_t2 - lofs); // old high pixel vec4 ho = textureLod(TextureSampler, p_t2 - lofs, 0); // old high pixel
vec4 co = texture(TextureSampler, p_t3); // old center pixel vec4 co = textureLod(TextureSampler, p_t3, 0); // old center pixel
vec4 lo = texture(TextureSampler, p_t2 + lofs); // old low pixel vec4 lo = textureLod(TextureSampler, p_t2 + lofs, 0); // old low pixel
vec3 mh = hn.rgb - ho.rgb; // high pixel motion vec3 mh = hn.rgb - ho.rgb; // high pixel motion
vec3 mc = cn.rgb - co.rgb; // center pixel motion vec3 mc = cn.rgb - co.rgb; // center pixel motion
@ -158,7 +158,7 @@ void ps_main4()
if ((vpos & 1) == field) if ((vpos & 1) == field)
{ {
// output coordinate present on current field // output coordinate present on current field
SV_Target0 = texture(TextureSampler, p_t0); SV_Target0 = textureLod(TextureSampler, p_t0, 0);
} }
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y)) else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{ {

View File

@ -35,7 +35,7 @@ void ps_main0()
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
if ((vpos & 1) == field) if ((vpos & 1) == field)
o_col0 = texture(samp0, v_tex); o_col0 = textureLod(samp0, v_tex, 0);
else else
discard; discard;
} }
@ -46,7 +46,7 @@ void ps_main0()
#ifdef ps_main1 #ifdef ps_main1
void ps_main1() void ps_main1()
{ {
o_col0 = texture(samp0, v_tex); o_col0 = textureLod(samp0, v_tex, 0);
} }
#endif #endif
@ -56,9 +56,9 @@ void ps_main1()
void ps_main2() void ps_main2()
{ {
vec2 vstep = vec2(0.0f, ZrH.y); vec2 vstep = vec2(0.0f, ZrH.y);
vec4 c0 = texture(samp0, v_tex - vstep); vec4 c0 = textureLod(samp0, v_tex - vstep, 0);
vec4 c1 = texture(samp0, v_tex); vec4 c1 = textureLod(samp0, v_tex, 0);
vec4 c2 = texture(samp0, v_tex + vstep); vec4 c2 = textureLod(samp0, v_tex + vstep, 0);
o_col0 = (c0 + c1 * 2.0f + c2) / 4.0f; o_col0 = (c0 + c1 * 2.0f + c2) / 4.0f;
} }
@ -90,7 +90,7 @@ void ps_main3()
// if the index of current destination line belongs to the current fiels we update it, otherwise // if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer // we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field)) if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
o_col0 = texture(samp0, iptr); o_col0 = textureLod(samp0, iptr, 0);
else else
discard; discard;
} }
@ -150,13 +150,13 @@ void ps_main4()
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1 // calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
vec4 hn = texture(samp0, p_t0 - lofs); // new high pixel vec4 hn = textureLod(samp0, p_t0 - lofs, 0); // new high pixel
vec4 cn = texture(samp0, p_t1); // new center pixel vec4 cn = textureLod(samp0, p_t1, 0); // new center pixel
vec4 ln = texture(samp0, p_t0 + lofs); // new low pixel vec4 ln = textureLod(samp0, p_t0 + lofs, 0); // new low pixel
vec4 ho = texture(samp0, p_t2 - lofs); // old high pixel vec4 ho = textureLod(samp0, p_t2 - lofs, 0); // old high pixel
vec4 co = texture(samp0, p_t3); // old center pixel vec4 co = textureLod(samp0, p_t3, 0); // old center pixel
vec4 lo = texture(samp0, p_t2 + lofs); // old low pixel vec4 lo = textureLod(samp0, p_t2 + lofs, 0); // old low pixel
vec3 mh = hn.rgb - ho.rgb; // high pixel motion vec3 mh = hn.rgb - ho.rgb; // high pixel motion
vec3 mc = cn.rgb - co.rgb; // center pixel motion vec3 mc = cn.rgb - co.rgb; // center pixel motion
@ -181,7 +181,7 @@ void ps_main4()
if ((vpos & 1) == field) // output coordinate present on current field if ((vpos & 1) == field) // output coordinate present on current field
{ {
// output coordinate present on current field // output coordinate present on current field
o_col0 = texture(samp0, p_t0); o_col0 = textureLod(samp0, p_t0, 0);
} }
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y)) else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{ {

View File

@ -33,6 +33,10 @@ struct ConvertPSRes
{ {
return texture.sample(s, coord); return texture.sample(s, coord);
} }
float4 sample_level(float2 coord, float lod)
{
return texture.sample(s, coord, level(lod));
}
}; };
struct ConvertPSDepthRes struct ConvertPSDepthRes

View File

@ -27,7 +27,7 @@ fragment float4 ps_interlace0(ConvertShaderData data [[stage_in]], ConvertPSRes
const int vpos = int(data.p.y); // vertical position of destination texture const int vpos = int(data.p.y); // vertical position of destination texture
if ((vpos & 1) == field) if ((vpos & 1) == field)
return res.sample(data.t); return res.sample_level(data.t, 0);
else else
discard_fragment(); discard_fragment();
@ -38,7 +38,7 @@ fragment float4 ps_interlace0(ConvertShaderData data [[stage_in]], ConvertPSRes
// Bob shader // Bob shader
fragment float4 ps_interlace1(ConvertShaderData data [[stage_in]], ConvertPSRes res) fragment float4 ps_interlace1(ConvertShaderData data [[stage_in]], ConvertPSRes res)
{ {
return res.sample(data.t); return res.sample_level(data.t);
} }
@ -47,9 +47,9 @@ fragment float4 ps_interlace2(ConvertShaderData data [[stage_in]], ConvertPSRes
constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]]) constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{ {
float2 vstep = float2(0.0f, uniform.ZrH.y); float2 vstep = float2(0.0f, uniform.ZrH.y);
float4 c0 = res.sample(data.t - vstep); float4 c0 = res.sample_level(data.t - vstep, 0);
float4 c1 = res.sample(data.t); float4 c1 = res.sample_level(data.t, 0);
float4 c2 = res.sample(data.t + vstep); float4 c2 = res.sample_level(data.t + vstep, 0);
return (c0 + c1 * 2.f + c2) / 4.f; return (c0 + c1 * 2.f + c2) / 4.f;
} }
@ -79,7 +79,7 @@ fragment float4 ps_interlace3(ConvertShaderData data [[stage_in]], ConvertPSRes
// if the index of current destination line belongs to the current fiels we update it, otherwise // if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer // we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field)) if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
return res.sample(iptr); return res.sample_level(iptr, 0);
else else
discard_fragment(); discard_fragment();
@ -137,13 +137,13 @@ fragment float4 ps_interlace4(ConvertShaderData data [[stage_in]], ConvertPSRes
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1 // calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
float4 hn = res.sample(p_t0 - lofs); // new high pixel float4 hn = res.sample_level(p_t0 - lofs, 0); // new high pixel
float4 cn = res.sample(p_t1); // new center pixel float4 cn = res.sample_level(p_t1, 0); // new center pixel
float4 ln = res.sample(p_t0 + lofs); // new low pixel float4 ln = res.sample_level(p_t0 + lofs, 0); // new low pixel
float4 ho = res.sample(p_t2 - lofs); // old high pixel float4 ho = res.sample_level(p_t2 - lofs, 0); // old high pixel
float4 co = res.sample(p_t3); // old center pixel float4 co = res.sample_level(p_t3, 0); // old center pixel
float4 lo = res.sample(p_t2 + lofs); // old low pixel float4 lo = res.sample_level(p_t2 + lofs, 0); // old low pixel
float3 mh = hn.rgb - ho.rgb; float3 mh = hn.rgb - ho.rgb;
float3 mc = cn.rgb - co.rgb; float3 mc = cn.rgb - co.rgb;
@ -168,7 +168,7 @@ fragment float4 ps_interlace4(ConvertShaderData data [[stage_in]], ConvertPSRes
if ((vpos & 1) == field) if ((vpos & 1) == field)
{ {
// output coordinate present on current field // output coordinate present on current field
return res.sample(p_t0); return res.sample_level(p_t0, 0);
} }
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y)) else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{ {