Processor 'EffectProcessor' had unexpected failure AFTER MonoGame 3.8 update

Prior to updating to MonoGame 3.8 (I believe I was on 3.6 but it may have been older), I had two shaders (Bloom.fx and BloomCrossPlatform.fx) that compiled fine.

Since that upgrade, when I build my solution, I get this error for both:

“Processor ‘EffectProcessor’ had unexpected failure!”

There’s no line number and I can’t seem to find anything else with more details beyond that error message.

Here is Bloom.fx… if I can resolve this, hopefully I can resolve the other file too as they are rather similar. My knowledge on Shaders is unfortunately low and I probably just found this as is online and didn’t actually write it from scratch. Any help on making it work again would be appreciated.

// Added to use older pixel shader.
PixelShader = compile ps_3_0 PixelShaderFunction();

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VARIABLES
////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Needed for pixel offset
float2 InverseResolution;

//The threshold of pixels that are brighter than that.
float Threshold = 0.8f;

//MODIFIED DURING RUNTIME, CHANGING HERE MAKES NO DIFFERENCE;
float Radius;
float Strength;

//How far we stretch the pixels
float StreakLength = 1;

// Input texture
Texture2D ScreenTexture;

SamplerState LinearSampler
{
Texture = ;

MagFilter = LINEAR;
MinFilter = LINEAR;
Mipfilter = LINEAR;

AddressU = CLAMP;
AddressV = CLAMP;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// STRUCTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct VertexShaderInput
{
float3 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VERTEX SHADER
////////////////////////////////////////////////////////////////////////////////////////////////////////////

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
output.Position = float4(input.Position, 1);
output.TexCoord = input.TexCoord;
return output;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PIXEL SHADER
////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Just an average of 4 values.
float4 Box4(float4 p0, float4 p1, float4 p2, float4 p3)
{
return (p0 + p1 + p2 + p3) * 0.25f;
}

//Extracts the pixels we want to blur
float4 ExtractPS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
float4 color = ScreenTexture.Sample(LinearSampler, texCoord);

float avg = (color.r + color.g + color.b) / 3;

if (avg>Threshold)
{
return color * (avg - Threshold) / (1 - Threshold);// * (avg - Threshold);
}

return float4(0, 0, 0, 0);
}

//Extracts the pixels we want to blur, but considers luminance instead of average rgb
float4 ExtractLuminancePS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
float4 color = ScreenTexture.Sample(LinearSampler, texCoord);

float luminance = color.r * 0.21f + color.g * 0.72f + color.b * 0.07f;

if(luminance>Threshold)
{
  return color * (luminance - Threshold) / (1 - Threshold);// *(luminance - Threshold);
    //return saturate((color - Threshold) / (1 - Threshold));
}

return float4(0, 0, 0, 0);

}

//Downsample to the next mip, blur in the process
float4 DownsamplePS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
float2 offset = float2(StreakLength * InverseResolution.x, 1 * InverseResolution.y);

float4 c0 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-2, -2) * offset);
float4 c1 = ScreenTexture.Sample(LinearSampler, texCoord + float2(0,-2)*offset);
float4 c2 = ScreenTexture.Sample(LinearSampler, texCoord + float2(2, -2) * offset);
float4 c3 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, -1) * offset);
float4 c4 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, -1) * offset);
float4 c5 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-2, 0) * offset);
float4 c6 = ScreenTexture.Sample(LinearSampler, texCoord);
float4 c7 = ScreenTexture.Sample(LinearSampler, texCoord + float2(2, 0) * offset);
float4 c8 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, 1) * offset);
float4 c9 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, 1) * offset);
float4 c10 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-2, 2) * offset);
float4 c11 = ScreenTexture.Sample(LinearSampler, texCoord + float2(0, 2) * offset);
float4 c12 = ScreenTexture.Sample(LinearSampler, texCoord + float2(2, 2) * offset);

return Box4(c0, c1, c5, c6) * 0.125f +
Box4(c1, c2, c6, c7) * 0.125f +
Box4(c5, c6, c10, c11) * 0.125f +
Box4(c6, c7, c11, c12) * 0.125f +
Box4(c3, c4, c8, c9) * 0.5f;

}

//Upsample to the former MIP, blur in the process
float4 UpsamplePS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
float2 offset = float2(StreakLength * InverseResolution.x, 1 * InverseResolution.y) * Radius;

float4 c0 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, -1) * offset);
float4 c1 = ScreenTexture.Sample(LinearSampler, texCoord + float2(0, -1) * offset);
float4 c2 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, -1) * offset);
float4 c3 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, 0) * offset);
float4 c4 = ScreenTexture.Sample(LinearSampler, texCoord);
float4 c5 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, 0) * offset);
float4 c6 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1,1) * offset);
float4 c7 = ScreenTexture.Sample(LinearSampler, texCoord + float2(0, 1) * offset);
float4 c8 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, 1) * offset);

//Tentfilter  0.0625f    
return 0.0625f * (c0 + 2 * c1 + c2 + 2 * c3 + 4 * c4 + 2 * c5 + c6 + 2 * c7 + c8) * Strength + float4(0, 0,0,0); //+ 0.5f * ScreenTexture.Sample(c_texture, texCoord);

}

//Upsample to the former MIP, blur in the process, change offset depending on luminance
float4 UpsampleLuminancePS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
float4 c4 = ScreenTexture.Sample(LinearSampler, texCoord); //middle one

/*float luminance = c4.r * 0.21f + c4.g * 0.72f + c4.b * 0.07f;
luminance = max(luminance, 0.4f);

*/
float2 offset = float2(StreakLength * InverseResolution.x, 1 * InverseResolution.y) * Radius; /// luminance;

float4 c0 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, -1) * offset);
float4 c1 = ScreenTexture.Sample(LinearSampler, texCoord + float2(0, -1) * offset);
float4 c2 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, -1) * offset);
float4 c3 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, 0) * offset);
float4 c5 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, 0) * offset);
float4 c6 = ScreenTexture.Sample(LinearSampler, texCoord + float2(-1, 1) * offset);
float4 c7 = ScreenTexture.Sample(LinearSampler, texCoord + float2(0, 1) * offset);
float4 c8 = ScreenTexture.Sample(LinearSampler, texCoord + float2(1, 1) * offset);

return 0.0625f * (c0 + 2 * c1 + c2 + 2 * c3 + 4 * c4 + 2 * c5 + c6 + 2 * c7 + c8) * Strength + float4(0, 0, 0, 0); //+ 0.5f * ScreenTexture.Sample(c_texture, texCoord);

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TECHNIQUES
////////////////////////////////////////////////////////////////////////////////////////////////////////////

technique Extract
{
pass Pass1
{
VertexShader = compile vs_4_0 VertexShaderFunction();
PixelShader = compile ps_4_0 ExtractPS();
}
}

technique ExtractLuminance
{
pass Pass1
{
VertexShader = compile vs_4_0 VertexShaderFunction();
PixelShader = compile ps_4_0 ExtractLuminancePS();
}
}

technique Downsample
{
pass Pass1
{
VertexShader = compile vs_4_0 VertexShaderFunction();
PixelShader = compile ps_4_0 DownsamplePS();
}
}

technique Upsample
{
pass Pass1
{
VertexShader = compile vs_4_0 VertexShaderFunction();
PixelShader = compile ps_4_0 UpsamplePS();
}
}

technique UpsampleLuminance
{
pass Pass1
{
VertexShader = compile vs_4_0 VertexShaderFunction();
PixelShader = compile ps_4_0 UpsampleLuminancePS();
}
}

Have you got Content->Build->DebugMode = False?

I’ve not been using 3.8 but I do have

#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1

for this shader.

I added those lines and am learning that the more specific errors appear in my output.

I removed that entire bloom shader I had above since I don’t think I was implimenting it anyways, but I use others like BloomCombine which is now giving me this error:

Effects\BloomCombine.fx(28,18): warning X3206: ‘dot’: implicit truncation of vector type

Line 28:
float grey = dot(color, float3(0.3, 0.59, 0.11));

My other shader is throwing an error: error X3000: syntax error: unexpected token ‘;’

On the bold line:

// Added to use older pixel shader.
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1

// Our texture sampler
texture Texture;

sampler TextureSampler = sampler_state
{
Texture = < Texture >;
};

But if I remove the semicolon on that line, I get an error saying that it “Expected Semicolon”. WTF.

It’s very difficult, I know.

You do seem to have spaces in your bold line “< Texture >” instead of “<Texture>”, so that may be a cause?

Stepping back though…I recognize “BloomCombine” as one of the shaders I used to use going back to the XNA days (and was still in an old Monogame examples repository) and one which I found now (in Monogame 3.7) failed to compile for reasons I didn’t understand.

So I looked for a more up to date example and found, essentially, the same thing you did (maybe a different version though?).

So I removed “BloomCombine” and it’s associated shader, “BloomExtract” and classes from my solution and instead tried to work with the new solution, that did it all in one shader and one class.

Here is the result I came up with (“Bloom.fx”) after combining both the normal and “Multiplatform” versions of that shader, maybe give it a try and see if it compiles for MonoGame 3.8 also ?

Note: The halfPixelOffset below is set from C# code:
new Vector2(1.0f / _width, 1.0f / _height);
where _width and _height are essentially the “screen size” values and is only used to adjust slightly for OpenGL…for DirectX can be left as Vector2.Zero.

#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_2_0
#define PS_SHADERMODEL ps_2_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// INCORPORATES the functionality from BloomCrossPlatform.fx (but for OGL Shader Level 2).
////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  VARIABLES
////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Needed for HalfPixel Offset (OpenGL)
float2 HalfPixelOffset;

//Needed for Streak
float2 InverseResolution;

//MODIFIED DURING RUNTIME, CHANGING HERE MAKES NO DIFFERENCE;
float Threshold = 0.8f;
float Radius;
float Strength;

//How far we stretch the pixels
float StreakLength = 1;

// Input texture
Texture2D ScreenTexture;

SamplerState LinearSampler
{
	Texture = <ScreenTexture>;

	MagFilter = LINEAR;
	MinFilter = LINEAR;
	Mipfilter = LINEAR;

	AddressU = CLAMP;
	AddressV = CLAMP;
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  STRUCTS
////////////////////////////////////////////////////////////////////////////////////////////////////////////

struct VertexShaderInput
{
	float3 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
};

struct VertexShaderOutput
{
	float4 Position : POSITION0;
	float2 TexCoord : TEXCOORD0;
}; 

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////

	////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//  VERTEX SHADER
	////////////////////////////////////////////////////////////////////////////////////////////////////////////

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
	VertexShaderOutput output;
	output.Position = float4(input.Position, 1);
	output.TexCoord = input.TexCoord;
	return output;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//  PIXEL SHADER
	////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Just an average of 4 values.
float4 Box4(float4 p0, float4 p1, float4 p2, float4 p3)
{
	return (p0 + p1 + p2 + p3) * 0.25f;
}

//Extracts the pixels we want to blur
float4 ExtractPS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
    float2 texCoordHalfPixel = texCoord + HalfPixelOffset;

	float4 color = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel);

	float avg = (color.r + color.g + color.b) / 3;

	if (avg>Threshold)
	{
		return color * (avg - Threshold) / (1 - Threshold);// * (avg - Threshold);
	}

	return float4(0, 0, 0, 0);
}

//Extracts the pixels we want to blur, but considers luminance instead of average rgb
float4 ExtractLuminancePS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
    float2 texCoordHalfPixel = texCoord + HalfPixelOffset;

    float4 color = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel);

    float luminance = color.r * 0.21f + color.g * 0.72f + color.b * 0.07f;

    if(luminance>Threshold)
    {
		return color * (luminance - Threshold) / (1 - Threshold);
    }

    return float4(0, 0, 0, 0);
}

//Downsample to the next mip, blur in the process
float4 DownsamplePS(float4 pos : SV_POSITION,  float2 texCoord : TEXCOORD0) : SV_TARGET0
{
    float2 offset = float2(StreakLength * InverseResolution.x, 1 * InverseResolution.y);
        
    float2 texCoordHalfPixel = texCoord + HalfPixelOffset;

    float4 c0 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-2, -2) * offset);
    float4 c1 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(0,-2)*offset);
    float4 c2 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(2, -2) * offset);
    float4 c3 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, -1) * offset);
    float4 c4 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, -1) * offset);
    float4 c5 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-2, 0) * offset);
    float4 c6 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel);
    float4 c7 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(2, 0) * offset);
    float4 c8 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, 1) * offset);
    float4 c9 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, 1) * offset);
    float4 c10 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-2, 2) * offset);
    float4 c11 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(0, 2) * offset);
    float4 c12 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(2, 2) * offset);

    return Box4(c0, c1, c5, c6) * 0.125f +
    Box4(c1, c2, c6, c7) * 0.125f +
    Box4(c5, c6, c10, c11) * 0.125f +
    Box4(c6, c7, c11, c12) * 0.125f +
    Box4(c3, c4, c8, c9) * 0.5f;
}

//Upsample to the former MIP, blur in the process
float4 UpsamplePS(float4 pos : SV_POSITION,  float2 texCoord : TEXCOORD0) : SV_TARGET0
{
    float2 offset = float2(StreakLength * InverseResolution.x, 1 * InverseResolution.y) * Radius;

    float2 texCoordHalfPixel = texCoord + HalfPixelOffset;

    float4 c0 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, -1) * offset);
    float4 c1 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(0, -1) * offset);
    float4 c2 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, -1) * offset);
    float4 c3 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, 0) * offset);
    float4 c4 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel);
    float4 c5 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, 0) * offset);
    float4 c6 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1,1) * offset);
    float4 c7 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(0, 1) * offset);
    float4 c8 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, 1) * offset);

    //Tentfilter  0.0625f    
    return 0.0625f * (c0 + 2 * c1 + c2 + 2 * c3 + 4 * c4 + 2 * c5 + c6 + 2 * c7 + c8) * Strength + float4(0, 0,0,0);

}

//Upsample to the former MIP, blur in the process, change offset depending on luminance
float4 UpsampleLuminancePS(float4 pos : SV_POSITION, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
    float2 texCoordHalfPixel = texCoord + HalfPixelOffset;

    float4 c4 = ScreenTexture.Sample(LinearSampler, texCoord);  //middle one
 
    /*float luminance = c4.r * 0.21f + c4.g * 0.72f + c4.b * 0.07f;
    luminance = max(luminance, 0.4f);
*/
	float2 offset = float2(StreakLength * InverseResolution.x, 1 * InverseResolution.y) * Radius; /// luminance;

    float4 c0 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, -1) * offset);
    float4 c1 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(0, -1) * offset);
    float4 c2 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, -1) * offset);
    float4 c3 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, 0) * offset);
    float4 c5 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, 0) * offset);
    float4 c6 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(-1, 1) * offset);
    float4 c7 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(0, 1) * offset);
    float4 c8 = ScreenTexture.Sample(LinearSampler, texCoordHalfPixel + float2(1, 1) * offset);
 
    return 0.0625f * (c0 + 2 * c1 + c2 + 2 * c3 + 4 * c4 + 2 * c5 + c6 + 2 * c7 + c8) * Strength + float4(0, 0, 0, 0);

}

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  TECHNIQUES
////////////////////////////////////////////////////////////////////////////////////////////////////////////

technique Extract
{
	pass Pass1
	{
		VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
		PixelShader = compile PS_SHADERMODEL ExtractPS();
	}
}

technique ExtractLuminance
{
	pass Pass1
	{
		VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
		PixelShader = compile PS_SHADERMODEL ExtractLuminancePS();
	}
}

technique Downsample
{
    pass Pass1
    {
		VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
        PixelShader = compile PS_SHADERMODEL DownsamplePS();
    }
}

technique Upsample
{
    pass Pass1
    {
		VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
        PixelShader = compile PS_SHADERMODEL UpsamplePS();
    }
}


technique UpsampleLuminance
{
    pass Pass1
    {
		VertexShader = compile VS_SHADERMODEL VertexShaderFunction();
        PixelShader = compile PS_SHADERMODEL UpsampleLuminancePS();
    }
}

For completeness, here is my (slightly modified?) version of the “BloomFilter.cs” class you’re probably already using (please excuse the namespacing).

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace VRGame.Rendering
{
    /// <summary>
    /// 
    /// Version 1.1, 16. Dez. 2016
    /// 
    /// Bloom / Blur, 2016 TheKosmonaut
    /// 
    /// High-Quality Bloom filter for high-performance applications
    /// 
    /// Based largely on the implementations in Unreal Engine 4 and Call of Duty AW
    /// For more information look for
    /// "Next Generation Post Processing in Call of Duty Advanced Warfare" by Jorge Jimenez
    /// http://www.iryoku.com/downloads/Next-Generation-Post-Processing-in-Call-of-Duty-Advanced-Warfare-v18.pptx
    /// 
    /// The idea is to have several rendertargets or one rendertarget with several mip maps
    /// so each mip has half resolution (1/2 width and 1/2 height) of the previous one.
    /// 
    /// 32, 16, 8, 4, 2
    /// 
    /// In the first step we extract the bright spots from the original image. If not specified otherwise this happens in full resolution.
    /// We can do that based on the average RGB value or Luminance and check whether this value is higher than our Threshold.
    ///     BloomUseLuminance = true / false (default is true)
    ///     BloomThreshold = 0.8f;
    /// 
    /// Then we downscale this extraction layer to the next mip map.
    /// While doing that we sample several pixels around the origin.
    /// We continue to downsample a few more times, defined in
    ///     BloomDownsamplePasses = 5 ( default is 5)
    /// 
    /// Afterwards we upsample again, but blur in this step, too.
    /// The final output should be a blur with a very large kernel and smooth gradient.
    /// 
    /// The output in the draw is only the blurred extracted texture. 
    /// It can be drawn on top of / merged with the original image with an additive operation for example.
    /// 
    /// If you use ToneMapping you should apply Bloom before that step.
    /// 
    /// Example usage:
    ///         // LoadContent:
    ///        _bloomFilter = new BloomFilter();
    ///        _bloomFilter.Load(GraphicsDevice, Content, _width, _height);
    ///        _bloomFilter.BloomPreset = BloomFilter.BloomPresets.One;
    ///        _bloomFilter.BloomThreshold = 0f;
    ///        _bloomFilter.BloomStrengthMultiplier = .8f;
    ///        ...
    ///        Draw:
    ///        Texture2D bloom = _bloomFilter.Draw(_renderTargetScreen, _width, _height);
    ///        GraphicsDevice.SetRenderTarget(null);
    ///
    ///        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.Additive);
    ///        spriteBatch.Draw(_renderTargetScreen, new Rectangle(0, 0, _width, _height), Color.White);
    ///        spriteBatch.Draw(bloom, new Rectangle(0, 0, _width, _height), Color.White);
    ///        spriteBatch.End();
    /// </summary>
    public class BloomFilter : IDisposable
    {
        #region fields & properties

        #region private fields

        //resolution
        private int _width;
        private int _height;

        //RenderTargets
        private RenderTarget2D _bloomRenderTarget2DMip0;
        private RenderTarget2D _bloomRenderTarget2DMip1;
        private RenderTarget2D _bloomRenderTarget2DMip2;
        private RenderTarget2D _bloomRenderTarget2DMip3;
        private RenderTarget2D _bloomRenderTarget2DMip4;
        private RenderTarget2D _bloomRenderTarget2DMip5;

        private SurfaceFormat _renderTargetFormat;

        //Objects
        private GraphicsDevice _graphicsDevice;
        private QuadRenderer _quadRenderer;

        //Shader + variables
        private Effect _bloomEffect;

        private EffectPass _bloomPassExtract;
        private EffectPass _bloomPassExtractLuminance;
        private EffectPass _bloomPassDownsample;
        private EffectPass _bloomPassUpsample;
        private EffectPass _bloomPassUpsampleLuminance;

        private EffectParameter _bloomParameterScreenTexture;
        private EffectParameter _bloomInverseResolutionParameter;
        private EffectParameter _bloomHalfPixelOffsetParameter;
        private EffectParameter _bloomRadiusParameter;
        private EffectParameter _bloomStrengthParameter;
        private EffectParameter _bloomStreakLengthParameter;
        private EffectParameter _bloomThresholdParameter;

        //Preset variables for different mip levels
        private float _bloomRadius1 = 1.0f;
        private float _bloomRadius2 = 1.0f;
        private float _bloomRadius3 = 1.0f;
        private float _bloomRadius4 = 1.0f;
        private float _bloomRadius5 = 1.0f;

        private float _bloomStrength1 = 1.0f;
        private float _bloomStrength2 = 1.0f;
        private float _bloomStrength3 = 1.0f;
        private float _bloomStrength4 = 1.0f;
        private float _bloomStrength5 = 1.0f;

        
        
        private float _radiusMultiplier = 1.0f;


        #endregion

        #region public fields + enums

        public float BloomStrengthMultiplier = 1.0f;
        public bool BloomUseLuminance = true;
        public int BloomDownsamplePasses = 5;
        //public BlendState BlendStateBloom;

        //enums
        public enum BloomPresets
        {
            Wide,
            Focussed,
            Small,
            SuperWide,
            Cheap,
            One
        };

        #endregion

        #region properties

        public BloomPresets BloomPreset
        {
            get { return _bloomPreset; }
            set
            {
                if (_bloomPreset == value) return;

                _bloomPreset = value;
                SetBloomPreset(_bloomPreset);
            }
        }
        private BloomPresets _bloomPreset;


        private Texture2D BloomScreenTexture { set { _bloomParameterScreenTexture.SetValue(value); } }
        private Vector2 BloomInverseResolution
        {
            get { return _bloomInverseResolutionField; }
            set
            {
                if (value != _bloomInverseResolutionField)
                {
                    _bloomInverseResolutionField = value;
                    _bloomInverseResolutionParameter.SetValue(_bloomInverseResolutionField);
                }
            }
        }
        private Vector2 _bloomInverseResolutionField;

        private Vector2 BloomHalfPixelOffset
        {
            get { return _bloomHalfPixelOffsetField; }
            set
            {
                if (value != _bloomHalfPixelOffsetField)
                {
                    _bloomHalfPixelOffsetField = value;
                    _bloomHalfPixelOffsetParameter.SetValue(_bloomHalfPixelOffsetField);
                }
            }
        }
        private Vector2 _bloomHalfPixelOffsetField;

        private float BloomRadius
        {
            get
            {
                return _bloomRadius;
            }

            set
            {
                if (Math.Abs(_bloomRadius - value) > 0.001f)
                {
                    _bloomRadius = value;
                    _bloomRadiusParameter.SetValue(_bloomRadius * _radiusMultiplier);
                }

            }
        }
        private float _bloomRadius;

        private float BloomStrength
        {
            get { return _bloomStrength; }
            set
            {
                if (Math.Abs(_bloomStrength - value) > 0.001f)
                {
                    _bloomStrength = value;
                    _bloomStrengthParameter.SetValue(_bloomStrength * BloomStrengthMultiplier);
                }

            }
        }
        private float _bloomStrength;

        public float BloomStreakLength
        {
            get { return _bloomStreakLength; }
            set
            {
                if (Math.Abs(_bloomStreakLength - value) > 0.001f)
                {
                    _bloomStreakLength = value;
                    _bloomStreakLengthParameter.SetValue(_bloomStreakLength);
                }
            }
        }
        private float _bloomStreakLength;

        public float BloomThreshold
        {
            get { return _bloomThreshold; }
            set {
                if (Math.Abs(_bloomThreshold - value) > 0.001f)
                {
                    _bloomThreshold = value;
                    _bloomThresholdParameter.SetValue(_bloomThreshold);
                }
            }
        }
        private float _bloomThreshold;

#endregion

#endregion

#region initialize

        /// <summary>
        /// Loads all needed components for the BloomEffect. This effect won't work without calling load
        /// </summary>
        /// <param name="graphicsDevice"></param>
        /// <param name="content"></param>
        /// <param name="width">initial value for creating the rendertargets</param>
        /// <param name="height">initial value for creating the rendertargets</param>
        /// <param name="renderTargetFormat">The intended format for the rendertargets. For normal, non-hdr, applications color or rgba1010102 are fine NOTE: For OpenGL, SurfaceFormat.Color is recommended for non-HDR applications.</param>
        /// <param name="quadRenderer">if you already have quadRenderer you may reuse it here</param>
        public void Load(GraphicsDevice graphicsDevice, ContentManager content, int width, int height, SurfaceFormat renderTargetFormat = SurfaceFormat.Color, QuadRenderer quadRenderer = null)
        {
            _graphicsDevice = graphicsDevice;
            UpdateResolution(width, height);

            //if quadRenderer == null -> new, otherwise not
            _quadRenderer = quadRenderer ?? new QuadRenderer(graphicsDevice);

            _renderTargetFormat = renderTargetFormat;

            //Load the shader parameters and passes for cheap and easy access
            _bloomEffect = content.Load<Effect>("VRGameFX/Bloom");
            _bloomInverseResolutionParameter = _bloomEffect.Parameters["InverseResolution"];

            _bloomHalfPixelOffsetParameter = _bloomEffect.Parameters["HalfPixelOffset"];

            _bloomRadiusParameter = _bloomEffect.Parameters["Radius"];
            _bloomStrengthParameter = _bloomEffect.Parameters["Strength"];
            _bloomStreakLengthParameter = _bloomEffect.Parameters["StreakLength"];
            _bloomThresholdParameter = _bloomEffect.Parameters["Threshold"];

            //For DirectX / Windows
            _bloomParameterScreenTexture = _bloomEffect.Parameters["ScreenTexture"];

            //If we are on OpenGL it's different, load the other one then!
            if (_bloomParameterScreenTexture == null)
            {
                //for OpenGL / CrossPlatform
                _bloomParameterScreenTexture = _bloomEffect.Parameters["LinearSampler+ScreenTexture"];
            }

            _bloomPassExtract = _bloomEffect.Techniques["Extract"].Passes[0];
            _bloomPassExtractLuminance = _bloomEffect.Techniques["ExtractLuminance"].Passes[0];
            _bloomPassDownsample = _bloomEffect.Techniques["Downsample"].Passes[0];
            _bloomPassUpsample = _bloomEffect.Techniques["Upsample"].Passes[0];
            _bloomPassUpsampleLuminance = _bloomEffect.Techniques["UpsampleLuminance"].Passes[0];

            //An interesting blendstate for merging the initial image with the bloom.
            //BlendStateBloom = new BlendState();
            //BlendStateBloom.ColorBlendFunction = BlendFunction.Add;
            //BlendStateBloom.ColorSourceBlend = Blend.BlendFactor;
            //BlendStateBloom.ColorDestinationBlend = Blend.BlendFactor;
            //BlendStateBloom.BlendFactor = new Color(0.5f, 0.5f, 0.5f);

            //Default threshold.
            BloomThreshold = 0.8f;
            //Setup the default preset values.
            //BloomPreset = BloomPresets.One;
            SetBloomPreset(BloomPreset);
        }

        /// <summary>
        /// A few presets with different values for the different mip levels of our bloom.
        /// </summary>
        /// <param name="preset">See BloomPresets enums. Example: BloomPresets.Wide</param>
        private void SetBloomPreset(BloomPresets preset)
        {
            switch(preset)
            {
                case BloomPresets.Wide:
                {
                        _bloomStrength1 = 0.5f;
                        _bloomStrength2 = 1;
                        _bloomStrength3 = 2;
                        _bloomStrength4 = 1;
                        _bloomStrength5 = 2;
                        _bloomRadius5 = 4.0f;
                        _bloomRadius4 = 4.0f;
                        _bloomRadius3 = 2.0f;
                        _bloomRadius2 = 2.0f;
                        _bloomRadius1 = 1.0f;
                        BloomStreakLength = 1;
                        BloomDownsamplePasses = 5;
                        break;
                }
                case BloomPresets.SuperWide:
                    {
                        _bloomStrength1 = 0.9f;
                        _bloomStrength2 = 1;
                        _bloomStrength3 = 1;
                        _bloomStrength4 = 2;
                        _bloomStrength5 = 6;
                        _bloomRadius5 = 4.0f;
                        _bloomRadius4 = 2.0f;
                        _bloomRadius3 = 2.0f;
                        _bloomRadius2 = 2.0f;
                        _bloomRadius1 = 2.0f;
                        BloomStreakLength = 1;
                        BloomDownsamplePasses = 5;
                        break;
                    }
                case BloomPresets.Focussed:
                    {
                        _bloomStrength1 = 0.8f;
                        _bloomStrength2 = 1;
                        _bloomStrength3 = 1;
                        _bloomStrength4 = 1;
                        _bloomStrength5 = 2;
                        _bloomRadius5 = 4.0f;
                        _bloomRadius4 = 2.0f;
                        _bloomRadius3 = 2.0f;
                        _bloomRadius2 = 2.0f;
                        _bloomRadius1 = 2.0f;
                        BloomStreakLength = 1;
                        BloomDownsamplePasses = 5;
                        break;
                    }
                case BloomPresets.Small:
                    {
                        _bloomStrength1 = 0.8f;
                        _bloomStrength2 = 1;
                        _bloomStrength3 = 1;
                        _bloomStrength4 = 1;
                        _bloomStrength5 = 1;
                        _bloomRadius5 = 1;
                        _bloomRadius4 = 1;
                        _bloomRadius3 = 1;
                        _bloomRadius2 = 1;
                        _bloomRadius1 = 1;
                        BloomStreakLength = 1;
                        BloomDownsamplePasses = 5;
                        break;
                    }
                case BloomPresets.Cheap:
                    {
                        _bloomStrength1 = 0.8f;
                        _bloomStrength2 = 2;
                        _bloomRadius2 = 2;
                        _bloomRadius1 = 2;
                        BloomStreakLength = 1;
                        BloomDownsamplePasses = 2;
                        break;
                    }
                case BloomPresets.One:
                    {
                        _bloomStrength1 = 4f;
                        _bloomStrength2 = 1;
                        _bloomStrength3 = 1;
                        _bloomStrength4 = 1;
                        _bloomStrength5 = 2;
                        _bloomRadius5 = 1.0f;
                        _bloomRadius4 = 1.0f;
                        _bloomRadius3 = 1.0f;
                        _bloomRadius2 = 1.0f;
                        _bloomRadius1 = 1.0f;
                        BloomStreakLength = 1;
                        BloomDownsamplePasses = 5;
                        break;
                    }
            }
        }

#endregion

        /// <summary>
        /// Main draw function
        /// </summary>
        /// <param name="inputTexture">the image from which we want to extract bright parts and blur these</param>
        /// <param name="width">width of our target. If different to the input.Texture width our final texture will be smaller/larger.
        /// For example we can use half resolution. Input: 1280px wide -> width = 640px
        /// The smaller this value the better performance and the worse our final image quality</param>
        /// <param name="height">see: width</param>
        /// <returns></returns>
        public Texture2D Draw(Texture2D inputTexture, int width, int height)
        { 
            //Check if we are initialized
            if(_graphicsDevice==null)
                throw new Exception("Module not yet Loaded / Initialized. Use Load() first");

            //Change renderTarget resolution if different from what we expected. If lower than the inputTexture we gain performance.
            if (width != _width || height != _height)
            {
                UpdateResolution(width, height);

                //Adjust the blur so it looks consistent across diferrent scalings
                _radiusMultiplier = (float)width / inputTexture.Width;
                
                //Update our variables with the multiplier
                SetBloomPreset(BloomPreset);
            }

            _graphicsDevice.RasterizerState = RasterizerState.CullNone;
            _graphicsDevice.BlendState = BlendState.Opaque;

            //EXTRACT  //Note: Is setRenderTargets(binding better?)
            //We extract the bright values which are above the Threshold and save them to Mip0
            _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip0);

            BloomScreenTexture = inputTexture;

            // To do with Streak...represents one pixel...
             
            BloomInverseResolution = new Vector2(1.0f / _width, 1.0f / _height);

#if ANDROID || LINUX
            // To do with OpenGL, half pixel offset.
            BloomHalfPixelOffset = BloomInverseResolution;// / 2;
#else
            BloomHalfPixelOffset = Vector2.Zero;
#endif

            if (BloomUseLuminance) _bloomPassExtractLuminance.Apply(); 
            else _bloomPassExtract.Apply();
            _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);
            
            //Now downsample to the next lower mip texture
            if (BloomDownsamplePasses > 0)
            {
                //DOWNSAMPLE TO MIP1
                _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip1);

                BloomScreenTexture = _bloomRenderTarget2DMip0;
                //Pass
                _bloomPassDownsample.Apply();
                _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                if (BloomDownsamplePasses > 1)
                {
                    //Our input resolution is halfed, so our inverse 1/res. must be doubled
                    BloomInverseResolution *= 2;

                    //DOWNSAMPLE TO MIP2
                    _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip2);

                    BloomScreenTexture = _bloomRenderTarget2DMip1;
                    //Pass
                    _bloomPassDownsample.Apply();
                    _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                    if (BloomDownsamplePasses > 2)
                    {
                        BloomInverseResolution *= 2;

                        //DOWNSAMPLE TO MIP3
                        _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip3);

                        BloomScreenTexture = _bloomRenderTarget2DMip2;
                        //Pass
                        _bloomPassDownsample.Apply();
                        _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);
                        
                        if (BloomDownsamplePasses > 3)
                        {
                            BloomInverseResolution *= 2;

                            //DOWNSAMPLE TO MIP4
                            _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip4);

                            BloomScreenTexture = _bloomRenderTarget2DMip3;
                            //Pass
                            _bloomPassDownsample.Apply();
                            _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                            if (BloomDownsamplePasses > 4)
                            {
                                BloomInverseResolution *= 2;

                                //DOWNSAMPLE TO MIP5
                                _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip5);

                                BloomScreenTexture = _bloomRenderTarget2DMip4;
                                //Pass
                                _bloomPassDownsample.Apply();
                                _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                                ChangeBlendState();
                                
                                //UPSAMPLE TO MIP4
                                _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip4);
                                BloomScreenTexture = _bloomRenderTarget2DMip5;

                                BloomStrength = _bloomStrength5;
                                BloomRadius = _bloomRadius5;
                                if (BloomUseLuminance) _bloomPassUpsampleLuminance.Apply();
                                else _bloomPassUpsample.Apply();
                                _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                                BloomInverseResolution /= 2;
                            }
                            
                            ChangeBlendState();

                            //UPSAMPLE TO MIP3
                            _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip3);
                            BloomScreenTexture = _bloomRenderTarget2DMip4;

                            BloomStrength = _bloomStrength4;
                            BloomRadius = _bloomRadius4;
                            if (BloomUseLuminance) _bloomPassUpsampleLuminance.Apply();
                            else _bloomPassUpsample.Apply();
                            _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                            BloomInverseResolution /= 2;

                        }

                        ChangeBlendState();

                        //UPSAMPLE TO MIP2
                        _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip2);
                        BloomScreenTexture = _bloomRenderTarget2DMip3;

                        BloomStrength = _bloomStrength3;
                        BloomRadius = _bloomRadius3;
                        if (BloomUseLuminance) _bloomPassUpsampleLuminance.Apply();
                        else _bloomPassUpsample.Apply();
                        _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                        BloomInverseResolution /= 2;

                    }

                    ChangeBlendState();

                    //UPSAMPLE TO MIP1
                    _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip1);
                    BloomScreenTexture = _bloomRenderTarget2DMip2;

                    BloomStrength = _bloomStrength2;
                    BloomRadius = _bloomRadius2;
                    if (BloomUseLuminance) _bloomPassUpsampleLuminance.Apply();
                    else _bloomPassUpsample.Apply();
                    _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);

                    BloomInverseResolution /= 2;
                }

                ChangeBlendState();

                //UPSAMPLE TO MIP0
                _graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip0);
                BloomScreenTexture = _bloomRenderTarget2DMip1;

                BloomStrength = _bloomStrength1;
                BloomRadius = _bloomRadius1;

                if (BloomUseLuminance) _bloomPassUpsampleLuminance.Apply();
                else _bloomPassUpsample.Apply();
                _quadRenderer.RenderQuad(_graphicsDevice, Vector2.One * -1, Vector2.One);
            }

            //Note the final step could be done as a blend to the final texture.
            
            return _bloomRenderTarget2DMip0;
        }

        private void ChangeBlendState()
        {
            _graphicsDevice.BlendState = BlendState.AlphaBlend;
        }

        /// <summary>
        /// Update the InverseResolution of the used rendertargets. This should be the InverseResolution of the processed image
        /// We use SurfaceFormat.Color, but you can use higher precision buffers obviously.
        /// </summary>
        /// <param name="width">width of the image</param>
        /// <param name="height">height of the image</param>
        public void UpdateResolution(int width, int height)
        {
            _width = width;
            _height = height;

            if (_bloomRenderTarget2DMip0 != null)
            {
                Dispose();
            }

            _bloomRenderTarget2DMip0 = new RenderTarget2D(_graphicsDevice,
                (int) (width),
                (int) (height), false, _renderTargetFormat, DepthFormat.None, 0, RenderTargetUsage.DiscardContents);
            _bloomRenderTarget2DMip1 = new RenderTarget2D(_graphicsDevice,
                (int) (width/2),
                (int) (height/2), false, _renderTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
            _bloomRenderTarget2DMip2 = new RenderTarget2D(_graphicsDevice,
                (int) (width/4),
                (int) (height/4), false, _renderTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
            _bloomRenderTarget2DMip3 = new RenderTarget2D(_graphicsDevice,
                (int) (width/8),
                (int) (height/8), false, _renderTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
            _bloomRenderTarget2DMip4 = new RenderTarget2D(_graphicsDevice,
                (int) (width/16),
                (int) (height/16), false, _renderTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
            _bloomRenderTarget2DMip5 = new RenderTarget2D(_graphicsDevice,
                (int) (width/32),
                (int) (height/32), false, _renderTargetFormat, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
        }

        /// <summary>
        ///Dispose our RenderTargets. This is not covered by the Garbage Collector so we have to do it manually
        /// </summary>
        public void Dispose()
        {
            _bloomRenderTarget2DMip0.Dispose();
            _bloomRenderTarget2DMip1.Dispose();
            _bloomRenderTarget2DMip2.Dispose();
            _bloomRenderTarget2DMip3.Dispose();
            _bloomRenderTarget2DMip4.Dispose();
            _bloomRenderTarget2DMip5.Dispose();
        }
    }
}

I had to type it like that or the forum here wouldn’t display it. I didn’t actually have spaces in there in the real version.

Thanks for all the response… I think I’ve gotten there, the biggest thing was those VS_SHADERMODEL and PS_SHADERMODEL lines and then also updating Windows file associations which don’t apparently update when you install MonoGame to use the latest version of the Content Builder Pipeline. I have a warning though that I’m gonna circle back on and maybe some of your other changes/differences from my code would resolve this.

I’ve got one other Content Importer error to figure out but hopefully once I get that, I can test out if everything works, but right now its all building at least.

That’s brilliant, I’m glad your making progress :slight_smile:

Got the other non-shader content manager errors figured out… back to this…

So when i build out of the MGCB Editor, everything compiles correctly. Works perfectly.

When I build my solution in Visual Studio, it fails with the “DX9-style intrinsics are disabled when not in dx9 compatibility mode” and “forced to unroll loop, but unrolling failed” errors.

I’m confused why its different? Shouldn’t behind the scenes it be using the same build process for these? Is there something in my project somewhere that is perhaps using a different/older version of the content pipeline?

Trying your combined bloom fx solution and no compile errors with that (have yet to see it in game to know if it looks the same as what I had before). Does resolve the DX9 error.

Down to the “forced to unroll loop, but unrolling failed” error (in Visual Studio, no errors in the Editor still).

I believe the loop being referred to is this one:

float4 PixelShaderFunction(float2 texCoord : TEXCOORD0) : COLOR0
{
    float4 c = 0;
    
    // Combine a number of weighted image filter taps.
    for (int i = 0; i < SAMPLE_COUNT; i++)
    {
        c += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i];
    }
    
    return c;
}

Looks like you have to edit the csproj file by hand too to point to the correct MonoGame.Content.Builder.Task.targets file.

Looks like its building with the expected version but still throwing errors that I don’t get when building from the Editor.

1>C:\Users\Kris\.nuget\packages\monogame.content.builder.task\3.8.0.1641\build\MonoGame.Content.Builder.Task.targets(138,5): error MSB3073: The command "dotnet C:\Users\Kris\.nuget\packages\monogame.content.builder.task\3.8.0.1641\tools\netcoreapp3.1\any\mgcb.dll /quiet /@:"U:\SourceControl\UltraAktionSteam\Source\Content\Content.mgcb" /platform:DesktopGL /outputDir:"U:/SourceControl/UltraAktionSteam/Source/Content/bin/DesktopGL/Content" /intermediateDir:"U:/SourceControl/UltraAktionSteam/Source/Content/obj/DesktopGL/Content" /workingDir:"U:/SourceControl/UltraAktionSteam/Source/Content/"" exited with code 2.