Sign in to follow this  
ext

Copy a rendertarget texture into a regular texture

Recommended Posts

Hello, is it possible to copy the data in a texture which was created with the flag D3DUSAGE_RENDERTARGET (and the associated D3DPOOL_DEFAULT) into a regular texture with the pool D3DPOOL_MANAGED? It seems, that the IDirect3DDevice9::GetRenderTargetData can do this, but this call fails always with the INVALIDCALL-error.

Share this post


Link to post
Share on other sites
It's possible, but you'd need to go via a temporary surface in system memory and your source must be in the default pool:

CreateOffscreenPlainSurface() to create a temporary surface,
GetRenderTargetData() on the source to the temporary surface,
LockRect() on the destination,
memcpy() from the tempporary surface to the destination
UnlockRect() on the destination

It would be much more convenient to GetRenderTargetData() straight from the RT to the texture, but MSDN says that's against the rules:

Quote:
Original text from MSDN
IDirect3DDevice9::GetRenderTargetData Method
...
Remarks

The destination surface must be either an off-screen plain surface or a level of a texture (mipmap or cube texture) created with D3DPOOL_SYSTEMMEM.

The source surface must be a regular render target or a level of a render-target texture (mipmap or cube texture) created with POOL_DEFAULT.

This method will fail if:

* The render target is multisampled.
* The source render target is a different size than the destination surface.
* The source render target and destination surface formats do not match.


Regards
Admiral

Share this post


Link to post
Share on other sites
When calling GetRenderTargetData I get always an D3DERR_INVALIDCALL error. I cannot find in the directx documentation a note that this function is _not_ supported by all graphics card.

My code:

IDirect3DTexture9* img = NULL;
d3dDevice->CreateTexture( 256, 256, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &img, NULL );
IDirect3DSurface9* sf = NULL;
d3dDevice->CreateOffscreenPlainSurface( 256, 256, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &sf, NULL );
IDirect3DSurface9* src = NULL;
img->GetSurfaceLevel( 0, &src );
d3dDevice->GetRenderTargetData( src, sf );



According to the directx documentation

Quote:

This method will fail if:

The render target is multisampled.
The source render target is a different size than the destination surface.
The source render target and destination surface formats do not match.



But my render target is not multisampled, it has the same format and they're the same size (I compared the values in their D3DSURFACE_DESC structures and they have the same format and same sizes and the multisampletype of the source surface is D3DMULTISAMPLE_NONE).

Share this post


Link to post
Share on other sites
The directx documentation of CreateOffscreenPlainSurface confused me with their remark:

Quote:

D3DPOOL_SCRATCH will return a surface that has identical characteristics to a surface created by the DirectX 8.x method CreateImageSurface.

D3DPOOL_DEFAULT is the appropriate pool for use with the StretchRect and ColorFill.

D3DPOOL_MANAGED is not allowed when creating an offscreen plain surface. For more information about memory pools, see D3DPOOL.

Off-screen plain surfaces are always lockable, regardless of their pool types.


That's why I thought by using off-screen surfaces it doesn't matter when using the default pool.
But you're right that was the problem. Thank you very much :-)

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