Monogame GOTCHA's

I thought we should put together a thread with things that aren’t obvious that have caught us out in the past.

A thread you can read through when nothing makes sense and your code won’t do what you tell it to do.

My contribution…

ContentManager Automatic Caching

When you load a shader through the content manager, you do not get a new instance of the shader.
If you load the same shader multiple times, there is only one instance of that shader.

So this pseudo code will not wok

` Foreach mesh part
            Load the shader
            Setup uniforms for this mesh part
  End loop

`

What happens in this case is all the mesh parts will be rendered with the same uniforms, the last set you set.

If you want to use this technique, you have to clone the effect

Thread open to anyone, please add your own GOTCHA’s

1 Like

When I was starting to learn coding, I somehow stumbled through 2 years without realizing objects (that weren’t ValueType) passed through parameters by reference. I thought it made a copy of the object every time (by magic). I thought I had to use the ref keyword to pass something to modify within the method. (Still not exactly sure what the ref keyword does, I abandoned it because the general consensus was that it’s stupid slow and shouldn’t be used)

Eventually I got through an animation editor and found that all my frames changed if I changed one, because I had them all set to the same object I thought I was copying. I usually try to figure out something by myself for a week before I go to a forum, so that’s how long it took me. At that point I realized all of my code was hopelessly slow and bleeding memory leaks.

So my gotcha was not knowing about the Clone() method.

1 Like

Want me to blow your mind? In C# some objects are not passed by reference and are actually copied every time you pass them in a method. They are called structs.
explosion noises

1 Like

You realize you’re using it wrong? There is no need to load anything more than once. Or to clone the effects.

You clone the effects if you have uniforms you want to persist.

Instead of doing effect.Parameters[“SomeString”].SetValue(somevalue); every frame you do it just once.

Since you have an instance of the shader, these persist.

This is particularly useful in multithreaded renderers when you usually create a render command and add it to a list.

Why not, tho? I am not aware of uniforms being slow.

Lol wow. It took me 4 years of C# to find that out.

Well I guess I still wouldn’t use struct much, since passing by reference is pretty much what you want it to do 90% of the time.

Not really, you use value types a whole lot. They have different usecases, of course, but as a quick example, Vector2 and Color are structs and are passed by value. I have a custom code highlighter which colors structs yellow and classes green so I immediately know what is what. Dunno why VS color scheme doesn’t do that by default.

1 Like

Good idea. I actually have want to make a valuetype class, but couldn’t figure it out, but that’s what you get when you’re self taught.

They can be incredibly slow as they involve CPU -> GPU upload, which is something you want to front-load and not interleave with state/draw calls:

// This is something that idiots do
foreach (light)
    setup uniforms // stalls for every light
    draw light volume shape

// When you're using your head
foreach (light)
   setup uniforms into target buffers
foreach (light)
   bind uniform buffer range
   draw light volume shape

IIRC, the very first change I made to my local copy of MG was to overhaul cbuffer handling so I could lock them and keep MG’s effects from messing with them or binding overtop of them in order to have external buffers for light / IBL parameters so that my stuff could actually run on an Intel and not cry.

The ref keyword is essentially what objects are passed by.

List is a object type.

public List<int> integerList = new List<int>();

public void PassMe( List<int> t)
{  
   t[0] = 1;
   //  t in this case is a placeholder for integerList itself.
}

same as this so ref here is redundant.

public void PassMe(ref List<int> t)
{  
       t[0] = 1;
       // the reference t points to the same memory area as used by the thing outside of it the reference that is passed points to the original memory area not a new area with the old values copied in.
}

Values are passed by reference as well but they are first copyed into registers and placed on the stack and then the new memory structure is passed by reference a (new reference) into the object hence the values are passed not the old memory location.

a plain old int is a value type.

public void PassMe( int t)
{  
  var i = t; // values in t are copied into a new reference for a new memory area
}

same as

int t =0;
public void PassMe()
{  
       var i = t; // values in t are copied into a new reference for a new memory area
}

this however is not the same.

public void PassMe(ref int t)
{  
   var i = t; 
    //  i is t  now the value hasn't been copied like above the reference has. Hence now this struct is passed as if it were a object like the list was.
}

A reference itself is a container that holds a value that points to were memory is stored at.

If you ever get confused by it all just keep in mind that references and passing is about what is being copied in New or Old data.

1 Like

question: isn’t changing the shader (as the original posted said as alternative to avoid changing parameters) for each object rendered more expensive? ( I think I read that somewhere else, and that’s the main reason I only use a single copy of effect )