Sign in to follow this  
jviruss

Fast DirectX Screen Capture

Recommended Posts

Hello,I have to do a application wich take a screenshoot and send it by net with a UDP MULTICAST protocol.
The problem is that the screen shoot is too slow.I have created a texture with D3DUSAGE_RENDERTARGET flag,after i have get the surface 0 in the texture and I have putted it in the directx device as render target 0.
Anybody knows a faster method?Thanks.Perhaps is too slow why I´m using d3dxSaveTextureToFileInMemory with a JPG???

[size="2"]Thanks!!!![/size]

Share this post


Link to post
Share on other sites
Please be more precise, your app render what ? how much time does the rendering frame cost (fps) ?
Like you describe it, your application seems to do nothing apart dumping the framebuffer ?
i don't think the rendering into the rendertarget is slow, rather the JPG compression can be slow if you do it once per frame on a full framebuffer ...

If you want to know this run a basic free profiler like very sleepy, it's free and reveal you what time is spent in wich functions.

Share this post


Link to post
Share on other sites
You should be able to just grab the back buffer.

[code]
if (ui.DumpBackbuffer)
{
LPDIRECT3DSURFACE9 psurf;

// Get the present params from the swap chain
IDirect3DSurface9* pBackBuffer = NULL;
hr = pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
if( SUCCEEDED(hr) )
{

hr = D3DXSaveSurfaceToFile(thumbNail.c_str(), D3DXIFF_JPG, pBackBuffer, NULL, NULL);

SAFE_RELEASE( pBackBuffer );
}
}

[/code]

If saving to disk is too slow, you can try to save to memory first, then save the surfaces.

Share this post


Link to post
Share on other sites
It's been a while since I've done this, but IIRC the fastest way I found was to create two render targets, and change which one I'm using each frame. I'd then read from the other render-target each frame using [url="http://msdn.microsoft.com/en-us/library/bb174405(v=vs.85).aspx"]GetRenderTargetData[/url].
i.e. Frame #1 -- Render to A, Get data for B. Frame #2 -- Render to B, Get data for A.

Also, if you use the GPU to [url="http://outerra.com/video/index.html"]compress the data[/url] before downloading it to the CPU, the transfer will be much faster.

Share this post


Link to post
Share on other sites
Hodgman why is faster render on a buffer and extract info from the another buffer?????The code is secuential.You must to render first in a buffer and the "render time" is the same in A that B.You after must get data and the "get data" time is the same in A that B.Perhaps the solution is change the buffers in one thread and read in another thread???Please,Can you write me some code or explain me with more detail?

Thanks!!!

Share this post


Link to post
Share on other sites
[quote name='jviruss' timestamp='1305757891' post='4812768']
Hodgman why is faster render on a buffer and extract info from the another buffer?????The code is secuential.You must to render first in a buffer and the "render time" is the same in A that B.You after must get data and the "get data" time is the same in A that B.Perhaps the solution is change the buffers in one thread and read in another thread???Please,Can you write me some code or explain me with more detail?

Thanks!!!
[/quote]

The GPU runs in parallel with the CPU. So by putting instructions in the right order you can gain performance.Think of it as two threads but one runs on the CPU and the other on your graphics card.

Share this post


Link to post
Share on other sites
Yeah, it's a type of double-buffering, which is used a lot in threaded systems to hide latency.

When you issue a command to DirectX, this command gets put into a queue, which the GPU will execute [b]at a later point in time[/b].

e.g.
If you write 5 commands, like this:[code]Draw...//#1
Draw...//#2
Draw...//#3
Draw...//#4
GetRenderTargetData...//#5[/code]Then when the CPU reaches command #5, the GPU might only be processing command #1 still!
If this happens, it means the CPU has to sit around waiting for the GPU to catch up before it can download the render target.

If you instead try to download the render target that was used on the previous frame, there's more chance that the GPU has actually finished rendering to that target already.

e.g. In this example the CPU finishes trying to modify target 'a' at #4, but doesn't ask for the data until #10, which gives the GPU much more time to finish it's work.[code]SetRenderTarget( a )//#1
Draw...//#2
Draw...//#3
Draw...//#4
GetRenderTargetData( b )//#5

SetRenderTarget( b )//#6
Draw...//#7
Draw...//#8
Draw...//#9
GetRenderTargetData( a )//#10[/code]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this