As a foreword, the exact same code works just fine in XNA, but Monogame throws an exception. This likely requires someone familiar with the Monogame rendering pipeline.
During the Draw section of my game, there's a ShadowmapResolver that renders out a texture that is the final calculated light pattern from a given light. It's receiving an exception when rendering from what is essentially EffectPass.Apply()
complaining that from somewhere within Mono theres an attempted cast from int32[]
to Single[]
. Here's my code that calls it:
private void ExecuteTechnique(Texture2D source, RenderTarget2D destination,
string techniqueName, Texture2D shadowMap)
{
graphicsDevice.SetRenderTarget(destination);
graphicsDevice.Clear(Color.Transparent);
resolveShadowsEffect.Parameters["renderTargetSizeX"].SetValue((float)baseSizeX);
resolveShadowsEffect.Parameters["renderTargetSizeY"].SetValue((float)baseSizeY);
if (source != null)
resolveShadowsEffect.Parameters["InputTexture"].SetValue(source);
if (shadowMap != null)
resolveShadowsEffect.Parameters["ShadowMapTexture"].SetValue(shadowMap);
resolveShadowsEffect.CurrentTechnique = resolveShadowsEffect
.Techniques[techniqueName];
try
{
foreach (EffectPass pass in resolveShadowsEffect.CurrentTechnique.Passes)
{
pass.Apply(); // <--- InvalidCastException re-enters my program here
quadRender.Render(Vector2.One * -1, Vector2.One);
}
}
catch (Exception ex)
{
Util.Log(LogManager.LogLevel.Critical, ex.Message);
}
graphicsDevice.SetRenderTarget(null);
}
And here is the stacktrace:
at Microsoft.Xna.Framework.Graphics.ConstantBuffer.SetData(Int32 offset, Int32 rows, Int32 columns, Object data)
at Microsoft.Xna.Framework.Graphics.ConstantBuffer.SetParameter(Int32 offset, EffectParameter param)
at Microsoft.Xna.Framework.Graphics.ConstantBuffer.Update(EffectParameterCollection parameters)
at Microsoft.Xna.Framework.Graphics.EffectPass.Apply()
at JASG.ShadowmapResolver.ExecuteTechnique(Texture2D source, RenderTarget2D destination, String techniqueName, Texture2D shadowMap) in C:\Users\[snip]\dropbox\Projects\JASG2\JASG\JASG\Rendering\ShadowmapResolver.cs:line 253
So it would appear that one of the parameters of my shader which I am trying to set is confusing monogame somehow, but I don't see what it could be. I'm pushing floats, not int arrays. I even tried changing the RenderTarget2D.SurfaceFormat
from Color to Single for all my targets and textures, still gives the exact same error.
Outside of the function I gave, in a broader scope, there are no other parameters being set since another EffectPass.Apply
. There are multiple other effects that render without error before this one.
In case it helps, here's the source for the MonoGame Framework regarding ConstantBuffer.SetData()
private void SetData(int offset, int rows, int columns, object data)
{
// Shader registers are always 4 bytes and all the
// incoming data objects should be 4 bytes per element.
const int elementSize = 4;
const int rowSize = elementSize * 4;
// Take care of a single element.
if (rows == 1 && columns == 1)
{
// EffectParameter stores all values in arrays by default.
if (data is Array)
Buffer.BlockCopy(data as Array, 0, _buffer, offset, elementSize);
else
{
// TODO: When we eventually expose the internal Shader
// API then we will need to deal with non-array elements.
throw new NotImplementedException();
}
}
// Take care of the single copy case!
else if (rows == 1 || (rows == 4 && columns == 4))
Buffer.BlockCopy(data as Array, 0, _buffer, offset, rows*columns*elementSize);
else
{
var source = data as Array;
var stride = (columns*elementSize);
for (var y = 0; y < rows; y++)
Buffer.BlockCopy(source, stride*y, _buffer, offset + (rowSize*y),
columns*elementSize);
}
}
Is this some sort of marshaling problem? Thanks for your time!
Edit: P.S.: The exception is an InvalidCastException
and not a NotImplementedException
.
Not sure if this helps you or not but the only casting I see being done is the data as Array. I would bet that it is crashing on the line :
Buffer.BlockCopy(data as Array, 0, _buffer, offset, rows*columns*elementSize);
or
var source = data as Array;
Because they don't do any type checking before casting there. If that is the line it is crashing on it is because they don't seem to support non-array data values. I don't know this framework well enough to give you a solid answer on how to work around this. I would probably report this as a bug to the makers here
Try 2MGFX tool which optimizes shaders for monogame. MGFX tool tips
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With