我有D3D11的经验,并想学习D3D12。我正在阅读正式的D3D12多线程示例,不明白为什么为每个帧创建影子映射(在第一次传递中生成的DSV,第二次以SRV的形式使用)(实际上只有两个副本,因为FrameResource每2帧重复使用一次)。
创建影子映射资源的代码是这里,在FrameResource类中,其实例被创建为这里。
实际上,为每个帧创建了另一个资源,即常量缓冲区。我有点理解常量缓冲器。因为它是由CPU编写的(D3D11动态使用),并且需要保持不变,直到GPU使用完它,所以需要有两个副本。但是,我不明白为什么阴影映射需要这样做,因为它只被GPU (D3D11默认用法)修改,而且还有一些隔离命令来区分对纹理的读写。只要GPU遵循栅栏,一个纹理就足以使GPU正确工作。我哪里错了?
提前谢谢。
编辑
根据下面的评论,我上面提到的“围栏”应该更准确地称为“资源障碍”。
发布于 2021-06-18 21:43:59
关键的问题是,您不想拖延GPU的最佳性能。双缓冲是一个最低限度的要求,但通常三缓冲是更好的平滑帧对帧渲染尖峰,等等。
FWIW,DXGI Present的默认行为是只在提交了三帧工作框架之后才停止工作,而不是两帧。
当然,在三重缓冲和输入响应之间有一个权衡,但如果你保持60赫兹或更高的频率,它可能是不明显的。
尽管如此,通常您不需要双缓冲深度/模板缓冲区来呈现,尽管如果您想让深度缓冲区的初始写入与先前深度缓冲区的读取重叠,那么您将需要每个帧的不同缓冲区来提高性能和正确性。
在DX12中的“读”之前,“写”全部完成,因为在命令列表中注入了“资源屏障”:
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));
}请注意,此示例是旧版本的DirectX SDK示例MultithreadedRendering11的端口/重写,因此,使用两个影子缓冲区而不是一个影子缓冲区可能只是一个方便的工件。
https://stackoverflow.com/questions/68040979
复制相似问题