Psycho Potato

Good day all, I'm new to HLSL/XNA and C#, and here's a rather silly question for y'all. Taking "Effect.fx" that came with the XNA documentation, I see the following "global" declarations:

uniform extern float4x4 WorldViewProj : WORLDVIEWPROJECTION;
uniform extern texture UserTexture;


... and say if I were to add one CurrentTime variable for animation, it'll look something like this:

uniform extern float4x4 WorldViewProj : WORLDVIEWPROJECTION;
uniform extern texture UserTexture;
uniform extern float CurrentTime;


From within my game code I do this to update game time for animation:

protected override void Draw(GameTime gameTime)
{
float fCurrTime = ((float)gameTime.ElapsedTime.Millisecond);
effect.Parameters["CurrentTime"].SetValue(fCurrTime);

// Other render stuff goes here...
}


Now my animation seems working well right now and by right I shouldn't be worrying. But then I realized what the XNA document says (EffectParameter.SetValue):

"Setting the value of an effect parameter is a slow operation. Avoid high frequency calls."


Hang on a sec, that's exactly what I'm doing!! Ever since then, the more new parameters are added to my shader code the more worried I am. But looking at the CPU usage it's currently 3% (yah I'm not doing too much at the moment), so I'm wondering should I be worrying about the performance at all Is my case considered "high frequency" one Are there any read-backs from the GPU for this operation Is there any alternative to setting shader parameters


Thanks a lot, in advance.
_Ben.




Re: XNA Framework HOWTO: The fastest way to update shader parameters?

Leaf.

There isn't really an alternative to setting effect/shader parameters. I suspect that the what the docs meant is try to manage your parameters so that you only set them as often as necessary. For example if you were drawing 100 objects using the same effect then you should try to set the time parameter only once per frame not 100 times per frame. Another small point for your particular example is that you are looking up the "CurrentTime" effect parameter every time you set it, ideally you would get a reference to that particular EffectParameter and then use the EffectParameter reference to set the value but this, like setting the values, is not going to become a problem until you have a lot more effects and rendered objects.

Cheers,
Leaf.






Re: XNA Framework HOWTO: The fastest way to update shader parameters?

Jon Watte

The pipeline will stall a lot when you change effects, and stall a little bit when you change parameters. However, if you stall the pipeline to change one parameter, it is often almost free (or at least comparatively cheap) to also set another parameter.

This is why it's good to improve batching. Whatever you can do to make sure you draw at least 2,000 triangles in each call to draw will help you in case you are vertex transform or batch limited. However, if you are fill limited, none of this will matter.

From your code, though, you could save some CPU load by getting the parameter handle once (as an EffectParameter) and then calling SetValue() on it when you need to change it.

// in initialization
EffectParameter wvpParam = theEffect.Parameters["WVP"];
EffectParameter texParam = theEffect.Parameters["Texture"];

...

// in drawing
wvpParam.SetValue(myMatrix);
texParam.SetValue(myTexture);
do the drawing






Re: XNA Framework HOWTO: The fastest way to update shader parameters?

Shawn Hargreaves - MSFT

It's important to differentiate between CPU and GPU performance here. Because the CPU and GPU run in parallel, the overall performance ends up being defined by whichever of the two is slowest, so there is no point trying to speed up the other.

What Jon says about pipeline stalls is spot on for GPU performance, but on the CPU side, setting many parameters will cost more than just setting a few. Obviously some parameters will always need to change, for instance you can't make a very interesting game without ever altering the camera and world matrices! Other parameters like the texture settings for a material, or the lighting setup, may well be constant across the whole game, though. You can get a useful performance gain by just setting those values once when you load the content, and then only bothering to update the things that really are changing each time you draw the object.

Jon's advice about caching the EffectHandle is very good: this can make a big difference.

Also bear in mind, though, that none of this stuff matters if your game is already running fast enough! It's a waste of time to optimize something unless you really need to, so I wouldn't worry about any of this until (and if) you actually do run into performance problems.





Re: XNA Framework HOWTO: The fastest way to update shader parameters?

Psycho Potato

Thanks Leaf, Jon and Shawn. It is consistently pointed out that getting a handle to parameter will speed things up (and make a big difference), and I guess the slowdown is actually coming from the "look-up" of parameters, rather than the way it's being sent across the bus down to the GPU. Good thing to know!





Re: XNA Framework HOWTO: The fastest way to update shader parameters?

Ultrahead

Jon, you mean "EffectParameter wvpParam = ...", right "EffectHandle" was the one to use in MDX ...




Re: XNA Framework HOWTO: The fastest way to update shader parameters?

Jon Watte

So right, UltraHead. EffectParameter it is.