Microsoft::WRL::ComPtr<ID3D12Resource> mVertexBuffer;
D3D12_VERTEX_BUFFER_VIEW mVertexBufferView;
// Index Buffer
Microsoft::WRL::ComPtr<ID3D12Resource> mIndexBuffer;
D3D12_INDEX_BUFFER_VIEW mIndexBufferView;
// World View Projection Constant Buffer
Microsoft::WRL::ComPtr<ID3D12Resource> mWVPConstantBuffer;
WVPData mWVPData;
UINT8* mMappedWVPBuffer;
// Directional Light Constant Buffer
Microsoft::WRL::ComPtr<ID3D12Resource> mDirLightConstantBuffer;
DirLightData mDirLightData;
UINT8* mMappedDirLightBuffer;
// CBVHeap
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mCbvHeap;
UINT mCbvDescriptorSize;
顶点缓冲区,索引缓冲区, cbvHeap和两个常量缓冲区。一种用于变换矩阵,另一种用于定向光数据。
我不确定cbvHeap(恒定缓冲区视图堆)的实际作用。我只是知道如何使用它来将内容显示到屏幕上。所以我做了实验。我从网格对象中取出了cbvHeap和mCbvDescriptorSize并将其放入场景对象(包含网格阵列的场景对象)中,然后在我所有的网格中使用相同的cbvheap。这没有用,因为它在整个网格上提供了一种一致的颜色。 (即:每个网格都使用了相同的常量缓冲区,从而为它们提供了相同的漫反射和环境光数据。)描述符堆正是由于什么原因引起的?我对每个网格的定义正确吗?
#1 楼
在DX12中,描述符是一条小记录,基本上是一个指针,它告诉GPU在哪里可以找到一些数据,例如常量缓冲区。由于每个对象都将具有其自己的常量缓冲区数据以及其特定的变换,照明/材质属性等,因此每个对象还必须以一组单独的描述符结尾以指向其各自的数据。有两种方法可以在DX12中设置描述符。首先,您可以在命令列表中添加直接在根表中更新描述符的命令。例如,可以使用
SetGraphicsRootConstantBufferView()
为对象的常量缓冲区设置描述符,然后绘制对象。重复多个对象。这些描述符将保存在命令列表中,并在GPU上执行命令列表时按顺序应用。另一种方法是使用描述符堆。描述符堆基本上是存储描述符数组的缓冲区。使用这种方法,命令列表不会为您保存描述符。您必须自己管理它们。如果在GPU使用描述符之前覆盖了所有描述符,那么您将得到错误的结果。这听起来像是程序中正在发生的事情:每次在CPU上发布对象的绘制命令时,您都可能覆盖堆中的相同描述符,因此在GPU执行命令列表时,只有最后写入的描述符仍然存在要解决此问题,必须在描述符堆中分配足够的空间来存储要用于框架的所有描述符。将所有对象的描述符写入堆。然后在绘制每个对象时,使用
SetGraphicsRootDescriptorTable()
将着色器指向该对象的数据,并带有偏移句柄,该句柄指向该对象的描述符所在的堆中的位置。只要您仍在尝试学习并运行一个简单的应用程序,我就可能会坚持使用根表方法。对于更严肃的高性能应用程序,可能需要对描述符堆进行优化,例如将给定材料的所有常量和纹理保持在一起,以便可以在多个对象之间重用它们并将它们全部绑定在一个调用中。您可能还想避免每个对象具有恒定的缓冲区和描述符堆,而是将许多对象的数据聚合到几个大的缓冲区中。 还值得注意的是,一个严肃的3D应用程序希望同时运行多个帧的命令列表,以获得CPU / GPU。并行性,这将需要延长常量缓冲区和描述符堆的长度,以存储多个帧的数据。同样,您可以通过一次构建单个命令列表,提交并等待其完成然后再转到下一帧来掩盖这些信息,以进行学习/培训。
评论
$ \ begingroup $
两种方法(使用SetGraphicsRootConstantBufferView()设置常量缓冲区GPU地址或对根表中的描述符使用辅助查找)的问题是,如果没有足够的GPU地址可用于渲染所有对象,则应用程序开发人员必须实施重用恒定缓冲存储器的策略。应用程序可能必须关闭并提交当前命令列表(先关闭(Close(),然后再重置Reset)),这意味着您必须将状态(PSO和其他状态)复制到新的命令列表中。应用程序应如何在环形缓冲区策略中使用常量缓冲区存储器
$ \ endgroup $
–user5241
16-10-6在0:59
$ \ begingroup $
好像SE在转换为评论时切断了帖子。它以“ ... y继续”。在过去,驱动程序会注意到没有覆盖设置,或者如果先前的内存繁忙则重命名该内存。如何在DX12中实现这些策略?
$ \ endgroup $
–马丁·恩德(Martin Ender)
16-10-6在8:08