Loading shader at runtime fails

Hey guys,
I’m working on some shaders and when compiling 2MGFX complained saying “not enough arithmetic instruction slots”, so i upgraded the pixel shader profile to ps_4_0 (using DX for now). I wanted to load effects from binary by extending Effect and calling base(GraphicsDevice, effectBytes) like MonoGame does for the stock effects , but after the shader profile upgrade SharpDX gives me a runtime exception “The parameter is incorrect”. After googling around a bit, it seems this can mean pretty much anything. Any ideas what might be causing this/how to solve this? Profiles ps_4_0_level_9_3 and lower work fine, but 512 instruction slots is still not enough :confounded:
Also, does anyone know what devices don’t support ps_4_0 or where I can get a list of supported devices per shader profile? Thanks!

Yes that can mean almost anything, maybe you are specifying a multi sample count when creating your rendertarget, that is known to throw that error.

Apart from that Shader Modell 4 means at least DirectX10 compatible card and Windows Vista.
For Amd that would mean the HD 2000 series and for nvidia the GeForce 8000 series. Both are almost 10 years old.

What comes to mind:
Do you use [unroll] ?
Which registers do you use ?
Do you use Geometry shaders ?
Maybe optimizing the shader could help ?

Maybe you could find the culprit here ? https://msdn.microsoft.com/en-us/library/windows/desktop/bb509657(v=vs.85).aspx

Thanks for the information! I’m not even creating a render target yet, the exception is thrown when creating an Effect (so in the Effect constructor that takes a GraphicsDevice and a byte array). I stepped through the MonoGame source code and it seems it’s the creation of a new PixelShader in Shader.DirectX that’s causing the exception to be thrown.
Not sure if i should create an issue on the GitHub page since I seem to be the only one with this specific problem, so it’s probably not a bug in MonoGame.

Some of the shaders are pretty large and I’d much prefer to upgrade the profile than try and shrink them so they work on the older profiles, but thanks for the suggestions :slightly_smiling:

You could also try to comment some parts of the code to narrow the field of possible error generators

Yeah, I’m splitting up the shader right now, the first few parts did not give me any errors. Thanks!

Oops, I was using a shader I compiled previously with shader profile ps_4_0_level_1. If I use ps_4_0 I can’t get any shader to load (though compilation with 2MGFX still works fine). I tried with a minimal shader, but get the same exception. ps_4_0_level_9_1 and ps_4_0_level_9_3 work fine. :sob:

EDIT: For completeness, here’s the shader I tested with:

float4 MainVS(float4 Position : SV_POSITION) : SV_POSITION
{
     return Position;
}

float4 MainPS() : COLOR0
{
    return float4(1.0, 0.0, 0.0, 1.0);
}

technique ThisIsStillNotWorking
{
    pass {
        VertexShader = compile vs_4_0 MainVS();
        PixelShader = compile ps_4_0 MainPS();
    }
}

@Jjagg: have you tried with the shader from the effect template ? (when using pipeline and new effect)

Your minimal example seems wrong to me (see my post), and COLOR0 should be replace by COLOR (no zero). As the shader compiler is a lot more “tighter” than the one used by VS with XNA, it may cause the issue.

Just tried this with the template and the same thing happens. ps_4_0_level_9_* works fine, but ps_4_0 or higher gives me the same exception.

I have this exact same issue. I’m using integrated Intel HD Graphics 4600, which, while no powerhouse, is supposed to be compatible with DirectX 11. I tried it with the template as well, and SharpDX throws an exception when attempting to load the effect.

And, unfortunately, I’m already setting the graphics profile to HiDef in the Game1 constructor…

graphics.GraphicsProfile = GraphicsProfile.HiDef;

…and the issue still persists. I’m also using the latest build of MonoGame available via installer.

EDIT: Never mind, it turns out I was unwittingly calling graphics.ApplyChanges() before I set the profile to HiDef, with the result that the GraphicsDevice was still targeting Reach. Setting the graphics profile to HiDef is the solution to the SharpDX exception problem.

However, now that no exceptions are thrown, I have the new problem that my shader, which works using Reach, no longer works right when using HiDef. The screen only displays a solid color.

How do you declare the samplers in the shader ? There are some things to do in a particular manner to make sure the sampler is right. (If this is a glitch between reach and hidef)

I solved the Reach/HiDef problem by using this specific vertex shader output struct as the input for my pixel shader:

//This was taken straight from some MSDN example
struct VS_OUTPUT
{
	float4 Position   : SV_POSITION; // vertex position 
	float4 Diffuse    : COLOR0;      // vertex diffuse color (note that COLOR0 is clamped from 0..1)
	float2 TextureUV  : TEXCOORD0;   // vertex texture coords
};

And here’s the sampler, since you asked:

SamplerState TextureSampler
{
	Filter = Point;
	AddressU = Clamp;
	AddressV = Clamp;
};