mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
21fa2ee87b
commit
6924249bcf
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue