4
votes

I have a Direct3D 11 renderer that I'm implementing shared surfaces in to display content in a WPF application (which only uses Direct3D 9).

On the D3D11 side my back buffer is using the format DXGI_FORMAT_R8G8B8A8_UNORM and this works fine. According to this documentation DXGI_FORMAT_R8G8B8A8_UNORM maps to D3DFMT_A8B8G8R8 in D3D9. However, when I go to create the texture on the D3D9 side using that format it fails. I'm using Windows 10 and there's no D3D9 debug runtime so all I get is a D3DERR_INVALIDCALL as a result with no additional information.

This documentation seems to say that only the ARGB format is supported for back buffers in D3D9, with the ABGR format not listed under any section for support. Is this a mistake in the documentation or is this format completely unsupported?

If I instead use DXGI_FORMAT_B8G8R8A8_UNORM on the D3D11 side and D3DFMT_A8R8G8B8 on the D3D9 side texture creation succeeds.

For further confusion, this post implies that DXGI_FORMAT_R8G8B8A8_UNORM should be the more compatible format, yet it's the one I'm having trouble with.

I've also confirmed this behavior with the Microsoft WPF DirectX Interop sample on GitHub. Out of the box it's using DXGI_FORMAT_R8G8B8A8_UNORM and works fine, but if I change the back buffer to DXGI_FORMAT_B8G8R8A8_UNORM it breaks.

Why does a format that my video card supports work in one API and not the other? How do I know for sure which formats are supported in D3D9?

2

2 Answers

2
votes

Stick with DXGI_FORMAT_B8G8R8A8_UNORM on the D3D11 side and D3DFMT_A8R8G8B8 in D3D9. Although DXGI_FORMAT_R8G8B8A8_UNORM is technically more compatible, if you don't require D3D10 support, it should be supported on all D3D11 devices.

How do I know for sure which formats are supported in D3D9?

You can get this (for your system) using the "DirectX Caps Viewer" (which comes with the Windows SDK - which comes with recent versions of Visual Studio). There is a section "Direct3D9 Devices". If you expand that for your adapter, and then D3D Device Types -> HAL -> Adapter Formats, there are sections for backbuffer formats, and which formats they support (screenshot from my system attached).

DirectX Caps Viewer

This same information is available at runtime via IDirect3D9::CheckDeviceFormat.

This documentation seems to say that only the ARGB format is supported for back buffers in D3D9, with the ABGR format not listed under any section for support. Is this a mistake in the documentation or is this format completely unsupported?

D3D9 did not support rendering to ABGR formats, but theoretically it was available as a format that could be sampled. However, it was not in common use, and looking through my current driver's caps, it's not supported. Best to stick to ARGB, which has universal (although, not actually guaranteed) support.

0
votes

The BGRA (or ARGB) format is actually more compatible on most PCs, as that's the pixel format used by Windows GDI. At least NVidia built their GPUs with the Windows GDI pixel format in mind, so they recommend using BGRA instead of RGBA in order to bypass any costly format conversion: http://http.download.nvidia.com/developer/Papers/2005/Fast_Texture_Transfers/Fast_Texture_Transfers.pdf

If you had a Direct3D9 back buffer using D3DFMT_A8B8G8R8 (if Direct3D9 would support that), then on every call to IDirect3DDevice9::Present() the system (or GPU) would have to switch the bytes of each back buffer pixel around to match what Windows GDI expects, which is a very costly operation. This performance penalty is actually noticeable on OpenGL (which targets a hypothetical "perfect" GPU and allows for many incompatible format combinations by performing the necessary conversions on the CPU).