为什么需要为 D3D12 中的每一帧创建 GBuffers?

Why GBuffers need to be created for each frame in D3D12?

我有使用 D3D11 的经验,想学习 D3D12。我正在阅读 official D3D12 multithread example 并且不明白为什么为每个帧(实际上只有 2 个副本,因为 FrameResource 每 2 帧重复使用一次)。

创建阴影贴图资源的代码是here, in the FrameResource class, instances of which is created here

实际上还有一个为每一帧创建的资源,常量缓冲区。我有点理解常量缓冲区。因为是CPU写的(D3D11动态使用),需要保持不变,直到GPU用完,所以需要2份。但是,我不明白为什么阴影贴图需要做同样的事情,因为它只被GPU修改(D3D11默认使用),而且无论如何都有栅栏命令来分离读取和写入那个纹理。只要 GPU 跟随栅栏,单个纹理就足以让 GPU 正常工作。我哪里错了?

提前致谢。

编辑

根据下面的评论,我上面说的“围栏”更准确的说应该叫“资源屏障”。

关键问题是您不想停止 GPU 以获得最佳性能。双缓冲是最低要求,但通常三缓冲更适合平滑帧到帧渲染尖峰等。

FWIW,DXGI Present 的默认行为是仅在您提交 三个 个工作帧后才停止,而不是两个。

Of course, there's a trade-off between triple-buffering and input responsiveness, but if you are maintaining 60 Hz or better than it's likely not noticeable.

综上所述,通常您不需要双缓冲 depth/stencil 缓冲区进行渲染,尽管如果您想让深度缓冲区的初始写入与 previous 深度缓冲区通过然后你会希望每帧都有不同的缓冲区以提高性能和正确性。

DX12 中 'writes' 在 'reads' 之前全部完成,因为 'Resource Barrier' 注入了命令列表:

void FrameResource::SwapBarriers()
{
    // Transition the shadow map from writeable to readable.
    m_commandLists[CommandListMid]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_shadowTexture.Get(), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
}

void FrameResource::Finish()
{
    m_commandLists[CommandListPost]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_shadowTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
}

Note that this sample is a port/rewrite of the older legacy DirectX SDK sample MultithreadedRendering11, so it may be just an artifact of convenience to have two shadow buffers instead of just one.