Advertisement Jump to content
Sign in to follow this  

Take a screenshot in D3D12

This topic is 782 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts


here the code I used using D3D11 to take a screenshot :

CImage CDirect3D11RenderWindow::ScreenShot() const
	// Get the back buffer.
	ID3D11Texture2D* BackBuffer;
	m_SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< LPVOID* >( &BackBuffer ) );

	// Set the staging desc.
	D3D11_TEXTURE2D_DESC StagingDesc;
	BackBuffer->GetDesc( &StagingDesc );
	StagingDesc.Usage = D3D11_USAGE_STAGING;
	StagingDesc.BindFlags = 0;
	StagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;

	// Create the back buffer staging texture.
	ID3D11Texture2D* BackBufferStaging;
	CDirect3D11Device::GetDevice()->CreateTexture2D( &StagingDesc, nullptr, &BackBufferStaging );

	// Copy back buffer to back buffer staging.
	CDirect3D11Device::GetDeviceContext()->CopyResource( BackBufferStaging, BackBuffer );

	// Get the size of the window.
	UInt32 Width, Height;
	GetSize( &Width, &Height );

	// Image data.
	UInt8* ImageData = new UInt8[ Width * Height * 4 ];

	// Create the image.
	CDirect3D11Device::GetDeviceContext()->Map( BackBufferStaging, 0, D3D11_MAP_READ, 0, &Map );
	UInt8* BackBufferData = static_cast< UInt8* >( Map.pData );
	UInt8* ImageDataPtr = &ImageData[ 0 ];
	for( UInt32 y = 0; y < Height; ++y )
		for( UInt32 x = 0; x < Width; ++x )
			ImageDataPtr[ 4 * x + 0 ] = BackBufferData[ 4 * x + 0 ];
			ImageDataPtr[ 4 * x + 1 ] = BackBufferData[ 4 * x + 1 ];
			ImageDataPtr[ 4 * x + 2 ] = BackBufferData[ 4 * x + 2 ];
			ImageDataPtr[ 4 * x + 3 ] = 255;
		BackBufferData += Map.RowPitch;
		ImageDataPtr += Width * 4;
	CDirect3D11Device::GetDeviceContext()->Unmap( BackBufferStaging, 0 );

	// Release the backbuffer staging.

	// Create the image.
	CImage Image;
	Image.Create( Width, Height, ImageData );

	// Return the image.
	return Image;

I'm not well experienced actually in D3D12 but from what I saw, the read back is different than D3D11.

Is it possible to have informations about how to convert for D3D12 correctly ?



Share this post

Link to post
Share on other sites

There's no such thing as a staging or readback texture anymore in D3D12, so you'll have to copy your texture over to a readback buffer first using ID3D12GraphicsCommandList::CopyTextureRegion.

Have a look at D3D12_TEXTURE_COPY_LOCATION to see how you can set up your buffer as a texture copy destination.

Share this post

Link to post
Share on other sites

If you are not an expert at d3d11, you should probably not even look at d3d12, and if you are you would probably no asking that :) But anyway, here the details :


0. Create or use an existing graphic command list

1. Use GetCopyableFootprints to obtain the size a readback buffer you are gonna need

2. Create a commited resource buffer in copy dest state

3. Transition the image resource you want to copy to generic read

4. Use CopyTextureRegion to copy from the texture to the buffer

5. Execute the command list

6. Fence and wait for everything to have complete

7. Map on the buffer, use the result of 1 to know how to read the image ( pitch, width, height, ... )


The 6 is the important concept in d3d12 that is not in d3d11, you are responsive for making sure everything execute or is unused before you proceed further or destroy any resource that may be still in use otherelse

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!