graphics - 为什么需要为 D3D12 中的每一帧创建 GBuffers?
问题描述
我有 D3D11 的经验并想学习 D3D12。我正在阅读官方 D3D12 多线程示例,但不明白为什么要为每一帧创建阴影贴图(在第一遍中作为 DSV 生成,在第二遍中作为 SRV 使用)(实际上只有 2 个副本,因为FrameResource
被重用每 2 帧)。
创建阴影贴图资源的代码在此处,在FrameResource
类中,其实例在此处创建。
实际上,每个帧都会创建另一个资源,即常量缓冲区。我有点理解常量缓冲区。因为是CPU写的(D3D11动态使用),需要保持不变直到GPU用完,所以需要2份。但是,我不明白为什么阴影贴图需要这样做,因为它仅由 GPU 修改(D3D11 默认使用),并且无论如何都有栅栏命令来分离对该纹理的读取和写入。只要 GPU 遵循围栏,单个纹理就足以让 GPU 正常工作。我哪里错了?
提前致谢。
编辑
根据下面的评论,我上面提到的“栅栏”应该更准确地称为“资源屏障”。
解决方案
关键问题是您不想让 GPU 停止以获得最佳性能。双缓冲是最低要求,但通常三缓冲更适合平滑帧到帧的渲染峰值等。
FWIW,DXGI 的默认行为Present
是仅在您提交三帧工作后才停止,而不是两帧。
当然,在三重缓冲和输入响应之间需要权衡取舍,但如果您保持 60 Hz 或更好的频率,则可能不会引起注意。
综上所述,通常您不需要双缓冲深度/模板缓冲区进行渲染,尽管如果您想让深度缓冲区的初始写入与先前深度缓冲区通道的读取重叠,那么您会为了性能和正确性,每帧需要不同的缓冲区。
由于在命令列表中注入了“资源屏障”,因此“写入”在 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的移植/重写,因此拥有两个阴影缓冲区而不仅仅是一个阴影缓冲区可能只是一种方便的工件。
推荐阅读
- python - 当估计矩阵用作MVN分布的协方差矩阵时,如何避免输入矩阵在RNN模型中不可逆错误
- swift - 闰年和使用的符号
- python - 海龟图形移动方块
- jenkins - 如何在 Jenkins 的 Groovy 脚本中使用参数化的字符串
- sql - 将过时的 Oracle 联接转换为 SQL
- html - Guru Meditation 错误:ESP32 上的 Core 1 Panic'ed (Load Prohibited)
- android - Android 双向数据绑定使用 MutableStateFlow 并观察 ViewModel 的变化
- docker - Elasticsearch 错误:“master not found yet” - 节点之间没有路由
- c# - 如何抑制 NLOG 结构化日志记录中的某些字段?
- java - IntelliJ Idea 如何在我的 maven 项目中自动检测 testng 监听器?