0

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

D3D12 错误:ID3D12CommandList::ResolveSubresource:指定的格式与源资源不兼容。格式:R10G10B10A2_UNORM,源资源格式:R16G16B16A16_FLOAT [RESOURCE_MANIPULATION ERROR #878:RESOLVESUBRESOURCE_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') 与当前设置的描述符堆 0x0000025428203540:'EffectTextureFactory' 不同。[执行错误#708:SET_DESCRIPTOR_TABLE_INVALID] D3D12:为上一条消息启用了BREAK,即:[错误执行#708:SET_DESCRIPTOR_TABLE_INVALID]

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

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

4

2 回答 2

1

为了使用 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 工具包推进我的项目。

于 2021-03-29T08:02:06.903 回答
0

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

一般来说,您需要:

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

渲染 UI 有时会发生在第 3 步之前,有时会发生在第 3 步之后。如果之前完成,您通常必须“放大” UI 颜色以使它们脱颖而出。

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

DirectX Tool Kit包括一个PostProcess可以执行 HDR10 色调映射的类。请参阅本教程

于 2021-03-27T19:14:43.103 回答