0
votes

I trying to take a screenshot using DirectX, and then save it to file. But when the below code executes, I get a totally black .png sized(width/height) as target DirectX app. What am I doing wrong?

HRESULT hr = S_OK;

ID3D11Texture2D* pBuffer;
ID3D11Texture2D* pBackBufferStaging = NULL;

pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBuffer);

D3D11_TEXTURE2D_DESC td;
pBuffer->GetDesc(&td);
td.Usage = D3D11_USAGE_STAGING;
td.BindFlags = 0;
td.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
td.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;

pDevice->CreateTexture2D(&td, NULL, &pBackBufferStaging);
pContext->CopyResource(pBackBufferStaging, pBuffer);

D3DX11SaveTextureToFile(pContext, pBackBufferStaging, D3DX11_IFF_PNG, L"D:\\screen.png");

pBackBufferStaging->Release();
pBuffer->Release();

pSwapChain is pointer to IDXGISwapChain, pDevice is pointer to ID3D11Device, and pContext is pointer to ID3D11DeviceContext. They are all setup correctly but the resulting screenshot is still black.

Update #1

Error checking shows nothing. All functions are successfully executed. While in DirectX 11 "Hello world", everything works fine. What am I doing wrong? I am trying to screen shot a World of Tanks game.

Update #2

On DirectX 9, my approach works fine - Heartstone produces working screenshot.

2
Error checking is not optional.Hans Passant
@HansPassant the question was not about this. And as I said, they are hooked correctly. So the question is what's wrong hereIGR94
Well, you have no error checking and that's exactly why you don't know what's wrong.Violet Giraffe
@VioletGiraffe okey, with error checking, no errors occurred but screenshot is still black.IGR94
WoT game? some DRM protection is in the way perhaps - is the behavior the same when you just use print screen?Ap31

2 Answers

1
votes

Try to pass the following texture description to CreateTexture2D:

D3D11_TEXTURE2D_DESC td;
pBuffer->GetDesc( &td);
td.BindFlags = 0;
td.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
td.Usage = D3D11_USAGE_STAGING;

Do not set td.Format and td.MiscFlags.

1
votes

Are you trying to get a screenshot of your own app, or of the desktop? If it's another app, how did you get its swap chain? If you're using Windows 8+, you can get a screenshot of the desktop using the Desktop Duplication API

BTW, you can pass the flag D3D11_CREATE_DEVICE_DEBUG when creating the device (D3D11CreateDevice or D3D11CreateDeviceAndSwapChain) and then inspect the debugging output. It might give you some important clues.