为什么只需要 1 Depth/Stencil 缓冲区,即使交换链是三重缓冲的 DirectX 12

Why is only 1 Depth/Stencil buffer needed, even when the swap chain is tripple buffered DirectX12

我正在学习 DirectX12 编程。让我感到困惑的一件事是,在我阅读的所有教程中,即使 triple/double 缓冲与交换链一起使用,它们也只创建一个 depth/stencil 缓冲区。难道你不需要每个帧的 depth/stencil 缓冲区吗?

有问题的代码:

            D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
            dsvHeapDesc.NumDescriptors = 1; //why only 1?
            dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
            dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
            if(FAILED(device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&dsDescriptorHeap))))
            {
                MessageBoxW(NULL, L"Failed to create depth buffer descriptor heap!", L"Error", MB_OK | MB_ICONERROR);
                return -1;
            }
            D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
            depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
            depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
            depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;

            D3D12_CLEAR_VALUE depthOptimizedClearValue = {};
            depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;
            depthOptimizedClearValue.DepthStencil.Depth = 1.0f;
            depthOptimizedClearValue.DepthStencil.Stencil = 0;

            device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL), D3D12_RESOURCE_STATE_DEPTH_WRITE, &depthOptimizedClearValue, IID_PPV_ARGS(&depthStencilBuffer));
            depthStencilBuffer->SetName(L"Depth/Stencil Resource Heap");
            device->CreateDepthStencilView(depthStencilBuffer, &depthStencilDesc, dsDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

相关教程:

3D Game Engine Programming

BraynzarSoft

一般来说,“中间资源”(例如深度模板和中间渲染目标)不会呈现在屏幕上。

因此,当一个交换链准备好呈现(并且您开始记录下一帧命令)时,可以安全地覆盖这些资源,因为内容已在交换链中准备就绪。

这些资源的唯一例外通常是从 cpu 上传的缓冲区,对于它们来说,每帧需要一个缓冲区(因为您将在另一个命令列表仍在执行时开始复制数据) .