XNA Creators Club Online
Page 1 of 1 (13 items)
Sort Posts: Previous Next

Background loading- trying to create a thread-safe ContentManager?

Last post 9/2/2009 2:08 PM by Kevin Gadd. 12 replies.
  • 8/28/2009 5:07 AM

    Background loading- trying to create a thread-safe ContentManager?

    So I've been toying with this idea for some time now, but my limited experience with multithreading is making me wonder how plausible my ideas really are~

    I'm aware that the ContentManager, as it is, is not thread-safe.  I've also already gone thru and gotten working a multi-threaded loading screen with a basic animation playing while the content loads in the background (this, thanks to other posts here!)

    What I've been thinking about tho, is making my game virtually load screen free~ That is, streaming in content as needed.  The issue obviously, is trying to call ContentManager.Load in a background thread, while my world object is querying about whether certain assets are loaded, and if so, calling ContentManager.Load to retrieve them, in the main thread.

    So, there's 2 things I want to do:
    1) Add query functionality to the ContentManager to check if an asset is loaded already or not, without actually -requesting- it to load.
    2) Add proper locks and whatnot to allow one thread to access already loaded content while another thread is loading content.

    The first should be negligible at worst, to do, but the second is the one that I'm really not up-to-par with me multi-thread-coding enough to be sure about the plausibility of.  Would this be possible?  Perhaps by means of some sort of invoking of the main thread to add an asset to it's loadedAssets Dictionary once the loading is actually complete?

    Of course, there may be other objects that need to be worried about as well as far as loading content goes- I'm not overly familiar with the inner-workings of how XNA loads content.
  • 8/28/2009 5:47 AM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Have a look at ContentTracker (in my sig). I'm think it handles both of your stated goals, but regardless it should be helpful to see the inner workings of a custom ContentManager.

    It supports Async loading by loading sequentially on a separate thread. The items to be loaded are queued up and yes, it calls a delegate on the main thread once an object has been loaded. This is probably the best approach when implementing a streaming content situation.

    It includes a small example game implementing the streaming content. To minimize download size, I made all the content tiny, but when you start loading large models / textures, you may notice an issue I stumbled against: When the graphics device resources (vertex & index buffers) are instantiated, it blocks the main thread. I haven't figured out a way around this yet, other than to ensure all of the content is broken into relatively small bits and possibly to stagger the calls to load them (not nice). It may not be a problem for you though... even in Unreal Tournament 3, the start of the levels always seemed to stutter a bit as it streamed in the last of the content (well that's what I assumed it was doing anyway).





  • 8/28/2009 6:16 AM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Your post doesn't show your sig right now- have you maybe disabled it recently and forgotten to show it again?

    It sounds like what you describe ContentTracker to be is exactly what I'm looking for, so I look forward to peeking at it's workings! ^^
  • 8/28/2009 2:49 PM In reply to
    • (2342)
    • premium membership MVP
    • Posts 1,226

    Re: Background loading- trying to create a thread-safe ContentManager?

    That's weird, I see his sig just fine.  Here's the link: http://contenttracker.codeplex.com/

    Also with regards to the "blocking the main thread" issue...typically what games will do is they do all of the I/O and conversion stuff on a worker thread, then hand off the final processed data to the main thread.  The main thread then does the final task of creating the graphics resource and filling it with the data.  It doesn't totally solve the problem since you still have to do it on the main thread, but at least it lets you do it at a time that's convenient...and also when you're not in a lost device state.  Unfortunately since the ContentTypeReaders for things like Texture2D, Effect, and Model aren't set up to do this so you'd have to make your own version along with new intermediate types.
    Matt Pettineo | DirectX/XNA MVP


    Ride into The Danger Zone | PIX With XNA Tutorial
  • 8/28/2009 7:01 PM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Ah- I can see signatures now- but thank you for the link anyways MJP^^
  • 8/28/2009 8:59 PM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Make sure you acquire a lock while loading resources, and acquire that same lock when your graphics device is reset. You can do this by attaching event handlers to GraphicsDeviceManager.DeviceReset and GraphicsDeviceManager.DeviceResetting. Acquire the lock (using Monitor.Enter) in DeviceResetting and release it (using Monitor.Exit) in DeviceReset. Acquire the same lock (you can use a lock () block for this probably) before loading textures or other device resources. If you don't do this you'll get intermittent failures.

    Also, you should be aware that it's currently close to impossible to do much content streaming in an XNA game - between the tremendous amount of garbage generated by the Texture2D loader, and the apparently unavoidable pauses when creating resources, your game will stutter a lot. (There may be some ways around this, though, if you're dead-set on streaming.)
    Kevin Gadd, Squared Interactive
    Development Blog | Twitter
    Help playtest my game, Inferus!
  • 8/28/2009 9:37 PM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Monitor.Enter and Monitor.Exit are not available on the Xbox, unfortunately.
    On the other hand, the device does not generally get reset on the Xbox, after you've started your game.

    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 8/28/2009 9:56 PM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Monitor.Enter and Exit are available on Xbox.

    The C# lock statement translates into Monitor.Enter and Exit calls, so the C# language itself would be broken if these were not available!
    XNA Framework Developer - blog - homepage
  • 8/28/2009 10:54 PM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    jwatte:
    Monitor.Enter and Monitor.Exit are not available on the Xbox, unfortunately.
    On the other hand, the device does not generally get reset on the Xbox, after you've started your game.
    You're probably thinking of Monitor.Wait/Monitor.Pulse.

    You're correct about device resets - the only case I know of where a reset triggers on the 360 is if you call GraphicsDeviceManager.ApplyChanges.
    Kevin Gadd, Squared Interactive
    Development Blog | Twitter
    Help playtest my game, Inferus!
  • 8/29/2009 2:44 AM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Yes, I was thinking of Pulse/Wait. Sorry to confuse the issue.

    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 8/30/2009 2:28 AM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    So does that mean on the XBox, you wouldn't have to worry about handing lost/reset devices and such if you're never going to call GraphicsDevice.Apply() then?
  • 9/1/2009 4:42 AM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Looking more deeply into this subject, I have things mostly working how I intend, but to have some things more efficient on some other cross-thread code, I have a question:

    I know it's not thread-safe to have situations where an object can be modified in one thread while at the same time being read in another thread, but if you can GUARANTEE that the object will not be modified, is it considered safe to read the same object from multiple threads at the same time?
  • 9/2/2009 2:08 PM In reply to

    Re: Background loading- trying to create a thread-safe ContentManager?

    Nyxojaele:
    Looking more deeply into this subject, I have things mostly working how I intend, but to have some things more efficient on some other cross-thread code, I have a question:

    I know it's not thread-safe to have situations where an object can be modified in one thread while at the same time being read in another thread, but if you can GUARANTEE that the object will not be modified, is it considered safe to read the same object from multiple threads at the same time?
    Yes.

    Note that you need to make sure that the data structure you're using doesn't cause modifications when read. This is true of most data structures, but not all - for example, you wouldn't want to read from a 'least recently used' or 'most recently used' data structure from multiple threads at the same time.
    Kevin Gadd, Squared Interactive
    Development Blog | Twitter
    Help playtest my game, Inferus!
Page 1 of 1 (13 items) Previous Next