After quickly looking over that(sfifo) code, it appears that you’re
expecting certain C operations to be atomic. Is that a wise
decision? Would it work at all on RISC architectures? Would the
compiler’s optimizer produce assembly that you didn’t want? That
code doesn’t seem to be very thread-safe to me, but am I missing
something?
The only requirements are that reading and writing sfifo_atomic_t is
atomic, and that operations are done very roughly in the right order.
RISC/CISC is not an issue, as all operations but the actual reads and
writes to those variables are irrelevant. As to order, that’s just a
matter of bumping the read/write indices after reading/writing the
data in the buffer, so you keep the “other end” away from the part of
the buffer you’re messing with. Both sides read both indices, but the
writer only changes the write index, and the reader only changes the
read index.
The only environment I’m expecting problems with is SPARC SMP systems.
AFAIK, those have a maximum atomic transfer size (between CPUs) of 24
bits, which means that my “volatile int” typedef won’t work.
Actually, the problem is one of alignment rather than the actual size
of the index variables (only the low N bits are used, where N depends
on the FIFO buffer size), so it might actually work anyway, but I
wouldn’t bet on it…
A compiler that thinks int is 64 bits would create a similar
situation; indices may not be atomic (N bit CPU bus != N bit atomic
size on SMP systems), but only the 31 low bits are actually used, so
with normal alignment, it should work anyway.
Anyway, here’s a list of compiler / OS / architecture combos sfifo is
known to work on:
gcc / Linux / x86: Works
gcc / Linux / x86 kernel: Works
gcc / FreeBSD / x86: Works
gcc / NetBSD / x86: Works
gcc / OpenBSD / x86: Works
gcc / OpenBSD / PPC: Works
gcc / OpenBSD / SPARC: Works
gcc / OpenBSD / SPARC64: Works
gcc / Solaris / x86: Works
gcc / Solaris / SPARC: Works
gcc / Mac OS X / PPC: Works
gcc / BeOS / x86: Works
gcc / BeOS / PPC: Works
gcc / AmigaOS / 68k: Works
gcc / AmigaOS / PPC: Works
gcc / Win32 / x86: Works
gcc / Linux / PlayStation 2: Works
Borland C++ / DOS / x86RM: Works
Unfortunately, I don’t have any reliable info on SMP systems. Anyone
who got Kobo Deluxe to work properly with sound effects on SMP
systems, please report!
My emulator can’t have the sound emulation code run in the sound
callback function, as the sound emulation is synchronized and tied
into the cpu emulation, and the cpu can read from various registers
to get the state of the sound channels.
Yeah, that’s the usual situation with emulators, apparently…
Having the main thread block on sound writes does create noticeable
screen tearing(less noticeable if you use a high refresh rate, but
that’s not very feasible on LCD monitors). I have thought about
dynamically adjusting the output rate of the emulator(and not the
actual sound device) to synchronize the sound updates and video
updates, but that would cause a little sound distortion(such as a
4000hz square wave being output as a 3993hz square wave).
And more seriously, that kind of sync is very hard to get right unless
you have a real time OS. If you measure “current time” in the audio
callback and in the main emulator loop, or something like that,
you’ll have to do some substantial filtering to extract useful data.
Way too much scheduling jitter to do anything with the raw data.
The real
NES has a frame rate of about 60.1 fps. A refresh rate of “60” hz
is probably close enough to not cause noticeable sound problems,
but what about 70hz, or 72hz?
Not close enough… And then there are the occasional dropped frames.
If you “hard sync” audio to video, a dropped video frame causes an
audio glitch. (Audio glitches are much more annoying than occasional
dropped video frames…)
Unless I do some sort of blurring,
I’d expect the video updates to appear choppy.
I don’t think there’s any reasonably simple filtering that can solve
that. You can cross fade or something, but I doubt that will do much
good on this kind of video. (Sort of works if there’s motion blur, I
think, but it’s still far from perfect.) The proper solution would be
to interpolate the scroll and sprite positions, but that might cause
weird effects with some games…
And this is
assuming I could even get double buffering to work right under X
with OpenGL. My Geforce2 card does double buffering when I set
that environment variable, but it seems to consistently perform the
flips in the middle of the screen in my code, and not in vblank.
Probably a bug in my code…
I doubt it’s your code. (OpenGL doesn’t give you that kind of control,
AFAIK.) Retrace sync causing tearing seems to be “normal” for current
Linux drivers. The problem is that nearly all drivers do "fake"
double buffering (back->front blits instead of h/w page flipping),
which means that you get tearing if the “flip” isn’t started at the
exact right moment.
//David Olofson - Programmer, Composer, Open Source Advocate
.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`-----------------------------------> http://audiality.org -’
— http://olofson.net — http://www.reologica.se —On Saturday 16 August 2003 19.13, xodnizel wrote: