Saving Depth/Stencil buffer to file

Started by
4 comments, last by Evil Steve 18 years, 7 months ago
Hey all, I'm having a spot of trouble saving my Depth/Stencil buffer to a file.

HRESULT hr;
IDirect3DSurface9* pTemp;
IDirect3DSurface9* pTemp2;

m_D3DDevice->CreateOffscreenPlainSurface( m_iWidth, m_iHeight, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTemp, NULL );
hr = m_D3DDevice->CreateOffscreenPlainSurface( m_iWidth, m_iHeight, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTemp2, NULL );
				
if( hr != D3D_OK ) {
	MessageBox( m_hWnd, "Surface Creation Failed", "BUGGER", MB_OK );
}

hr = m_D3DDevice->GetDepthStencilSurface( &pTemp );
				
if( hr != D3D_OK ) {
	MessageBox( m_hWnd, "GetDepthStencilSurface Failed", "BUGGER", MB_OK );
}

m_D3DDevice->UpdateSurface( pTemp, NULL, pTemp2, NULL );

hr = D3DXSaveSurfaceToFile( "Temp.tga", D3DXIFF_TGA, pTemp, NULL, NULL );

if( hr != D3D_OK ) {
	MessageBox( m_hWnd, "D3DXSaveSurfaceToFile Failed.", "BUGGER", MB_OK );
}

pTemp->Release();
pTemp2->Release();

it all seems to work file until i try to update the surface where i get: Direct3D9: (ERROR) :Source and dest surfaces are different formats. UpdateSurface fails Direct3D9: (ERROR) :This format is not supported for SystemMem, Scratch or Managed textures Direct3D9: (ERROR) :Failure trying to create a texture the last 2 come from when it executes the SaveSurfaceToFile function. what am i doing wrong? my guess would have been the z/stencil buffer is a different format than my surfaces, but if i try to set it to be the same (D3DFMT_D24S8) i get an error that the format is not supported. any help would be great. thx in advance
Advertisement
D3DXSaveSurfaceToFile doesn't support depth-stencil buffers to the best of my knowlege. How would you convert depth information into pixel information?

Your best bet is creating a lockable depth buffer (D3DFMT_D16_LOCKABLE or D3DFMT_D32F_LOCKABLE), and locking it to save the values to a file.
As far as I know, you can't save stencil buffer information, or lock the stencil buffer.

Edit: About your errors:
The first error is because you create an A8R8G8B8 surface for pTemp2, but pTemp1 ends up as whatever format your depth-stencil surface is in. GetDepthStencilSurface() will overwrite the surface that's there (So you also have a resource leak).
The second and third errors are probably because you can't save depth-stencil formats to file using D3DXSaveSurfaceToFile().

Edit 2: What are you trying to do here anyway? If you want to save the depth buffer as an image, the best way would be to lock it, copy the data into a D3DFMT_L8 format surface (Lock them both, and do the conversion yourself), then save the D3DFMT_L8 surface with D3DXSaveSurfaceToFile().
cheers for the quick reply evil steve,

Quote:
The first error is because you create an A8R8G8B8 surface for pTemp2, but pTemp1 ends up as whatever format your depth-stencil surface is in. GetDepthStencilSurface() will overwrite the surface that's there (So you also have a resource leak).


yeah, i just saw this after posting.

Quote:
Your best bet is creating a lockable depth buffer (D3DFMT_D16_LOCKABLE or D3DFMT_D32F_LOCKABLE), and locking it to save the values to a file.


just so i can clarify, this basically means creating the depth/stencil buffer from scratch, not with the EnableAutoDepthStencil member of my Present parameters.


Quote:
As far as I know, you can't save stencil buffer information, or lock the stencil buffer.


i'm sure there must be a way, as i know Renderware is capable of this. Not sure if it is part of it's own functionality or what, but i have seen it done.
In your presentation parameters, when you create the device, you can specify one of those formats for the depth buffer format, you don't have to create it from scratch.

I also noticed that according to the D3DXSaveSurfaceToFile documentation (In my SDK at least, October 2004), it says that it can't save as TGA or PPM files.

The only way you can get access to the depth buffer is if you use a lockable format, and the only two lockable formats availiable don't have stencil information with them. The reason being that the graphics card might have the depth-stencil information in a special format, for performance reasons - or it might even be two seperate buffers, or compressed in some way.

Apparently it's possible to do what you're trying to do in OpenGL. Perhaps Renderware uses OGL? (I know nothing about either Renderware or OpenGL)
Quote:
I also noticed that according to the D3DXSaveSurfaceToFile documentation (In my SDK at least, October 2004), it says that it can't save as TGA or PPM files.


i read that as well, but it seems to work fine.

one more question, can i still read values from a buffer that i cant lock?

even the raw data would help, performance isn't an issue.

my plan is if i can get the raw data, convert it into rgb values( taking 8 bits for each colour ) then writing this manually to a file.

if you (or anyone else reading this) cannot think of any way i might be able to do this, maybe i should try doing this in OpenGL instead
Quote:Original post by NovaCaine
one more question, can i still read values from a buffer that i cant lock?
Nope. The only way to get information out of a non-lockable depth buffer would be with IDirect3DDevice::StretchRect() or IDirect3DDevice::UpdateSurface(), but StretchRect() can only copy to a depth-stencil buffer of the same format, which would mean you'd just have two copies of the data in a useless format. UpdateSurface() can only copy data from a system memory pool surface, and depth-stencil surfaces need to be in the default pool.
So it doesn't seem like it. Perhaps someone else can confirm/deny this?

What are you trying to do this for anyway? There may be a better way to do it.

This topic is closed to new replies.

Advertisement