Issue with EffectParameter.SetValue when using a float array.

I have been having an issue with setting a float[2] array on an EffectParameter. In code, I do this:

if (windowSize != null)
    windowSize.SetValue(new float[] { sceneMapTexture.Width, sceneMapTexture.Height });

But when it gets to that line, I get:

System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'

It shows me that windowSize has Data that is a float[2], so why does this not work?

I think this may be because of optimizations, are you using the array in your effect? Make sure you really access both floats

Yes, it is used in the shader multiple places. For example, in one pass of the vertex shader,

float2 texelSize = 1.0 / windowSize;

texelSize is then multiplied by a float, added to texCoord, and stored in the output.

Also, I don’t think that optimization would make sense when the debugger shows me that the parameter’s data is a float[2], so the EffectParameter does exist with both elements of the array.

I did not write this shader as I do not have a lot of experience with shader programming. This is one reason why I am running into this issue.

Im not sure, but the way i set float2 is with a Vector.
Try setting it like this
windowSize.SetValue(new Vector2 (sceneMapTexture.Width, sceneMapTexture.Height))

Yes. That works. I don’t know why float[2] doesn’t, though. Still seems like a bug to me.

Hi James,

float arrays are not vectors, you can’t call float[].Normalize() :smiley:

C# is strongly typed so you do need to use the correct types all the time I’m afraid.

a float[2] is something different than a float2 … the later is a vector while the first is an array.

EffectParameter is basically just copying values over and it may just handle your float[2] as what you send in and tries to fill a float[2] in the shader. but there is none. GPUs are not managed like C#/.Net

Those are both very valid points, and when you present it that way, it does actually make sense that it would expect a Vector2. However, the aggravating part is that MonoGame is now full of instances like this where something from XNA will not just simply compile. That is why I have recently been looking at FNA to use when porting. Granted, MonoGame is great when starting from scratch.

Finally, the really aggravating and confusing part of this is that the debugger shows the type of the Data member of the EffectInstance to be a float[2], but that will not work to set the data. I get that the GPU is not managed and the C# code is, but doesn’t that mean that MonoGame is converting my passed Vector2 in to a float[2]? Why not just show it as a Vector2 which is what it expects? And, yes, I know that the answer here is that in unmanaged languages like C++, in memory there is no difference between a Vector2 and a float[2]. They are both just contiguous bytes of memory that store 2 float values. What I originally had worked in XNA, but MonoGame broke it while not even displaying the appropriate data type when in the debugger, which cost me hours of time searching for answers before I even posted.

Looking at the source, a float-array is handled correctly by EffectParameter.SetValue. It copies each value of the array to the corresponding place/index in the target array. If that target is not an float-array it will fail with an out-of-index-exception. (the target is EffectParameter.Elements not Data)

What that “Elements” actually is, is created when the Effect is loaded by Monogame. So when the shader says it’s a float2, the “Elements[]” of the Parameter is actually an array (with 1 item) of type Vector2 - and not an array of floats. That’s why you get that error. (Not sure what Data is used later on)

Well - monogame COULD do checks about the datatype and do conversions or fill an Vector from the values of an array. But that would issue slow downs. Nobody wants slowdowns in game development :slight_smile: I personally prefer the way MG does it in the fastest possible way and let it to me to take care of type safety

I wonder how original XNA did this differently

1 Like

I would suggest not relying on the debugger that much when it comes to integration with hlsl, as in my experience there is some stuff that are not functioning as expected.
For example, in this situation I would cast a doubt on the way I do stuff, look at the effect source code and after seeing its a “float2” type, I would google “setting a float2 hlsl/monogame” or something like that.
Which will result in

I had a similar problem setting specific elements in an hlsl array parameter and that logic helped me back then (dont, set the entire array :relieved:).