Skip to main content
gamedev.net
🔒 Locked

fast screen capture/LockRect performance problem

Started by JoelBenM Feb 24, 2008 at 10:01 PM 2 replies 3.2k views
Original Post
JoelBenM
JoelBenM
Hi everyone, My game capture app needs to copy screen data to memory. after hooking and rerouting the Present function into my function, I GetBackBuffer, then CreateOffscreenPlainSurface (with D3DPOOL_SYSTEMMEM), then GetRenderTargetData from the backbuffer into the offscreen surface, and then - alas - LockRect the surface and memcpy the bits. Everything takes really fast, except one thing: the LockRect. it takes around 50ms, on some games. since I'm stalling the Present, the frame rate drops I tried using all the flags in LockRect (including D3DLOCK_DONOTWAIT!) but to no avail. I understood (thanks MS MVP Richard!) GetRenderTargetData queues a request for the data, and LockRect flushes it, so it take a long time I wondered if you have any ideas to speed it up/circumvent this. * What do you think about maybe GetRenderData to buffer N, but LockRect-ing buffer N-1? * What about a callback that I can receive, or poll somewhere, to know when LockRect finishes? * Last, what do you think about capturing the front buffer from another thread altogether? that should not harm the game frame rate? any other tricks to capture the screen fast? thanks very much for _any_ thought, J
jollyjeffers
jollyjeffers
Quote:
Original post by JoelBenM
* What do you think about maybe GetRenderData to buffer N, but LockRect-ing buffer N-1?
A 'bounded buffer' approach can help hide the latency so definitely give it a go.

Quote:
Original post by JoelBenM
* What about a callback that I can receive, or poll somewhere, to know when
LockRect finishes?
No, there isn't an asynchronous form of this operation.

Quote:
Original post by JoelBenM
* Last, what do you think about capturing the front buffer from another thread altogether? that should not harm the game frame rate?
No, this is highly unlikely to do anything other than hurt you. Multi-threaded device access is a no-no. By all means use your ring-buffer approach to grab a block of data and then hand it off to a worker thread, but keep all D3D API calls in one single thread.

Quote:
Original post by JoelBenM
any other tricks to capture the screen fast?
You mention you're creating a new surface each time. Don't. Resource modification & creation is typically an expensive operation, so re-use surfaces wherever possible

hth
Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
JoelBenM
JoelBenM
Jack, thanks a lot.

what do you think about capturing the front buffer from a different _process_ altogether? i tried that with http://www.codeproject.com/KB/dialog/screencap.aspx and it seems to work at 10fps, although sometimes I see garbage captured (perhaps I could wait for a vblank?). Also, people in many forums write that GetFrontBufferData can take up to a second, which doesn't seem to be the case on my machine.

I wonder what do you think about this approach?

thanks again
J
iSonic
iSonic
You should not use GetFrontBuffer. This is very slow. Better option would be to use GetBackBuffer and do this before you call the original Present().

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.