XNA HD filter not working on MonoGame? (updated)

I was trying to apply a HD filter to the UWP version of my game. I found this post:

I tried to use the xBR filter provided in the answer marked, but then MonoGame gave me this error:
“This MGFX effect was built for a different platform!”

I’m not familiar with writing shader so I don’t think I can fix this by myself… Can someone help me with this issue? Thanks very much! :slightly_smiling:

Edit: Just realized that the xBR shader was built for iOS… But here came another issue: when I chose to build it for Windows, the MG Pipeline tool gave me this error:

error: Processor ‘EffectProcessor’ had unexpected failure!
System.Exception: Invalid profile ‘vs_3_0’. Vertex shader ‘main_vertex’ must be SM 4.0 level 9.1 or higher!
at TwoMGFX.PassInfo.ValidateShaderModels(ShaderProfile profile)
at TwoMGFX.EffectObject.CompileEffect(ShaderInfo shaderInfo, String& errorsAndWarnings)
at Microsoft.Xna.Framework.Content.Pipeline.Processors.EffectProcessor.Process(EffectContent input, ContentProcessorContext context)
at Microsoft.Xna.Framework.Content.Pipeline.ContentProcessor`2.Microsoft.Xna.Framework.Content.Pipeline.IContentProcessor.Process(Object input, ContentProcessorContext context)
at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.ProcessContent(PipelineBuildEvent pipelineEvent)

What is this issue all about?

@greyp - Set the platform to Windows Store and it should work.

Hi @Tom, I tried building the content for Windows Store, Windows and Windows Phone, but the same error is still there:
error: Processor ‘EffectProcessor’ had unexpected failure!
System.Exception: Invalid profile ‘vs_3_0’. Vertex shader ‘main_vertex’ must be SM 4.0 level 9.1 or higher!
at TwoMGFX.PassInfo.ValidateShaderModels(ShaderProfile profile)
at TwoMGFX.EffectObject.CompileEffect(ShaderInfo shaderInfo, String& errorsAndWarnings)
at Microsoft.Xna.Framework.Content.Pipeline.Processors.EffectProcessor.Process(EffectContent input, ContentProcessorContext context)
at Microsoft.Xna.Framework.Content.Pipeline.ContentProcessor`2.Microsoft.Xna.Framework.Content.Pipeline.IContentProcessor.Process(Object input, ContentProcessorContext context)
at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.ProcessContent(PipelineBuildEvent pipelineEvent)

Could you help explain what that error means?

For the sake of convenience, I am pasting that shader here:

float2 textureSize;
float4x4 matrixTransform;

const static float coef = 2.0;
const static float3 yuv_weighted = float3(14.352, 28.176, 5.472);

sampler decal : register(s0);

float4 df(float4 A, float4 B)
{
    return abs(A - B);
}

float4 weighted_distance(float4 a, float4 b, float4 c, float4 d, 
                         float4 e, float4 f, float4 g, float4 h)
{
    return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0 * df(g, h));
}

float4 main_vertex(inout float4 col0 : COLOR0, inout float2 tex0 : TEXCOORD0, 
                   inout float4 pos0 : POSITION0) : TEXCOORD1
{
    float2 ps = 1.0 / textureSize;

    pos0 = mul(pos0, matrixTransform);

    return float4(ps.x, 0, 0, ps.y);
}

float4 main_fragment(float4 pos0 : POSITION0, float2 tex0 : TEXCOORD0, 
                     float4 tex1 : TEXCOORD1) : COLOR0
{
    bool4 edr, edr_left, edr_up, px; // px = pixel, edr = edge detection rule
    bool4 ir_lv1, ir_lv2_left, ir_lv2_up;
    bool4 nc; // new_color
    bool4 fx, fx_left, fx_up; // inequations of straight lines.

    float2 fp = frac(tex0 * textureSize);
    float2 dx = tex1.xy;
    float2 dy = tex1.zw;

    float3 A  = tex2D(decal, tex0 - dx - dy).xyz;
    float3 B  = tex2D(decal, tex0 - dy).xyz;
    float3 C  = tex2D(decal, tex0 + dx - dy).xyz;
    float3 D  = tex2D(decal, tex0 - dx).xyz;
    float3 E  = tex2D(decal, tex0).xyz;
    float3 F  = tex2D(decal, tex0 + dx).xyz;
    float3 G  = tex2D(decal, tex0 - dx + dy).xyz;
    float3 H  = tex2D(decal, tex0 + dy).xyz;
    float3 I  = tex2D(decal, tex0 + dx + dy).xyz;
    float3 A1 = tex2D(decal, tex0 - dx - 2.0 * dy).xyz;
    float3 C1 = tex2D(decal, tex0 + dx - 2.0 * dy).xyz;
    float3 A0 = tex2D(decal, tex0 - 2.0 * dx - dy).xyz;
    float3 G0 = tex2D(decal, tex0 - 2.0 * dx + dy).xyz;
    float3 C4 = tex2D(decal, tex0 + 2.0 * dx - dy).xyz;
    float3 I4 = tex2D(decal, tex0 + 2.0 * dx + dy).xyz;
    float3 G5 = tex2D(decal, tex0 - dx + 2.0 * dy).xyz;
    float3 I5 = tex2D(decal, tex0 + dx + 2.0 * dy).xyz;
    float3 B1 = tex2D(decal, tex0 - 2.0 * dy).xyz;
    float3 D0 = tex2D(decal, tex0 - 2.0 * dx).xyz;
    float3 H5 = tex2D(decal, tex0 + 2.0 * dy).xyz;
    float3 F4 = tex2D(decal, tex0 + 2.0 * dx).xyz;

    float4 b = mul(float4x3(B, D, H, F), yuv_weighted);
    float4 c = mul(float4x3(C, A, G, I), yuv_weighted);
    float4 e = mul(float4x3(E, E, E, E), yuv_weighted);
    float4 d = b.yzwx;
    float4 f = b.wxyz;
    float4 g = c.zwxy;
    float4 h = b.zwxy;
    float4 i = c.wxyz;

    float4 i4 = mul(float4x3(I4, C1, A0, G5), yuv_weighted);
    float4 i5 = mul(float4x3(I5, C4, A1, G0), yuv_weighted);
    float4 h5 = mul(float4x3(H5, F4, B1, D0), yuv_weighted);
    float4 f4 = h5.yzwx;

    float4 Ao = float4(1.0, -1.0, -1.0, 1.0);
    float4 Bo = float4(1.0, 1.0, -1.0, -1.0);
    float4 Co = float4(1.5, 0.5, -0.5, 0.5);
    float4 Ax = float4(1.0, -1.0, -1.0, 1.0);
    float4 Bx = float4(0.5, 2.0, -0.5, -2.0);
    float4 Cx = float4(1.0, 1.0, -0.5, 0.0);
    float4 Ay = float4(1.0, -1.0, -1.0, 1.0);
    float4 By = float4(2.0, 0.5, -2.0, -0.5);
    float4 Cy = float4(2.0, 0.0, -1.0, 0.5);

    // These inequations define the line below which interpolation occurs.
    fx.x = (Ao.x * fp.y + Bo.x * fp.x > Co.x);
    fx.y = (Ao.y * fp.y + Bo.y * fp.x > Co.y);
    fx.z = (Ao.z * fp.y + Bo.z * fp.x > Co.z);
    fx.w = (Ao.w * fp.y + Bo.w * fp.x > Co.w);

    fx_left.x = (Ax.x * fp.y + Bx.x * fp.x > Cx.x);
    fx_left.y = (Ax.y * fp.y + Bx.y * fp.x > Cx.y);
    fx_left.z = (Ax.z * fp.y + Bx.z * fp.x > Cx.z);
    fx_left.w = (Ax.w * fp.y + Bx.w * fp.x > Cx.w);

    fx_up.x = (Ay.x * fp.y + By.x * fp.x > Cy.x);
    fx_up.y = (Ay.y * fp.y + By.y * fp.x > Cy.y);
    fx_up.z = (Ay.z * fp.y + By.z * fp.x > Cy.z);
    fx_up.w = (Ay.w * fp.y + By.w * fp.x > Cy.w);

    ir_lv1      = ((e != f) && (e != h));
    ir_lv2_left = ((e != g) && (d != g));
    ir_lv2_up   = ((e != c) && (b != c));

    float4 w1 = weighted_distance(e, c, g, i, h5, f4, h, f);
    float4 w2 = weighted_distance(h, d, i5, f, i4, b, e, i);
    float4 df_fg = df(f, g);
    float4 df_hc = df(h, c);
    float4 t1 = (coef * df_fg);
    float4 t2 = df_hc;
    float4 t3 = df_fg;
    float4 t4 = (coef * df_hc);

    edr      = (w1 < w2)  && ir_lv1;
    edr_left = (t1 <= t2) && ir_lv2_left;
    edr_up   = (t4 <= t3) && ir_lv2_up;

    nc = (edr && (fx || edr_left && fx_left || edr_up && fx_up));

    t1 = df(e, f);
    t2 = df(e, h);
    px = t1 <= t2;

    float3 res = nc.x ? px.x ? F : H : 
                 nc.y ? px.y ? B : F : 
                 nc.z ? px.z ? D : B : 
                 nc.w ? px.w ? H : D : E;

    return float4(res.xyz, 1.0);
}

technique T0
{
    pass P0
    {
        VertexShader = compile vs_3_0 main_vertex();
        PixelShader = compile ps_3_0 main_fragment();
    }
}

It seems to have something to do with this part:

technique T0
{
    pass P0
    {
        VertexShader = compile vs_3_0 main_vertex();
        PixelShader = compile ps_3_0 main_fragment();
    }
}

Can I simply modify this part to make it work? Though I’m not sure how…

You need vs_4_0_level_9_1 (and the corresponding for ps as well) for Windows Store platforms.

Thanks very much for your help @KonajuGames! Do you mean I should change the last block to something like this?

technique T0
{
    pass P0
    {
        VertexShader = compile vs_4_0_level_9_1 main_vertex();
        PixelShader = compile ps_4_0_level_9_1 main_fragment();
    }
}

That should work, yes.

Thanks so much @KonajuGames ! :smiley:

The effect was built successfully. However, when I tried to use it in the game, another error popped up.
In the line below, I try to set the texture size (just following the example in the OP):
_game.HDFilter.Parameters["textureSize"].SetValue(new float[] { screenWidth, screenHeight });
And this line always results in an error: “IndexOutOfRangeException was unhandled by user code”
(from inside the EffectParameterCollection.cs file)

public EffectParameter this[int index]
{
	get { return _parameters[index]; }
}

And here is the call stack:

   at Microsoft.Xna.Framework.Graphics.EffectParameterCollection.get_Item(Int32 index)
   at Microsoft.Xna.Framework.Graphics.EffectParameter.SetValue(Single[] value)
   at MyGame.ScreenManager.Draw(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.<>c.<.cctor>b__118_0(IDrawable drawable, GameTime gameTime)
   at Microsoft.Xna.Framework.Game.SortingFilteringCollection`1.ForEachFilteredItem[TUserData](Action`2 action, TUserData userData)
   at Microsoft.Xna.Framework.Game.Draw(GameTime gameTime)
   at MyGame.Game1.Draw(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.DoDraw(GameTime gameTime)
   at Microsoft.Xna.Framework.Game.Tick()
   at Microsoft.Xna.Framework.UAPGameWindow.Tick()
   at Microsoft.Xna.Framework.UAPGamePlatform.<>c.<StartRunLoop>b__12_0(Object o, Object a)

Can anyone explain to me what this error is about?

Hi @KonajuGames , is there any chance that you happen to know why I can’t set the value of that parameter in the effect? Could it be that the effect compiler removed that parameter? (which I really doubt because that parameter ‘textureSize’ is used in several locations throughout the effect file)

To me it looks like it is specified as a float2, so it should be set as Vector2, not a float[2]. The IndexOutOfRangeException is probably when it was trying to set the second element of the shader variable (index 1) which doesn’t exist. Try this

_game.HDFilter.Parameters["textureSize"].SetValue(new Vector2(screenWidth, screenHeight));

Thanks so much for your help @KonajuGames! I tried your method and that error is gone.

But now I have encountered another problem: when using that xBR filter effect, the screen is all black. In the tutorial from the OP, the author posted his result and it seems that effect does work in XNA. Could it be that an XNA shader doesn’t work in MonoGame? Or could it be that doing xBR image upscaling for 1080p is too much? (the original resolution for my game is 800x480)