cse 380 – computer game programming render threading portal, by valve,...

25
CSE 380 – Computer Game Programming Render Threading Portal, by Valve, http://orange.half-life2.com/portal.html

Upload: christian-hensley

Post on 26-Dec-2015

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

CSE 380 – Computer Game ProgrammingRender Threading

Portal, by Valve, http://orange.half-life2.com/portal.html

Page 2: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 3: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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)

Page 4: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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…

Page 5: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 6: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 7: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 8: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 9: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 10: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 11: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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)

Page 12: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

How do we prevent race conditions?• Mutexes. What’s that?

– A mutex puts a lock on a piece of data

– 1st thread reserves a piece of data

– 2nd thread cannot use it until the 1st 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.

Page 13: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

Using Mutexes (type HANDLE)RenderList *renderList;

HANDLE renderListMutex;

// WHEN WE WANT TO USE renderList

WaitForSingleObject(renderListMutex, INFINITE);

... // USE renderList

ReleaseMutex(renderListMutex);

// NOW THE OTHER THREAD CAN USE IT

Page 14: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 15: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 16: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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).aspx

• _endthreadex– stops a thread

– http://msdn2.microsoft.com/en-us/library/hw264s73(VS.80).aspx

Page 17: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 18: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

GameRenderThread.hclass GameRenderThread

{

public:

virtual void kill()=0;

virtual void runFromMainThread(Game *game)=0;

virtual void start(Game *game)=0;

};

Page 19: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

WindowsGameRenderThread.hclass WindowsGameRenderThread : public GameRenderThread

{

private:

HANDLE renderThreadHandle;

DWORD renderThreadID;

Game *game;

bool timeToProcessData;

bool timeToRender;

HANDLE timeToProcessDataMutex;

HANDLE timeToRenderMutex;

HANDLE renderingRenderListMutex;

Page 20: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

WindowsGameRenderThread.cppWindowsGameRenderThread::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");

}

Page 21: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

WindowsGameRenderThread.cppvoid 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);

}

Page 22: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 23: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

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

Page 24: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

ReleaseMutex(thread->getRenderingRenderListMutex());

WaitForSingleObject(thread->getTimeToProcessDataMutex(), INFINITE);

thread->setTimeToProcessData(true);

ReleaseMutex(thread->getTimeToProcessDataMutex());

}

else

{

ReleaseMutex(thread->getTimeToRenderMutex());

}

}

_endthreadex( 0 );

return (26);

}

Render Thread

Page 25: CSE 380 – Computer Game Programming Render Threading Portal, by Valve, //orange.half-life2.com/portal.html

References• Coding For Multiple Cores on Xbox 360 and Microsoft Windows

– http://msdn2.microsoft.com/en-us/library/bb204834(VS.85).aspx