[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Linux sound (and threads)



Jeff Read wrote:

> > So the sound in Quadra seems fine and in any case, it does work, but I
> > was still wondering after hacking that thing if that was the best way to
> > do this?
> 
> I would have to say that this is one of the best possible approaches.
> The one I used for Xhedgehog and GNUdius is probably not-as-good. It
> involves a separate daemon being spawned (xhsound) which listens on a
> pipe for incoming requests. The requests are one-byte integers
> indicating which of a predetermined set of sound effects kept in memory
> are to be played. Probably a little better but not by much than the
> other sound daemon methods you described.

This is very curious, because I also thought of that approach. That's
exactly the one used in Doom, and it does lag, but the reason it lags
might be as simple as not flushing the pipe after a write (easily
fixable) to the hard ones like the context switching required.

What I actually find curious is that when I considered this approach, it
turned out that the trouble of crossing the process boundary (this
involves managing resources in both processes, pipes, assigning IDs to
the sound effects and keeping track of them) was *more* trouble than
what was saved by having the sound server "work by itself". Calling the
process_sound() method is *really* easy to do, considering that games
normally have a few hot spots where they go really often, like frame
buffer page flipping or input polling.

Add the risks of bugs in the sound server that might have it hang and
all the error checking involved by communicating over pipes (directly
calling a method doesn't involve additionnal error checking!), and I was
pretty much convinced that it had to happen within the same process.

This leads me to another thing. Some did it with a thread, which is
about halfway between a forked sound server and doing it in-process. I
have a general rant about threads: preemptive threads in a game sucks
ass. (I told you this was general!)

The thing is preemptive schedulers have the knack of interrupting a
thread right in an heavily optimized long operation counting on things
like processor cache and pipelining. You don't want to interrupt things
like software texturing or matrix transformations, because that kind of
stuff, even when given the same amount of CPU time, perform a lot worse
when interrupted.

Also, count in additionnal time used to manage locks and mutexes for
concurrent access, this just goes thru the roof for close-to-the-metal
game programming.

In Quadra, we use matrix-based explicit dispatching between small units
of execution, a kind of dynamic state machine, which is deadly
efficient, switching "threads" at moments we precisely defined. Nothing
is concurrent, so no locks/mutexes are needed.

The problem is, this is a pain to program to. We found that cool library
that could do non-preemtive threads in Unix at
http://www.engelschall.com/sw/nps/, but it doesn't work in Windows (uses
a wizard-level hack involving signals and manipulating stack frames). A
similar library that would work on both Unix (at least Linux) and
Windows would be extremely cool. With a XFree86-style license or the
MozPL (not the GPL, as we are into *commercial* games, and even the LGPL
is a pain in the ass, it prevents statically linked binaries, for
"dubious" systems (but is mostly fine otherwise)).

-- 
Pierre Phaneuf
Ludus Design, http://ludusdesign.com/
"First they ignore you. Then they laugh at you.
Then they fight you. Then you win." -- Gandhi