d3d10 convert render to texture to image format (e.g. bmp)

Started by
4 comments, last by undead 14 years, 5 months ago
Hi all, I am trying to save each rendered frame (which is a Render to Texture) into an image format so I can do some CPU image processing. The only thing I found while googling was a d3d9 device method d3dDevice->GetRenderTargetData() which it seems you can get the rgba bits from that. I'm not sure if this is the best way but it is also d3d9 and I am looking for a solution in d3d10. Thanks for any help!
Advertisement
There's a D3DX function for saving images, don't know if RTs create problems with that function.

D3DX10SaveTextureToFile

http://msdn.microsoft.com/en-us/library/ee416738(VS.85).aspx

You might want to give it a try, but I suppose it's going to slow down your rendering process a lot!
Thanks undead!

Hmm, you were right about performance. I even tried the D3DX10SaveTextureToMemory() and the performance hit was almost just as bad. If this is the only way, then I guess it will have to do.
So it turns out this is way too slow for me. Can anyone explain why this is so slow so maybe I can figure out a way to speed it up?

I'm guessing it is so slow because copying (1024x768 pixels)(8*3 bpp) is a ton of memory to copy every frame. Also, maybe the render target resides on the video card's memory so it has to be copied to system memory too?

But how does programs like fraps still work without this bad of a performance hit? (I know fraps performance hit is bad, but it isn't as bad as what I'm getting).

Thanks :D
Firstly if speed is what you need I'd suggest doing the image processing on the GPU, they can generally do it much quicker than the CPU. What effect are you trying to achieve?

If you really need to read the data on the CPU I'd suggest alternating between two render targets. Render to one while you copy the data out of the other. That will hopefully mean the GPU isn't going to be idle so much.

You may also be able to get more performance by avoiding D3DX and doing all the steps yourself. For example if you're requesting R8G8B8 when the buffer format is X8R8G8B8 then D3DX will be doing some format conversion for you.

Other than that profile it (try both a CPU and GPU profilers) to find out where the slowness is coming from.
Quote:Original post by link3978
So it turns out this is way too slow for me. Can anyone explain why this is so slow so maybe I can figure out a way to speed it up?

I'm guessing it is so slow because copying (1024x768 pixels)(8*3 bpp) is a ton of memory to copy every frame. Also, maybe the render target resides on the video card's memory so it has to be copied to system memory too?

But how does programs like fraps still work without this bad of a performance hit? (I know fraps performance hit is bad, but it isn't as bad as what I'm getting).

Thanks :D

Fraps can't sustain more than 30fps, at least with my pc, even if the scenes are simple (running at 250/300fps without grabbing).

I suppose one of the problems of the method I suggested is the continous allocation/deallocation. If you read back the texture you can allocate space once and fill it every frame. This might help.

Another thing which could help is to save raw files, after all you have a 24/32 bit framebuffer, no need to write appropriate headers. Save raw data then convert them later with an external application.

Another bad thing is the HDD latency. I'm pretty sure fraps is faster rendering videos than single frames. They don't need to create/close many files. They have their own video codec and add it to a file... I think it's an uncompressed (or poorly compressed) one because the files it generates are HUGE.

My suggestion is the following:
- create a file ONCE (like "myvideo.rawvideo") you can include a custom header (screen res and format)
- allocate memory for the current frame only ONCE
* for each frame
- retrieve data from texture -> write to your frame in memory
- add the raw frame to "myvideo.rawvideo"
* end of frame
- deallocate memory
- close the file

Then you can write a simple program reading "myvideo.rawvideo" and exporting each frame.

For reading back texture data in D3D9 I used LockRect().
I suppose you can do something similar in D3D10 (sorry I'm not a D3D10 programming expert) with Map(). Just be sure you set the correct CPU access flags.

This topic is closed to new replies.

Advertisement