I would like to capture the contents of my front or back buffer using DirectX 11 into an array of bytes which I can then use as a texture or as a source for creating a file. I have a swap chain setup, lots of rendering happening and the following code so far - which I make sure to call after the call to Present.
ID3D11Texture2D* pSurface;
HRESULT hr = m_swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pSurface ) );
if( pSurface )
{
const int width = static_cast<int>(m_window->Bounds.Width * m_dpi / 96.0f);
const int height = static_cast<int>(m_window->Bounds.Height * m_dpi / 96.0f);
unsigned int size = width * height;
if( m_captureData )
{
freeFramebufferData( m_captureData );
}
m_captureData = new unsigned char[ width * height * 4 ];
ID3D11Texture2D* pNewTexture = NULL;
D3D11_TEXTURE2D_DESC description =
{
width, height, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM,
{ 1, 0 }, // DXGI_SAMPLE_DESC
D3D11_USAGE_STAGING,
0, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, 0
};
HRESULT hr = m_d3dDevice->CreateTexture2D( &description, NULL, &pNewTexture );
if( pNewTexture )
{
m_d3dContext->CopyResource( pNewTexture, pSurface );
D3D11_MAPPED_SUBRESOURCE resource;
unsigned int subresource = D3D11CalcSubresource( 0, 0, 0 );
HRESULT hr = m_d3dContext->Map( pNewTexture, subresource, D3D11_MAP_READ, 0, &resource );
//resource.pData; // TEXTURE DATA IS HERE
const int pitch = width << 2;
const unsigned char* source = static_cast< const unsigned char* >( resource.pData );
unsigned char* dest = m_captureData;
for( int i = 0; i < height; ++i )
{
memcpy( dest, source, width * 4 );
source += pitch;
dest += pitch;
}
m_captureSize = size;
m_captureWidth = width;
m_captureHeight = height;
return;
}
freeFramebufferData( m_captureData );
}
It always gives me black with zero alphas.
I would normally have the option of GDI interop to use BitBlt to copy a bitmap out of the swap chain - however I have restrictions which means this is not a valid solution.
Also the D3DX library, which contains functionality for doing bits of this is also out of the question.
Swap chain buffers can be easily saved with D3D11 as shown below.
contrived code fragment:
To copy the correct size, use the code below.
So. A little more experimentation revealed the "problem". By getting the description of the framebuffer texture and using that as the basis to create the new texture the problem was resolved...