DirectDraw Flip() woes

Started by
14 comments, last by Nostalgia 20 years ago
Rock,

Your guess was right on the money. It's not the Flip() that's taking forever, it's the Blt() immediately before it that's blocking. The Flip() takes .03ms to execute. The Blt() takes up to 15ms! I'm a little curious about this. Check out my logic below to see why (along with timings):

1. Process engine until it's time to draw a frame (1-3ms)
2. backbuffer->Blt(colorfill); (.03ms)
3. offscreen_surface->Lock(); (.003ms)
4. Copy this frame's bitmap into offscreen_surface pointer. (.08ms)
5. offscreen_surface->Unlock(); (.003ms)
6. backbuffer->Blt(offscreen_surface); (15.4ms)
7. primarysurface->Flip(); (.03ms)
8. Goto step 1

1/60 second = 16.67ms.

So, if the problem is that the Blt() is waiting for the backbuffer to be drawn at vsync, why doesn't the Blt() in step 2 take forever? All Blt()s are being called with DDBLT_ASYNC and DDBLT_DONOTWAIT. No function call fails. The size of the surface being Blitted is 318x192.

Incidentally, if I replace the Flip() with a Blt(), the Blt() in step 6 takes about 2ms. Still a lot longer than it should.

This is getting intersting. Any other suggestions?

-Joe

...edit to add engine processing time

[edited by - Nostalgia on March 26, 2004 8:05:34 PM]

[edited by - Nostalgia on March 26, 2004 8:06:47 PM]
Nostalgia, an Intellivision Emulatorhttp://www.gotmaille.com/nostalgia/
Advertisement
Let me guess, your offscreen surface is in system memory?
Have you considered multithreading?
It is odd that its waiting if you pass in the don''t wait flag. I''d try to use neither wait flag and see what happens, just to see (I never understood why they added the don''t wait flag, since it wasn''t in DX5 and wasn''t needed). The first call could be OK if its just queueing the instruction. It probably is, especially since its just a color fill.

Maybe try using BltFast if you don''t need Blt functionality, see if it blocks or not. And as mentioned, if you are copying from system surface to the back buffer, it could take a long time. I''ve lost track of what type of numbers to expect, but 2 ms seems pretty good, depending on resolution and color depth.

But I think you can see that your program is probably waiting right where you''d want it to. Its got the next frame already to go, and it just needs to get the go-ahead to draw it.
The offscreen surface *was* being created in System memory. Thanks for catching that. I was debugging something a loooong time ago, and guess I forgot to change it back :/

So, that changes my timings to:

07:52:33 -> Engine : 00.785ms
07:52:33 -> Blt() colorfill: 00.011ms
07:52:33 -> Lock() : 14.652ms
07:52:33 -> Buffer Copy : 01.021ms
07:52:33 -> Unlock() : 00.014ms
07:52:33 -> Blt() screen : 00.025ms
07:52:33 -> Flip() : 00.013ms

So now it's the Lock() on the offscreen buffer that's blocking. I'm using the DDLOCK_DONOTWAIT | DDLOCK_NOSYSLOCK flags.

I've tried multithreading before, and it didn't buy me much. Although I didn't know as much about the problem as I do now. If I have the time, I'll try it again. It'll require a bit of re-architation. Is that a word?

-Joe

[edited by - Nostalgia on March 29, 2004 7:59:20 AM]
Nostalgia, an Intellivision Emulatorhttp://www.gotmaille.com/nostalgia/
Interesting postscript. I just tried the code on a different machine. This one is Win2k instead of XP. On this machine, the colorfill Blt() at the beginning of my display routine DOES fail when the surface is busy. You can see here that it dropped 3 frames while waiting for the surface:

11:10:35 -> Engine : 01.187ms
11:10:35 -> Blt failed (Backbuffer colorfill) : DDERR_WASSTILLDRAWING
11:10:35 -> Engine : 01.172ms
11:10:35 -> Blt failed (Backbuffer colorfill) : DDERR_WASSTILLDRAWING
11:10:35 -> Engine : 01.347ms
11:10:35 -> Blt failed (Backbuffer colorfill) : DDERR_WASSTILLDRAWING
11:10:35 -> Engine : 85.742ms
11:10:35 -> Blt() colorfill: 00.031ms
11:10:35 -> Lock() : 00.006ms
11:10:35 -> Buffer Copy : 00.114ms
11:10:35 -> Unlock() : 00.003ms
11:10:35 -> Blt() screen : 02.378ms
11:10:35 -> Flip() : 00.016ms

The reason the Engine took 85 ms is that skipping the frames allowed the emulator to get too far ahead of the sound and needed to be throttled.

So I wonder if the video card on my other machine is just quirky.

-Joe
Nostalgia, an Intellivision Emulatorhttp://www.gotmaille.com/nostalgia/

This topic is closed to new replies.

Advertisement