DirectX 12 学习 —— 描述符(Descriptor)管理

DirectX 12 学习 —— 描述符(Descriptor)管理
最新回答
落日在山时

2026-06-22 23:04:18

学习DirectX 12,了解描述符(Descriptor)管理时,面对《DirectX 12 3D 游戏开发实战》(龙书)中对DirectX 12 API的使用介绍,读者可能会遇到无法直接应用于工程实践的问题,特别是关于如何自行管理描述符堆。Jeremiah van Oosten的GitHub项目及其教程提供了一种可行的解决方案,旨在解决这一困惑。

管理方案的核心思路分为CPU可见和GPU可见的描述符堆。CPU可见的描述符堆负责存放所有资源描述符,而GPU可见的描述符用于绑定到根签名。当需要将资源描述符绑定到根签名时,会从CPU可见的描述符堆中拷贝到GPU可见的描述符堆中。这一设计使得资源描述符的管理更加灵活,适应了DirectX 12的自主管理需求。

在实现过程中,对于贴图的SRV(Shader Resource View)管理,创建贴图时,其构造函数调用CreateViews来创建SRV及相应的描述符。在描述符分配器(DescriptorAllocator)的作用下,所有CPU可见描述符通过它进行分配生成。分配器包含了多个描述符页(DescriptorAllocatorPage),每个描述符页是ID3D12DescriptorHeap的包装。当描述符堆满时,分配器会创建新的描述符页以继续分配描述符。

对于申请新的描述符堆,即创建新的描述符页,代码逻辑清晰明了。在渲染主循环中,通过CommandList里的动态描述符堆(DynamicDescriptorHeap)将SRV绑定到根签名,使用SetShaderResourceView函数暂存描述符,最后通过CommitDescriptorTables函数将暂存的描述符拷贝到GPU可见描述符堆中,再进行提交。

MiniEngine作为微软提供的使用DirectX 12实现的示例代码,其描述符管理逻辑与Jeremiah van Oosten的实现方案相似。UE4的Unreal Engine 4.26中,对于描述符的管理同样遵循了类似的策略,将CPU可见描述符称为离线描述符(Offline Descriptor),而GPU可见描述符则称为在线描述符(Online Descriptor)。

总结而言,通过CPU可见和GPU可见描述符堆的管理方案,DirectX 12的描述符问题得到了有效解决,既适应了API的自主管理需求,又提供了在工程实践中灵活分配资源的机制。学习DirectX 12时,不仅需要理解API的使用,更重要的是通过分析实际的引擎代码,了解知识如何应用于实际工程中,以解决具体问题。