GS: Reverted field order in MAD shader updated weave shader to same field order as MAD and merged two Weave shaders into one

GS: corrected refactoring errors in interlace shaders
This commit is contained in:
sideprojectslab 2022-11-13 19:49:08 +01:00 committed by refractionpcsx2
parent 21fa2ee87b
commit 6924249bcf
6 changed files with 92 additions and 98 deletions

View File

@ -14,22 +14,31 @@ struct PS_INPUT
float2 t : TEXCOORD0;
};
// Weave shader
float4 ps_main0(PS_INPUT input) : SV_Target0
{
if ((int(input.p.y) & 1) == 0)
const int idx = int(ZrH.x); // buffer index passed from CPU
const int field = idx & 1; // current field
const int vpos = int(input.p.y); // vertical position of destination texture
if ((vpos & 1) == field)
return Texture.Sample(Sampler, input.t);
else
discard;
return Texture.Sample(Sampler, input.t);
return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
// Bob shader
float4 ps_main1(PS_INPUT input) : SV_Target0
{
if ((int(input.p.y) & 1) != 0)
discard;
return Texture.Sample(Sampler, input.t);
}
// Blend shader
float4 ps_main2(PS_INPUT input) : SV_Target0
{
float2 vstep = float2(0.0f, ZrH.y);
@ -40,13 +49,9 @@ float4 ps_main2(PS_INPUT input) : SV_Target0
return (c0 + c1 * 2 + c2) / 4;
}
// MAD shader - buffering
float4 ps_main3(PS_INPUT input) : SV_Target0
{
return Texture.Sample(Sampler, input.t);
}
float4 ps_main4(PS_INPUT input) : SV_Target0
{
// We take half the lines from the current frame and stores them in the MAD frame buffer.
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
@ -68,7 +73,7 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
// 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
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);
else
discard;
@ -77,7 +82,8 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
}
float4 ps_main5(PS_INPUT input) : SV_Target0
// MAD shader - reconstruction
float4 ps_main4(PS_INPUT input) : SV_Target0
{
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current
// field.
@ -128,8 +134,7 @@ float4 ps_main5(PS_INPUT input) : SV_Target0
break;
}
// 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 cn = Texture.Sample(Sampler, p_t1); // new center pixel
@ -159,7 +164,7 @@ float4 ps_main5(PS_INPUT input) : SV_Target0
// selecting deinterlacing output
if ((vpos & 1) != field)
if ((vpos & 1) == field)
{
// output coordinate present on current field
return Texture.Sample(Sampler, p_t0);
@ -173,15 +178,11 @@ float4 ps_main5(PS_INPUT input) : SV_Target0
{
// missing line needs to be reconstructed
if (((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
{
// high motion -> interpolate pixels above and below
return (hn + ln) / 2.0f;
}
else
{
// low motion -> weave
return cn;
}
}
return float4(0.0f, 0.0f, 0.0f, 0.0f);

View File

@ -10,29 +10,29 @@ uniform vec4 ZrH;
layout(location = 0) out vec4 SV_Target0;
// TODO ensure that clip (discard) is < 0 and not <= 0 ???
// Weave shader
void ps_main0()
{
if ((int(gl_FragCoord.y) & 1) == 0)
discard;
// I'm not sure it impact us but be safe to lookup texture before conditional if
// see: http://www.opengl.org/wiki/GLSL_Sampler#Non-uniform_flow_control
vec4 c = texture(TextureSampler, PSin_t);
const int idx = int(ZrH.x); // buffer index passed from CPU
const int field = idx & 1; // current field
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
SV_Target0 = c;
if ((vpos & 1) == field)
SV_Target0 = texture(TextureSampler, PSin_t);
else
discard;
}
// Bob shader
void ps_main1()
{
if ((int(gl_FragCoord.y) & 1) != 0)
discard;
// I'm not sure it impact us but be safe to lookup texture before conditional if
// see: http://www.opengl.org/wiki/GLSL_Sampler#Non-uniform_flow_control
vec4 c = texture(TextureSampler, PSin_t);
SV_Target0 = c;
SV_Target0 = texture(TextureSampler, PSin_t);
}
// Blend shader
void ps_main2()
{
vec2 vstep = vec2(0.0f, ZrH.y);
@ -43,13 +43,9 @@ void ps_main2()
SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f;
}
// MAD shader - buffering
void ps_main3()
{
SV_Target0 = texture(TextureSampler, PSin_t);
}
void ps_main4()
{
// We take half the lines from the current frame and stores them in the MAD frame buffer.
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
@ -71,17 +67,17 @@ void ps_main4()
// 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
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);
else
discard;
}
void ps_main5()
// MAD shader - reconstruction
void ps_main4()
{
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current
// field.
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current field.
const int idx = int(ZrH.x); // buffer index passed from CPU
const int bank = idx >> 1; // current bank
@ -161,8 +157,8 @@ void ps_main5()
// selecting deinterlacing output
if ((vpos & 1) != field)
if ((vpos & 1) == field)
{
// output coordinate present on current field
SV_Target0 = texture(TextureSampler, p_t0);
@ -176,15 +172,11 @@ void ps_main5()
{
// missing line needs to be reconstructed
if(((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
{
// high motion -> interpolate pixels above and below
SV_Target0 = (hn + ln) / 2.0f;
}
else
{
// low motion -> weave
SV_Target0 = cn;
}
}
}

View File

@ -25,24 +25,33 @@ layout(push_constant) uniform cb0
layout(set = 0, binding = 0) uniform sampler2D samp0;
// Weave shader
#ifdef ps_main0
void ps_main0()
{
o_col0 = texture(samp0, v_tex);
if ((int(gl_FragCoord.y) & 1) == 0)
const int idx = int(ZrH.x); // buffer index passed from CPU
const int field = idx & 1; // current field
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
if ((vpos & 1) == field)
o_col0 = texture(samp0, v_tex);
else
discard;
}
#endif
// Bob shader
#ifdef ps_main1
void ps_main1()
{
o_col0 = texture(samp0, v_tex);
if ((int(gl_FragCoord.y) & 1) != 0)
discard;
}
#endif
// Blend shader
#ifdef ps_main2
void ps_main2()
{
@ -55,16 +64,10 @@ void ps_main2()
}
#endif
// MAD shader - buffering
#ifdef ps_main3
void ps_main3()
{
o_col0 = texture(samp0, v_tex);
}
#endif
#ifdef ps_main4
void ps_main4()
{
// We take half the lines from the current frame and stores them in the MAD frame buffer.
// the MAD frame buffer is split in 2 consecutive banks of 2 fields each, the fields in each bank
@ -86,7 +89,7 @@ void ps_main4()
// 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
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);
else
discard;
@ -94,8 +97,9 @@ void ps_main4()
#endif
#ifdef ps_main5
void ps_main5()
// MAD shader - reconstruction
#ifdef ps_main4
void ps_main4()
{
// we use the contents of the MAD frame buffer to reconstruct the missing lines from the current
// field.
@ -146,8 +150,7 @@ void ps_main5()
break;
}
// 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 cn = texture(samp0, p_t1); // new center pixel
@ -177,7 +180,7 @@ void ps_main5()
// selecting deinterlacing output
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
o_col0 = texture(samp0, p_t0);
@ -191,15 +194,11 @@ void ps_main5()
{
// missing line needs to be reconstructed
if(((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
{
// high motion -> interpolate pixels above and below
o_col0 = (hn + ln) / 2.0f;
}
else
{
// low motion -> weave
o_col0 = cn;
}
}
}
#endif

View File

@ -371,18 +371,18 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
{
case 0: // weave
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_merge, m_weavebob, field, false, offset, 0);
DoInterlace(m_merge, m_weavebob, 0, false, offset, field);
m_current = m_weavebob;
break;
case 1: // bob
// Field is reversed here as we are countering the bounce.
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_merge, m_weavebob, 3, true, yoffset * (1 - field), 0);
DoInterlace(m_merge, m_weavebob, 1, true, yoffset * (1 - field), 0);
m_current = m_weavebob;
break;
case 2: //Blend
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_merge, m_weavebob, field, false, offset, 0);
DoInterlace(m_merge, m_weavebob, 0, false, offset, field);
ResizeTarget(&m_blend, ds.x, ds.y);
DoInterlace(m_weavebob, m_blend, 2, false, 0, 0);
m_current = m_blend;
@ -393,9 +393,9 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
bufIdx |= field;
bufIdx &= 3;
ResizeTarget(&m_mad, ds.x, ds.y * 2.0f);
DoInterlace(m_merge, m_mad, 4, false, offset, bufIdx);
DoInterlace(m_merge, m_mad, 3, false, offset, bufIdx);
ResizeTarget(&m_weavebob, ds.x, ds.y);
DoInterlace(m_mad, m_weavebob, 5, false, 0, bufIdx);
DoInterlace(m_mad, m_weavebob, 4, false, 0, bufIdx);
m_current = m_weavebob;
break;
default:

View File

@ -737,7 +737,7 @@ private:
static const std::array<u8, 16> m_replaceDualSrcBlendMap;
protected:
static constexpr int NUM_INTERLACE_SHADERS = 6;
static constexpr int NUM_INTERLACE_SHADERS = 5;
static constexpr float MAD_SENSITIVITY = 0.08f;
static constexpr u32 MAX_POOLED_TEXTURES = 300;

View File

@ -17,22 +17,30 @@
using namespace metal;
// Weave shader
fragment float4 ps_interlace0(ConvertShaderData data [[stage_in]], ConvertPSRes res,
constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{
if ((int(data.p.y) & 1) == 0)
const int idx = int(uniform.ZrH.x); // buffer index passed from CPU
const int field = idx & 1; // current field
const int vpos = int(data.p.y); // vertical position of destination texture
if ((vpos & 1) == field)
return res.sample(data.t);
else
discard_fragment();
return res.sample(data.t);
}
fragment float4 ps_interlace1(ConvertShaderData data [[stage_in]], ConvertPSRes res,
constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
// Bob shader
fragment float4 ps_interlace1(ConvertShaderData data [[stage_in]], ConvertPSRes res)
{
if ((int(data.p.y) & 1) != 0)
discard_fragment();
return res.sample(data.t);
}
// Blend shader
fragment float4 ps_interlace2(ConvertShaderData data [[stage_in]], ConvertPSRes res,
constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{
@ -43,12 +51,9 @@ fragment float4 ps_interlace2(ConvertShaderData data [[stage_in]], ConvertPSRes
return (c0 + c1 * 2.f + c2) / 4.f;
}
fragment float4 ps_interlace3(ConvertShaderData data [[stage_in]], ConvertPSRes res)
{
return res.sample(data.t);
}
fragment float4 ps_interlace4(ConvertShaderData data [[stage_in]], ConvertPSRes res,
// MAD shader - buffering
fragment float4 ps_interlace3(ConvertShaderData data [[stage_in]], ConvertPSRes res,
constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{
// We take half the lines from the current frame and stores them in the MAD frame buffer.
@ -71,7 +76,7 @@ fragment float4 ps_interlace4(ConvertShaderData data [[stage_in]], ConvertPSRes
// 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
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);
else
discard_fragment();
@ -79,7 +84,9 @@ fragment float4 ps_interlace4(ConvertShaderData data [[stage_in]], ConvertPSRes
return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
fragment float4 ps_interlace5(ConvertShaderData data [[stage_in]], ConvertPSRes res,
// MAD shader - reconstruction
fragment float4 ps_interlace4(ConvertShaderData data [[stage_in]], ConvertPSRes res,
constant GSMTLInterlacePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{
const int idx = int(uniform.ZrH.x); // buffer index passed from CPU
@ -129,8 +136,7 @@ fragment float4 ps_interlace5(ConvertShaderData data [[stage_in]], ConvertPSRes
break;
}
// 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 cn = res.sample(p_t1); // new center pixel
@ -160,7 +166,7 @@ fragment float4 ps_interlace5(ConvertShaderData data [[stage_in]], ConvertPSRes
// selecting deinterlacing output
if ((vpos & 1) != field)
if ((vpos & 1) == field)
{
// output coordinate present on current field
return res.sample(p_t0);
@ -174,15 +180,11 @@ fragment float4 ps_interlace5(ConvertShaderData data [[stage_in]], ConvertPSRes
{
// missing line needs to be reconstructed
if (((mh_max > 0.0f) || (ml_max > 0.0f)) || (mc_max > 0.0f))
{
// high motion -> interpolate pixels above and below
return (hn + ln) / 2.0f;
}
else
{
// low motion -> weave
return cn;
}
}
return float4(0.0f, 0.0f, 0.0f, 0.0f);