在DirectX 12桌面应用程序中,是否可以将HDR与MSAA相结合



使用DirectX 12工具包,我能够成功编译和运行各个MSAA和HDR教程示例。然而,当我将MSAA和HDR组件的相关代码组合到一个Game.cpp文件中时,编译失败,并显示调试层消息:

D3D12错误:ID3D12CommandList::ResolveSubresource:指定的格式与源资源不兼容。格式:R10G10B10A2_UNORM,源资源格式:R16G16B16A16_FLOAT[RRESOURCE_MANIPULATION ERROR#878:RESOLESUBRESOURCE_INVALID_Format]

我正在使用SDR显示器的HDR示例代码,因此需要应用色调映射。关于调用的顺序,在尝试解析MSAA渲染目标之前,我会调用以结束HDR场景:

// 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();
...

然后,在MSAA解析块之后,我将音调映射语句放置如下:

// 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;
...

我发现在设置用于绘制2D精灵的描述符堆(在3D场景上(之前尝试色调映射会导致错误:

D3D12错误:CGraphicsCommandList::SetGraphicsRootDescriptorTable:包含句柄0x80000253a82ff205的描述符堆(0x0000025428203230:"DescriptorHeap"(与当前设置的描述符堆0x000002542820 3540:"EffectTextureFactory"不同。[执行错误#708:SET_DESCRIPTOR_TABLE_INVALID]D3D12:BREAK为上一条消息启用,该消息为:[ERROR EXECTION#708:SET_DESCRIPTOR_TABLE_INVALID]

我承认这是第一次尝试将HDR和MSAA结合起来,但我担心这些功能在DirectX 12中可能不兼容和/或互斥。我理解为什么在MSAA解决过程中会出现资源兼容性问题,因为我们需要为HDR使用浮点渲染目标。我应该注意,如果我通过将m_MSAA布尔值设置为false跳过MSAA代码块,我的程序将使用HDR正确运行和渲染。

期待任何人的建议。如果需要足够的代码或有关程序的其他详细信息,我很乐意更新我的帖子。

为了使用4xMSAA成功渲染HDR场景,我进行了以下修订:

  1. CreateWindowSizeDependentResources((中,MSAA渲染目标(和视图(的定义格式与HDR渲染纹理相同:

    // Create an MSAA render target.
    D3D12_RESOURCE_DESC msaaRTDesc = CD3DX12_RESOURCE_DESC::Tex2D(
    //m_deviceResources->GetBackBufferFormat(),
    m_hdrScene->GetFormat(), // set matching format to HDR target (_R16G16B16A16_FLOAT)
    backBufferWidth,
    backBufferHeight,
    1, // This render target view has only one texture.
    1, // Use a single mipmap level
    4  // <--- Use 4x MSAA
    );
    ...
    
  2. 下一个主要变化是Render((,其中MSAA对HDR目标的解析发生在结束HDR场景渲染之后色调映射过程之前

    // Resolve the MSAA render target.
    auto backBuffer = m_deviceResources->GetRenderTarget();
    auto hdrBuffer = m_hdrScene->GetResource(); // HDR destination texture
    {
    D3D12_RESOURCE_BARRIER barriers[2] =
    {
    // transition msaa texture from target to resolve source
    CD3DX12_RESOURCE_BARRIER::Transition(
    m_msaaRenderTarget.Get(),
    D3D12_RESOURCE_STATE_RENDER_TARGET,
    D3D12_RESOURCE_STATE_RESOLVE_SOURCE),
    // transition hdr texture from pixel shader resource to resolve destination
    CD3DX12_RESOURCE_BARRIER::Transition(
    hdrBuffer,
    D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
    D3D12_RESOURCE_STATE_RESOLVE_DEST)
    };
    commandList->ResourceBarrier(2, barriers);
    }
    //commandList->ResolveSubresource(backBuffer, 0, m_msaaRenderTarget.Get(), 0,
    //    m_deviceResources->GetBackBufferFormat());
    // resolve MSAA to the single sample 16FP resource destination
    commandList->ResolveSubresource(hdrBuffer, 0, m_msaaRenderTarget.Get(), 0,
    m_hdrScene->GetFormat());
    // prepare backbuffer for 2D sprite drawing, typically rendered without MSAA
    {
    D3D12_RESOURCE_BARRIER barriers[2] =
    {
    // transition hdr texture from resolve destination back to p.s resource
    CD3DX12_RESOURCE_BARRIER::Transition(
    hdrBuffer,
    D3D12_RESOURCE_STATE_RESOLVE_DEST,
    D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE),
    // transition backbuffer from Present to render target (for sprite drawing after the MSAA resolve)
    CD3DX12_RESOURCE_BARRIER::Transition(
    backBuffer,
    D3D12_RESOURCE_STATE_PRESENT,
    D3D12_RESOURCE_STATE_RENDER_TARGET)
    };
    commandList->ResourceBarrier(2, barriers);
    }
    ... do tone mapping
    ... do 2D sprite drawing
    

输出为传统1080p显示器(无HDR10或V-Sync(。LHS屏幕捕捉是没有MSAA的HDR场景,而RHS捕捉显示了4xMSAA对3D线框对象的平滑效果;地球模型和三角形广告牌。cat和"Hello World"文本是在MSAA解析和色调映射后绘制到后缓冲区的2D精灵。

再次感谢@ChuckWalbourn为我指明了正确的方向,我期待着使用DirectX工具包推进我的项目。

ResolveSubresource无法进行从16fp到10:10:10:2 HDR10的转换。

通常你需要:

  1. 在高动态范围(线性颜色空间(中渲染到MSAA浮点
  2. 将MSAA解析为单采样浮点。(许多游戏选择使用高级软件抗锯齿技术作为这一过程的一部分,如FXAA、SMAA等。(
  3. 执行色调映射和Rec.2020颜色空间从浮点到10:10:10:2的转换
  4. 显示HDR10

渲染UI有时发生在步骤3之前,有时发生在之后。如果以前做过,你通常必须"放大"UI颜色,使其脱颖而出。

有关技术详细信息,请参阅SimpleMSAA DX12和SimpleHDR DX12示例。

DirectX工具包包括一个PostProcess类,它可以执行HDR10色调映射。请参阅本教程。

最新更新