Silverlight 3 Speed Optimizations – The Ultimate Game Loop!

Edit: this post is now replaced by the more in-depth view here:



I just ported my Shock game to Silverlight 3.

Getting the graphics to work as before (and better), took me about an hour reading through docs. But the changes took about 5 minutes.

I’ll just list them here for you in case you’re building one of the next generation Silvelight games:

1.      In your Silverlight Control’s .HTML or .aspx file set EnableGPUAcceleration=”true”. This allows Silverilght to use the GPU for controls that you tell it to (see below).

Also set MaxFrameRate=”1000″. I’ll explain why we set the frame rate to such a high value in a bit.

Here’s how Shock’s Silverlight control looks after the change:

<asp:Silverlight ID=”Xaml1″ runat=”server” Source=”~/ClientBin/Shock.xap” MinimumVersion=”3.0″ Width=”640px” Height=”480px” EnableGPUAcceleration=”true” MaxFrameRate=”1000″/>

2.      Find elements in your application that move, scale, rotate or blend (use transparency).

For each of these elements turn on hardware acceleration from XAML by setting CacheMode=”BitmapCache” like this example:

                <Image x:Name=”imgBolt” CacheMode=”BitmapCache”











                        <RectangleGeometry x:Name=”boltClipRect”




This really helps (in my case CPU down from 10% to < 3%)! J I enabled hardware acceleration for the balls and for the lightning bolt in Shock. Now the animations and redraws look smoother.

3. If your game loop uses a timer, storyboard, or thread, change it to use CompositionTarget.Rendering instead. The reason is that Silverlight 3 can render animations more smoothly than Silverlight 2.

Also, your timer will typically be called every 15 msec now (60 FPS). In Shock, the balls move through Storyboard-s. I used to hit-test the balls with bricks, paddle, and screen 60 times per second. Now I see that sometimes animations will be drawn faster than this, and in some cases I could notice balls being drawn on top of bricks, or the paddle. With faster animations and better runtime, the effect is easier to notice.

This is the reason why I wanted to recalculate the hit testing and update animations faster. The easiest way to do this in Silverlight today is by using CompositionTarget.Rendering and setting MaxFrameRate to a high number (1000 is pretty good, although 200 generates almost the same results already). I used MaxFrameRate=”1000” in conjuction with CompositionTarget.Rendering to achieve smoother animations in Shock.

That’s for today! Hope you liked it!

I’m trying to stay away from posting yet-another-“Silverlight 3 is released”-post and listing all the benefits to get a temporary boost in reads. Instead I hope my own findings will bring you unique value and enjoyment developing Silverlight applications!

If you’re still interested in what’s new in SL 3, this is the official list

Comments (13)

  1. Denis says:

    The game is very laggy now. I get long pauses and sudden jumps. With new changes I am failing on the levels I used to breeze through.

  2. nikola says:

    Hi Denis, thank you for the feedback! I wonder what did I make wrong…

    could you send me your configuration (CPU speed/OS)?

    I appreciate your feedback!


  3. Denis says:

    I have 32bit Vista desktop with 2GB memory, ATI Radeon Xpress 1200 video and Core2 E6420 cpu. My Silverlight runtime version is 3.0.40624.0.

  4. nikola says:

    Thanks Dennis,

    hmm, I tried a few different things…but want to do some more research on speed…

  5. Isak says:

    Nikola, would you recommend switching from a Storyboard to CompositionTarget.Rendering, even if the Storyboard has no duration? E.g., the farseer physics samples, if you have seen those.

  6. nikola says:

    Hi Isak,

    Depends on your scenario. There are 2 things to take into account:

    * the resolution of CompositionTarget.Rendering is consistently 1000/frameCount (about 16 msec by default). I’m not sure if the Storyboard method can achieve the same resolution or achieve it consistently.

    * the storyboard will fire the event even if the Silverlight application is invisible. CompositionTarget.Rendering will fire the even whenever the screen renders (e.g. if your Silverlight application window is covered by another application CompositionTarget.Rendering may not be called).

    To see some real-life implications try this:

    1. open in Internet Explorer

    2. Open some other page in another browser tab

    3. Wait 2-3 seconds and switch back to the first tab

    -> you’ll notice the star field will be "empty". This is because CompositionTarget.Rendering wasn’t called.

    -> btw, you can compensate for this behaviour in code (see fixed version of the starfield here:

    I’m doing deep investigation to compare 5 different methods to create game loop (DispatcherTimer, Storyboard, Storyboard as Trigger, Thread and CompositionTarget.Rendering) and currently discussing few related questions with the Silverlight team. I’ll post all findings in this blog + some guidance on what to use and when.

    Thank you for the interest.

  7. Isak says:

    Interesting. Thanks for the response.

  8. nikola says:

    Hi Dennis,

    Could you try the Shock again and see how is it running for you now?

    I made few small tweaks (will publish some data about it) and wonder what is the effect of those on your PC.

    Thank you!


  9. nikola says:

    Hi Isak,

    I published a comprehensive overview of different game loop methods:

    Hope you like it,


  10. Ethen says:

    I have noticed that Silverlight doesn’t render frames when the browser is minimized. I have been

    told that this is due to optimizations in Silverlight.

    Is there a way to get the rendering going when the browser is minimized or when the silverlight player is launched on a machine with no display?



  11. nikola says:

    Hi Ethen,

    There isn’t a way as far as I know. You have to account for the page not being rendered in code.

    There are several ways to do this: either by measuring the time between frames and working with absolute time values (not frame values)

    or by doing some other custom stuff, for example:



    In the above example, I fix the issue by counting how many stars are out of screen. If there are more than 2 stars out at the same time, I assume browser was minimized or rendering didn’t happen and account for that. See UpdateStars() in the "after" link

  12. Ethen says:

    Hi Nikola,

    We are using MediaElement as against Canvas in your example. If I launch the media player page in a separate tab, the MediaElement state doesn’t change to “Opened” unless the browser

    is not minimized. So, the playout doesn’t start… any thoughts?


  13. nikola says:

    Hi Ethen,

    I think this is by design. What is the scenario you’re trying to achieve? Why do you want the media to start playing even though the page is not visible?

    Or do you want to detect when the control is created or something like that?

    Knowing the actual user scenario you’re trying to achieve will help me a lot to try and resolve the issue.