Skip to main content
gamedev.net
🔒 Locked

Multithreaded Game

Started by Zipster Oct 24, 2000 at 11:50 PM 17 replies 750+ views
Original Post
Zipster
Zipster
I had an idea. What if you were to put tasks such as rendering and input in their own threads? That way, you could recieve input where the main loop happens to be. Remember how sometimes when you''re playing a game, you press a key, but the game totally misses it? Wouldn''t multithreading solve that problem? WHICH then leads me to some questions: 1) When the main thread recieves a message, does it automatically send it to all the other threads of the proccess, and vice versa? 2) Even if i were to have a seperatie thread for input and rendering, wouldn''t it be useless anyway (just got these thoughts)? I mean, you''d have to mutex the input thread so it doesn''t switch to the rendering thread before input is complete (since what is rendered is determined by input), and youd have to mutex the rendering thread so that drawing is done before it switches to the input thread! So what are the advantages? Or should only input have a seperate thread? Or rendering? As you can see, I have many little questions regarding how it would work together overall, and how i would set this up to get it to work with the advantages i stated earlier.
Etnu
Etnu
Definately for sound, but I think it would be kind of difficult to pull off proper input and graphics if they are running on seperate threads like that.

You could probably stick some graphics stuff in another thread, but only if it is stuff that doesn''t rely on user movement.

many games essentially have all actors running on a seperate "thread", although their implementations are quite a bit different than say a windows thready.
---------------------------Hello, and Welcome to some arbitrary temporal location in the space-time continuum.
Sly
Sly
Most commercially released games do not use multithreading. Age Of Empires 2 for example. It''s single-threaded. Quake 3 only added multi-threading to cater for SMP (symmetric multi-processing) systems.

The only place I have seen multi-threading warranted is when implementing multiplayer. Reading the network packets is time-critical, so having a simple thread just doing this task is a good thing.



Steve 'Sly' Williams
Tools Developer
Krome Studios
Etnu
Etnu
If you read the UnrealEd docs, it basically explains how each actor runs on its own "thread".

Now this isn''t truly a "thread" as in a windows thread, but rather the classes are very well seperated so as to effectively be independent of one another.

Playing with the UnrealEd Scripts, I have to say I really like the way they laid the whole thing out. (Not like I am one to be a critic though )
---------------------------Hello, and Welcome to some arbitrary temporal location in the space-time continuum.
Shannon Barber
Shannon Barber
High perforamce graphics packages use multiple threads so that mulitple processors can be utilized.

My game currently uses 4 threads, one for window messages and OnIdle rendering, another for a client socket, a third for a server socket, and a fourth for input.

The graphics thread only reads the position data, and the input thread reads & writes, so it could work without any sycronization at all and be thread safe (though not multi-processor safe). At worst, a frame would disjointly display a single object... lock & unlock your geometry if its a big concern...

Winodws blows a lot of processing power during thread-thrashing. But at any given time there are twenty or more processes running plus some more threads for each of them... so if you have 6 thread dedicated to your game, you get a bigger slice of the pie than if you only had one (well not really, but it sounds good )

And no, when a thread receives a message it definetly does not send it to any other thread - unless you specifically code it too! How would it know when to stop? Thread1->msg->Thread2->msg->Thread1.... 100% cpu utilization & grid lock (not quite dead lock though)

Threads share memory, so they can "communicate" via global memory and/or messages. So for the input, you would create an input thread, initialize dInput, make a threadproc that just polls the keyboard once every 10ms and stores it in a buffer until the render loop ask for it (then it clears the buffer). Thread should be bumped up to real time priority so that it always gets called every 10ms (well as close to every 10ms as windows will let it anyway...)
You just need to use some thread safe code in the input routine.
Don''t screw-up a real time thread, and make it spin in a tight loop! If you do, you''ll be a hittin'' the reset button
    
BYTE* lpKbState = new BYTE[256];
lpDIKb->GetDeviceState(sizeof(BYTE[256]),(LPVOID)lpKbState);

//switch-a-rooski to prevent another thread from dereferencing a bad pointer <img src="smile.gif" width=15 height=15 align=middle>

BYTE* lpTemp;
lpTemp = m_lpKbState;
m_lpKbState = lpKbState; //one atomic mov, cannot be task switched during this line
delete lpTemp; //safe to delete now

//you make two BYTE[256] pointers and just flip as well, which is a much better method, cause this will fragment memory...


The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Korndog
Korndog
Yeah, I''ve done this with before and have continued to do this is many projects I''ve done before...

What I do is keep the render code in one thread and all other game stuff in another thread, and it works quite well because the render thread only reads the values.

I''ve been wondering if anyone else has done this too...

Korndog

"Look for the new ANB engine!"
Ziggy5000
Ziggy5000
I use a seperate thread to:
render 2d special effects- (since they are actually a low priority, think about it-)
handle http requests sync. (using wininet)
handle basic logic- move sprites, play sounds etc.

I don''t see any speed loss from multithreading- and it makes the code simpler. I did have a problem within Win2k though- it seems real sensitive to the thread priority level when 98 is not...

One trick to send info/flags between threads is to use 32-bit dwords- since a single processor system cannot create an exception because only a single ASM command in needed to change there state. (Hope this isn''t too confusing...)





ill-lusion.com

ziggy@ill-lusion.com
laxdigital.com
[email=ziggy@laxdigital.com]ziggy@laxdigital.com[/email]
AticAtac
AticAtac
One job for multithreading is mouse-handling.
If you want a good interface-response in your game you should separate mouse from main rendering loop. If fps drops you can still interact with the gameinterface in a fast way.
You can notice this if you have ever played games which dont support this, the mouse-movement is so slugish.
One of the most important part of game is the interface-response and if its slow then imo the game will suck , even it has nice gfx etc.
You still have to sync your mouse-drawing routines with the main rendering loop but its it worth.
Orpheum
Orpheum
I asked my friend who is a professional developer about this, as I was interrested in implementing threading in my game. He told me that the additional overhead of threading \0ified any benefit of using threads.
There is no spoon.
Zipster
Zipster
Alright, thank you for all the replies.

The question then becomes how to send messages to a specific thread without using global variables.
lohab
lohab
That''s the tricky part of multi-threaded processes.

The best method would be to use events to signal other processes to wake up. For example, you''d receive a message with one thread, enter a CRITICAL SECTION, set a flag that alarms the main thread of the message and copies all necessary data... (NOTE the copy, its never a good idea to use the same memory over 2 different processes. Often leads to horrible memory bugs... they can happen and your program might continue for another 5 minutes before crashing... Unless you enter a critical section every time.)
The critical sections are nice, but don''t go crazy, because they lead to another problem.... deadlock... where one thread is waiting on a critical section that it can never get. This is a huge topic... and hard to cover here.

So my advice... start a worker thread, it will wait on an event to be activated. When that happens, use a semaphore (or lock) to protect a local data member, enter the critical section, modify that data... Leave the critical section by releasing the semaphore or lock... and loop back around to wait on the event...
You can create these variables as object members (so they aren''t global, and pass them as parameters) When you initialize your game.

Hope that makes sense, its a difficult topic and hard to explain in a short email.

Lawrence Ohab
Zipster
Zipster
Thank you, I''ve read up on Mutexes.
Shannon Barber
Shannon Barber
In the Win32 environment, you lose nothing by using threads (unless you use them very poorly).

It''s already swapping between 30-40 threads, what''s another 3-8?


...
And the mouse comes back on an interaupt, it should be possible to update the cursor position damn quick. Or do you have to poll it like the keyboard?

Sometime you *must* use threads. For instance, if you were recording a live audio stream; you need work thread dedicated to the events; otherwise when the user moves the window around or clicks a menu and fuddles around - you''ll get a buffer underrun.
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Zipster
Zipster
Another example is when you use windows progress bars.
gmcbay
gmcbay
Threading is good.

In my experience using multithreading, the overhead of using them on single CPU systems (in terms of increased memory usage and thread switching time) is negligible.

And the gains when the program is run on a multiple CPU system (with an OS that can really support it, like Win2k or Linux) can be quite high, if you multithread wisely.
revolver
revolver
Well, on single processor systems, multithreading doesn't really do anything special. In such an environment, processing updates to your game objects in an incremental manner would really be the same as an OS "updating" threads with time-slices.

In dual (or more) processor systems, things get interesting, but you really have new issues to deal with, like syncronization/data access/blahblah. It is NOT easy to design parallel/superscalar applications... but that I suppose that complexity scales linearly program complexity.

Having an isolating a rendering thread might be an interesting way to stabilize rendering FPS when other game code is running slow though...

Edited by - revolver on October 28, 2000 5:00:38 AM
Creativity is a bloody nuisance and an evil curse that will see to it that you die from stress and alcohol abuse at a very early age, that you piss off all your friends, break appointments, show up late, and have this strange bohemian urge (you know that decadent laid-back pimp-style way of life). The truly creative people I know all live lousy lives, never have time to see you, don't take care of themselves properly, have weird tastes in women and behave badly. They don't wash and they eat
Etnu
Etnu
Another use for threads is for streaming in new areas as you approach them (similiar to streaming music data).

And yeah I usually use Dinput with the mouse on a seperate thread.
(not the keyboard though, I handle that usually via a 256 byte array for storing what keys are currently up and what are currently down).
---------------------------Hello, and Welcome to some arbitrary temporal location in the space-time continuum.
WMiller
WMiller
I designed a WinThread class in C++ (for Win9x/NT) that works just like the Thread class in Java. I''d appreciate it if you guys could download the source code, test it, and try to break it.

I included a sample test program you can use to see how it works if you are unfamiliar with Java threads.

www.eecs.ukans.edu\~millew

millew@eecs.ukans.edu

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.