[SDL] Proper way to duplicate a SDL_Texture

FabioF snowdruid at gmail.com
Thu Oct 17 00:20:55 PDT 2013

On Sun, Oct 6, 2013 at 12:01 AM, David Olofson <david at olofson.net> wrote:
> On Sat, Oct 5, 2013 at 11:32 PM, Ulf Magnusson <ulfalizer at gmail.com> wrote:
> [...]
>> Neither my emulator nor Firefox when it's scrolling uses very much CPU,
>> so from that perspective it wouldn't have any trouble keeping up. I guess
>> Firefox might be drawing in some fashion that hogs the render queue
>> (or whatever the term would be) for a long time though, so that SDL has
>> to wait to do its flip. Going on vague memories here, but I think Firefox
>> renders to and draws from a buffer, while Chromium uses higher-level
>> drawing commands - or did in the past at least. Made Firefox very slow
>> over X11 forwarding.
> That might explain it... If Firefox isn't smart about what it uploads,
> the GPU is going to have to spend quite a bit of time DMAing texture
> data from those buffers.
> [...]
>> In this case Firefox makes SDL_Flip() so slow that I can't maintain
>> 60 emulated frames per second,
> This is exactly why you would add buffering in one place or another.
> Of course, this adds latency - but that's what you get unless you're
> running on a dedicated realtime system. You simply need to have enough
> buffering that you're able to meet the deadlines.

If the period of not being able to emulate at full speed lasts long enough no
amount of buffering is going to help though, since audio is consumed at a
faster rate than it is generated. There's also the problem that you wouldn't
know that you need extra buffering until it's already too late (when you're
already emulating too slowly).

> [...]
>> which will always mess up audio
>> since I'm not interpolating samples (unless I stretch/slow down
>> the audio a lot, but that sounds really bad too).
> Stretching isn't going to solve this problem; only make it worse...
> Stretching is only for when the output sample rate differs from what
> you expect, and it should only be a matter of a fraction of a sample
> per buffer normally.

Stretching would help if you e.g. generate twice as many samples
(slowing the sound down to half speed) if you're only able to
maintain 30 FPS. Sounds wonky though.

Adjusting the playback rate very slightly (hopefully inaudibly) is used
in some modern emulators to make sure you never under- or overflow
(keep the audio buffer fill level consistent). Low-level sound emulation
gets messy since you basically have a single infinite "sound effect"
playing at all times, which needs to be perfectly synchronized to video.
If you try to simply generate samples at the backend's sample rate
without doing any monitoring or adjustments, you'll eventually
under- or overflow purely due to jitter. Stuff like that is why many
emulators like to have crappy sound. :)

>> I guess I could use a separate rendering thread as well instead of
>> messing with audio buffering. Once a frame is ready, the buffer
>> could be handed off to the rendering thread. If the rendering thread
>> has not finished displaying the previous frame at that point (e.g.
>> because it's stalled in SDL_Flip()), the new frame could be dropped.
>> That would mean dropped frames while doing stuff in Firefox, which
>> is probably better than bad audio at least.
> Yes, that's one way to do it. Probably better than audio buffering, as
> it doesn't add extra latency.
>> The drawback is I might have to do manual double-buffering, since
>> the emulation step wouldn't be able to write new pixels into the buffer
>> that's being drawn.
> Well, on the upside, this would allow emulator rendering and buffer
> rendering/uploading to happen asynchronously, theoretically allowing
> you to maintain 60 fps even if those operations take close to 16.7 ms
> each. So, you could basically double your rendering throughput on a
> slow/problematic system.

Yeah, I think I'll try this approach (after upgrading to SDL 2 just in case
that helps). Would be nice if there was a non-blocking version of SDL_Flip()
that returned a status and a new buffer pointer or something, but maybe it's
a bit specific...


More information about the SDL mailing list