Download presentation
Presentation is loading. Please wait.
Published byChristian Hensley Modified over 9 years ago
1
CSE 380 – Computer Game Programming Render Threading Portal, by Valve, http://orange.half-life2.com/portal.htmlhttp://orange.half-life2.com/portal.html
2
What is multi-tasking? Doing many things simultaneously On a computer, Operating Systems run multiple programs simultaneously When you’re working, how many different applications do you have open at one time? Games use threads to do multiple things simultaneously –Why? better utilization better framerates/performance
3
Threads Individual programs appear to do multitasking Each task is called a thread Programs that can run more than one thread at once are called multithreaded –a program is broken up into a number of threads of control –all threads share the same address space (data). –threads communicate with each other via the shared objects –operations in threads are scheduled by a thread scheduler (typically OS)
4
Why do we get a performance advantage? Imagine you wanted to make a CAR Approach 1: –Step 1: make 4 tires –Step2: when done with Step 1, Make a windshield –… –Step 1,000,000,000: Assemble Car 1. Make 4 Tires 2. Make a windshield 1,000,000,000. Assemble Car …
5
Why do we get a performance advantage? Imagine you wanted to make a CAR Approach 2: –Step 1: Simultaneously have different workers/suppliers make the windshield, engine, tires, etc. –Step 2: Assemble car as parts are available 1a. Make 4 Tires 1b. Make a windshield 2. Assemble Car …
6
How do you check for broken eggs? You buy a carton of eggs You don’t want any broken Option 1: –Take out and check them one at a time –Poor utilization. Why? because 11 eggs are idle while we check one of them Option 2: –Open carton and look at top –Flip carton upside down –Open carton and look at bottom –High utilization. Why? eggs are never waiting for other eggs that have been removed and are being examined
7
Utilization You don’t want your program to be idle when there’s work to be done. Like: –while our game loop is sleeping –while we’re retrieving user input –while expensive rendering is going on For multi-core: –while one core is doing something the others shouldn’t be idle
8
Typical Thread Tasks Rendering –separate thread only performs rendering –expensive operation Networking and I/O –threads may wait for messages –they check buffer continuously for immediate response Physics –do pathfinding on one CPU and physics on another
9
Using a Render Thread One approach: –Thread 1: all game updates (AI, Collisions, etc.) –Thread 2: all rendering, and only rendering Strategy: –Each frame: Thread 1 builds a RenderList Simultaneously Thread 2 renders the RenderList Thread 1 had built the previous frame –Note: this means we’ll need 2 RenderLists
10
2 RenderLists RenderList *renderList1, *renderList2; Each frame: Thread 1 If time to process data: Set time to process data to false Process data and build render list 1 Swap render lists 1 and 2 Set time to render to true Thread 2 If time to render: Set time to render to false Render render list 2 Set time to process data to true
11
Race Conditions Threads are independent pieces of control operating on shared data. If we’re not careful: –thread 2 could overwrite thread 1’s changes data corruption –thread 2 could try to use thread 1’s changes prematurely –or vice versa One thread corrupting shared data for the other threads is called a race condition Common to Consumer – Producer relationships –one thread is the producer (thread 1) –one thread is the consumer (thread 2)
12
How do we prevent race conditions? Mutexes. What’s that? –A mutex puts a lock on a piece of data –1 st thread reserves a piece of data –2 nd thread cannot use it until the 1 st thread is done with it Windows Mutexes: –WaitForSingleObject – requests a reservation http://msdn2.microsoft.com/en-us/library/ms687032(VS.85).aspx –ReleaseMutex – releases a reservation http://msdn2.microsoft.com/en-us/library/ms685066(VS.85).aspx What should we be locking? –anything used by both threads RenderLists, TextureManagers, text to render, etc.
13
Using Mutexes (type HANDLE) RenderList*renderList; HANDLErenderListMutex; … // WHEN WE WANT TO USE renderList WaitForSingleObject(renderListMutex, INFINITE);...// USE renderList ReleaseMutex(renderListMutex); // NOW THE OTHER THREAD CAN USE IT
14
Complication: Deadlock What’s that? –Thread 1 has a lock on object A –Thread 1 is waiting for object B –Thread 2 has a lock on object B –Thread 2 is waiting for object A Can bring a program to a halt How do we resolve it? –prevent it from happening through a well thought-out mutex/lock strategy
15
Platform dependency & threads One drawback of threads Thread libraries are typically system dependent For example: –C++’s CreateThread function creates threads C/C++ runtime (CRT) will not get properly initialized on Windows
16
Windows Thread Management _beginthreadex –starts a thread –you provide the method to run in that thread unsigned __stdcall MyMethod ( void* pArguments ) typically would have a loop tied to game loop timing –http://msdn2.microsoft.com/en-us/library/kdzttdcb(VS.80).aspxhttp://msdn2.microsoft.com/en-us/library/kdzttdcb(VS.80).aspx _endthreadex –stops a thread –http://msdn2.microsoft.com/en-us/library/hw264s73(VS.80).aspxhttp://msdn2.microsoft.com/en-us/library/hw264s73(VS.80).aspx
17
So we’ll need a Windows Thread class GameRenderThread – could be a virtual class with just method headers WindowsGameRenderThread – could be a Windows implementation of GameRenderThread
18
GameRenderThread.h class GameRenderThread { public: virtual void kill()=0; virtual void runFromMainThread(Game *game)=0; virtual void start(Game *game)=0; };
19
WindowsGameRenderThread.h class WindowsGameRenderThread : public GameRenderThread { private: HANDLE renderThreadHandle; DWORD renderThreadID; Game *game; bool timeToProcessData; bool timeToRender; HANDLE timeToProcessDataMutex; HANDLE timeToRenderMutex; HANDLE renderingRenderListMutex; …
20
WindowsGameRenderThread.cpp WindowsGameRenderThread::WindowsGameRenderThread() { renderThreadHandle = NULL; timeToProcessData = true; timeToRender = false; timeToProcessDataMutex = CreateMutex(0, NULL, L"timeToProcessDataMutex"); timeToRenderMutex = CreateMutex(0, NULL, L"timeToRenderMutex"); renderingRenderListMutex = CreateMutex(0, NULL, L"renderingRenderListMutex"); }
21
WindowsGameRenderThread.cpp void WindowsGameRenderThread::start(Game *game) { // START THE RENDER THREAD HANDLE renderThreadHandle; unsigned int renderThreadID; renderThreadHandle = (HANDLE)_beginthreadex( NULL, 0, &RenderThread, game, 0, &renderThreadID ); setRenderThreadHandle(renderThreadHandle); setRenderThreadID(renderThreadID); }
22
void WindowsGameRenderThread::runFromMainThread(Game *game) { WaitForSingleObject(timeToProcessDataMutex, INFINITE); if (timeToProcessData) { timeToProcessData = false; game->processGameData(); ReleaseMutex(timeToProcessDataMutex); // NOW LET'S SWAP THE RENDER LISTS WaitForSingleObject(renderingRenderListMutex, INFINITE); GameGraphics *graphics = game->getGraphics(); graphics->swapRenderLists(); ReleaseMutex(renderingRenderListMutex); WaitForSingleObject(timeToRenderMutex, INFINITE); timeToRender = true; ReleaseMutex(timeToRenderMutex); } else ReleaseMutex(timeToProcessDataMutex); } Called each frame by main thread
23
unsigned __stdcall RenderThread( void* pArguments ) { Game *game = (Game*)pArguments; GameGraphics *graphics = game->getGraphics(); WindowsGameRenderThread *thread = (WindowsGameRenderThread*)game->getRenderThread(); while (game->isGameActive()) { WaitForSingleObject(thread->getTimeToRenderMutex(), INFINITE); if (thread->isTimeToRender()) { thread->setTimeToRender(false); ReleaseMutex(thread->getTimeToRenderMutex()); WaitForSingleObject(thread->getRenderingRenderListMutex(), INFINITE); int gameMode = game->getGameMode(); if ((gameMode != LEVEL_LOADING_GAME_MODE) && (gameMode != LEVEL_UNLOADING_GAME_MODE)) graphics->renderGameInRenderThread(game); Render Thread
24
ReleaseMutex(thread->getRenderingRenderListMutex()); WaitForSingleObject(thread->getTimeToProcessDataMutex(), INFINITE); thread->setTimeToProcessData(true); ReleaseMutex(thread->getTimeToProcessDataMutex()); } else { ReleaseMutex(thread->getTimeToRenderMutex()); } _endthreadex( 0 ); return (26); } Render Thread
25
References Coding For Multiple Cores on Xbox 360 and Microsoft Windows –http://msdn2.microsoft.com/en-us/library/bb204834(VS.85).aspxhttp://msdn2.microsoft.com/en-us/library/bb204834(VS.85).aspx
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.