Search code examples
directx-12hdrmsaadirect3d12

Is it possible to combine HDR with MSAA in a DirectX 12 desktop application?


Using the DirectX Tool Kit for DirectX 12, I'm able to successfully compile and run the individual MSAA and HDR tutorial samples. When I combined the relevant code for the MSAA and HDR components together into a single Game.cpp file however, compilation fails with the debug layer message:

D3D12 ERROR : ID3D12CommandList::ResolveSubresource : The specified format is not compatible with the source resource.Format : R10G10B10A2_UNORM, Source Resource Format : R16G16B16A16_FLOAT [RESOURCE_MANIPULATION ERROR #878: RESOLVESUBRESOURCE_INVALID_FORMAT]

I am using the HDR sample code for an SDR display monitor, and therefore need to apply tone mapping. With respect to the order in which calls are made, I make a call to end the HDR scene before attempting to resolve the MSAA render target:

// 3d rendering completed
m_hdrScene->EndScene(commandList);

if (m_msaa)
{
    // Resolve the MSAA render target.
    //PIXBeginEvent(commandList, PIX_COLOR_DEFAULT, L"Resolve");

    auto backBuffer = m_deviceResources->GetRenderTarget();
    ...

Then following the MSAA resolve block, I place the tone mapping statement as follows:

// Unbind depth/stencil for sprites (UI)
auto rtvDescriptor = m_deviceResources->GetRenderTargetView();
commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, nullptr);

// set texture descriptor heap in prep for sprite drawing
commandList->SetDescriptorHeaps(static_cast<UINT>(std::size(heaps)), heaps);

// apply tonemapping to hdr scene
switch (m_deviceResources->GetColorSpace())
{
default:
    m_toneMap->Process(commandList);
    break;
...

I found that attempting to tone map before setting the descriptor heap for drawing 2D sprites (over the 3D scene) would result in the error:

D3D12 ERROR: CGraphicsCommandList::SetGraphicsRootDescriptorTable: The descriptor heap (0x0000025428203230:'DescriptorHeap') containing handle 0x80000253a82ff205 is different from currently set descriptor heap 0x0000025428203540:'EffectTextureFactory'. [ EXECUTION ERROR #708: SET_DESCRIPTOR_TABLE_INVALID] D3D12: BREAK enabled for the previous message, which was: [ ERROR EXECUTION #708: SET_DESCRIPTOR_TABLE_INVALID ]

I admit this was a rather naive first attempt to combine HDR and MSAA, but I'm concerned that these features could be incompatible and/or mutually exclusive in DirectX 12. I understand why a resource compatibility issue arises during MSAA resolve, as we need to use floating point render targets for HDR. I should note that my program will run and render correctly with HDR if I skip the MSAA code blocks by setting my m_msaa boolean to false.

Looking forward to any advice anyone may have. If sufficient code or other details about the program are required, I'll be happy to update my post.


Solution

  • ResolveSubresource cannot do the conversion from 16fp to 10:10:10:2 HDR10.

    Generally you need to:

    1. Render to MSAA floating-point in High Dynamic Range (linear color space)
    2. Resolve MSAA to single-sample floating-point. (Many games choose to use advanced software antialiasing techniques as part of this process such as FXAA, SMAA, etc.)
    3. Perform the tone-map and Rec.2020 colorspace conversion from floating-point to 10:10:10:2
    4. Display HDR10

    Rendering the UI sometimes happen before step 3, other times after. If done before, you typically have to 'scale up' the UI colors to make them stand out.

    See the SimpleMSAA DX12 and SimpleHDR DX12 samples for the technical details.

    DirectX Tool Kit includes a PostProcess class which can perform the HDR10 tone-map. See this tutorial.