DirectX 11 framebuffer capture (C ++, without Win32 or D3DX)

I would like to capture the contents of my front or rear buffer using DirectX 11 into an array of bytes, which I can then use as a texture or as a source to create a file. I have a swap chain, a lot of rendering results and the following code so far - which I will definitely call after the Present call.

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 ); } 

He always gives me black with zero alpha.

I usually have the option of interacting with GDI to use BitBlt to copy a bitmap from the swap chain, but I have limitations, which means that this is not an acceptable solution.

Nor can there be a D3DX library that contains the functionality to execute bits of this.

+8
c ++ directx graphics directx-11
source share
3 answers

So. A little more experimentation revealed a "problem." Having received a description of the framebuffer texture and using this as the basis for creating a new texture, the problem was solved ...

 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; pSurface->GetDesc( &description ); description.BindFlags = 0; description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; description.Usage = D3D11_USAGE_STAGING; 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_WRITE, 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 ); } 
+8
source share

Conversation buffers can be easily saved using D3D11, as shown below.

  • Create Texture2D just like the backup buffer you are trying to save
  • Call CopyResource in the device context to copy from the back buffer to the newly created texture
  • Call D3DX11SaveTextureToFile (...) with the file name

far-fetched code snippet:

 ID3D11Texture2D* pBuffer; swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBuffer); if(texture_to_save == NULL) { D3D11_TEXTURE2D_DESC td; pBuffer->GetDesc(&td); device->CreateTexture2D(&td, NULL, &texture_to_save); } deviceContext->CopyResource(texture_to_save, pBuffer); D3DX11SaveTextureToFile(deviceContext,texture_to_save,D3DX11_IFF_PNG,filename); 
+2
source share

To copy the correct size, use the code below.

 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; pSurface->GetDesc( &description ); description.BindFlags = 0; description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; description.Usage = D3D11_USAGE_STAGING; 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_WRITE, 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 += resource.RowPitch; // <------ dest += pitch; } m_captureSize = size; m_captureWidth = width; m_captureHeight = height; return; } freeFramebufferData( m_captureData ); } 
+2
source share

All Articles