posts - 34,  comments - 14,  trackbacks - 0
Thread 1:

I recorded the time it takes to call the Present method of the Direct3D device I'm using. It takes 15 - 16 ms. Doesn't this method just flip the backbuffer to the front? Why does it take so long?


Answer 1.1 ( selected ):

Present is a blocking call, and may take quite a while to finish, even when VSync is off.

During regular DX calls, the GPU and CPU are not sync'd. The CPU can issue commands to the GPU before it finishes the previous calls, by pushing them in to a command queue. The GPU then just processes commands in the queue at it's own time.

When you call Present, DX syncs between the CPU and GPU, to make sure the two don't drift apart too far. If the GPU has a lot more work to do than the CPU has, the CPU will be waiting for the GPU to finish before Present returns.

If you'd like, you can call Present with the D3DPRESENT_DONOTWAIT flag (I think it actually goes in the PresentParameters when you set up the device). With that flag set, Present returns immediately. Instead of waiting for the GPU to finish, Present returns a D3DERR_WASSTILLDRAWINGerror, to indicate the GPU hasn't finished it's work yet. This allows you to use these extra cycles for non-critical tasks.
while (Device->Present(0, 0, 0, 0) == D3DERR_WASSTILLDRAWING)

Hope this helps.

Answer 1.2 ( selected ):
Original post by devronious
while (Device->Present(0, 0, 0, 0) == D3DERR_WASSTILLDRAWING)

How can this work if present returns void? Also, I only show up to 3 params for that method.
You need to go via a proper swap-chain interface to get the Present() function in the form sirob posted it. The default/implicit chain controlled via the device doesn't expose it.

I don't have my docs to hand, but I'm pretty sure you can extract an IDirect3DSwapChain9 interface from the device and work from there...

btw, be very careful how you're profiling your application - there are a lot of ways to generate completely bogus results


Thread 2:
I'm using DirectX9

In a rendering loop, I believe there must be a blocking function call (Present(), EndScene() or BeginScene() ???)
in order for the CPU to wait for the GPU to finish drawing its frame.

I then wondered how could I achieve maximum parrallelism/concurrency betwwen CPU & GPU.

Intuitively (if we admit that present() is the "blocking" function) my loop would look like this

. (all kinds of drawing functions)

//While the graphic card/driver is executing all drawing commands, do some CPU intensive tasks


Present() //Stall the CPU while the GPU has finished drawing (if not yet)

Am I wrong ? right ? and which is the "blocking function" if one exists ?

Answer 2.1 ( selected ):
I believe there are two blocking factors. One is that the driver isn't supposed to queue more than 3 frames at a time. Present will block under these circumstances (unless you present on the swap chain itself, in which case you have the opportunity to D3DPRESENT_DONOTWAIT and the call will return immediately with D3DERR_WASSTILLDRAWING).

The other is that you can't render to a back buffer that's queued for display. So in some circumstances DrawPrimitive will block.

And I seem to recall that D3DSWAPEFFECT_COPY will block on Present until the back buffer has been blitted. But I haven't gotten around to testing all this, so don't hold me to it. Grain of salt and all that...
posted on 2008-03-18 23:42 Konami wiki 阅读(456) 评论(0)  编辑 收藏 引用