Gamasutra.com - Streaming for Next Generation Games
It's free to join Gamasutra!|Have a question? Want to know who runs this site? Here you go.|Targeting the game development market with your product or service? Get info on advertising here.||For altering your contact information or changing email subscription preferences.
Registered members can log in here.Back to the home page.

Search articles, jobs, buyers guide, and more.

By Fredrik Lönn
[Author's Bio]
Gamasutra
November 30, 2006

Streaming for Next Generation Games

arrowrightPage One
arrowrightPage Two
arrowrightPage Three

 



[Submit Letter]

[View All...]
  


Features

Streaming For Next Generation Games


Stream Queue Items

When a game system needs to load a resource through the stream system, it creates a stream item and passes it to the streamer. The stream item has the id of the file (the name or hash, depending on if we run in debug or release), the offset we need to read in the file, and the size of the read. It also contains a pointer to an object implementing a callback interface that will be called when the data is available or if something goes wrong.

struct StreamQueueItem
{
     std::string filename;
     unsigned int file_offset;
     unsigned int size;
     IStreamQueueItemCallback *callback;
};


The stream items are kept in one of several queues in the stream system. The streamer pops as many disc-stored items in the current queue as possible and fits them into the buffer. Data is then read by doing one read request from the reader thread. The buffer will eventually be filled by data when the threaded read operation completes, and during this time the buffer is marked as locked. When the read operation completes, the buffer is unlocked and the reader thread switches to repeat the process on the other buffer.

After the switch, a callback to the game system is generated for each stream queue item with a pointer to the newly loaded data, a pointer into one of the static buffers, and the size of the read data. While the callbacks are being issued, the buffer is marked as locked to prevent the read thread to overwrite the data before the game has had a chance to process it. When code called from one of the callback functions needs to access the data after the callback it has to lock the buffer. It is then up to the game system to unlock the buffer - until this happens, streaming will stall.

When running from a DVD, data processing is typically much faster than data read. As always, do profiling and tuning on the actual system you are designing for.

Priorities

Stream items are added to the streamer at one of several priority queues. The queues are processed in priority order, but we only change the current queue when reading the next item would cause a seek. In practice, you probably do not need more than three priority queues.

When the streaming system is under stress, changes in the game's state might cause the data to be obsolete before its read. Imagine an NPC that wants to play back dialogue, but before the dialogue has finished loading, the NPC gets killed. If the dialogue is still scheduled as a stream item we can simply remove the item from its queue. If we have started reading, the best is to let it load but ignore the callback.

Music Streaming

Streaming music is really nothing different from other types of data. When music streaming is implemented by middleware, we must take care to synchronize the different streaming systems and make sure the stream buffers for music are set up as large enough. If music is allowed to interrupt, our streaming system performance will suffer. One solution is to allow music streaming to take place when we are finished with our data, by adding a function to pause our streamer when we load music. Create a budget and decide how many data blocks we should be able to read after each music block. This kind of budget is easy to verify and serves as a guideline when you create the dimensions of the streaming buffers needed for music.

Compressed Data

Our streaming system is easily extended to support on the fly decompression of data by adding a third static buffer - a decompression buffer. As data is read into the static buffer, instead of passing it directly to the game system in a callback, it is decompressed into the decompression buffer one stream queue item a time. When the data is decompressed, we issue the callback and pass the game a pointer to the decompression buffer instead. We need to ensure an extra lock to handle decompression, and none of the stream queue items can be a larger size decompressed than the decompression buffer itself.


Just Cause

Conclusion

Using all of these methods in Just Cause, our hero Rico can do everything from walking around to flying jets through 32x32 km game environments. Everything is streamed directly from DVD on both current generation (PS2/XBOX) and next generation platforms (X360).




join | contact us | advertise | write | my profile
news | features | companies | jobs | resumes | education | product guide | projects | store



Copyright © 2006 CMP Media LLC

privacy policy
| terms of service