描述符表的高级用途

以下各节介绍有关描述符表的高级用途的信息。

更改呈现调用之间的描述符表项

在将设置描述符表的命令列表提交到队列以等待执行之后,应用程序不得从 CPU(属于 GPU 可能会引用的描述符堆的一部分)中编辑,直到应用程序知道 GPU 已用完引用。

可以使用用于跟踪 GPU 进度的 API 围栏或更粗略的机制(例如,等待查看已将呈现发送到显示器)在严格的界限内确定工作完成程度(任何适合应用程序的机制)。 如果应用程序知道只会访问描述符表指向的区域的一小部分(例如,由于着色器中的流控制),则仍可随意更改其他未引用的描述符。 如果应用程序需要在呈现调用之间切换不同的描述符表,有以下几种方法可供应用程序选择:

  • 描述符表版本控制:为命令列表引用的每个唯一的描述符集合创建 (或重复使用) 单独的描述符表。 当在描述符堆上编辑和重复使用之前填充的区域时,应用程序必须先确保 GPU 已用完将回收的描述符堆的任何部分。
  • 动态索引:应用程序可以排列不同绘制/调度 (甚至在描述符堆范围内的绘图) 内变化的对象,定义跨越所有对象的描述符表,并从着色器使用着色器执行期间对表进行动态索引以选择要使用的对象。
  • 直接在根签名中放置描述符。 通过这种方式只能管理极少数的描述符,因为根签名空间有限。

使用描述符表版本控制的含义是,描述符堆之外的描述符内存必须通过每个唯一描述符集刻录,这些描述符通过可以在任何给定时间内执行、排队等待执行或记录的每个命令列表的图形管道引用。

D3D12 将管理版本控制的责任留给通过描述符堆和描述符表管理的对象类型的应用程序。 这样做的一个好处是,应用程序可以选择尽可能多地重复使用描述符表内容,而不是始终为每个命令列表提交定义新的描述符表版本。 根签名是 D3D12 驱动程序自动版本控制的空间。

一次性地将多个描述符表绑定到根签名(从而绑定到管道)的能力使应用程序能够根据需要以不同的频率对描述符引用集进行分组和切换。 例如,应用程序可以使用少量(可能只有一个)很少更改的大型静态描述符表,或根据需要填充基础描述符堆内存中的区域(通过使用从着色器到选择纹理的动态索引)。 同时,应用程序可以维护另一个资源类,其中每个绘制调用引用的集使用描述符表版本控制技术从 CPU 进行切换。

越界索引

着色器中的任何描述符表的越界索引导致很大程度上未定义的内存访问,包括读取任意进程内内存的可能性,如同它是硬件状态描述符并伴随硬件所执行的操作一样。 这可能会导致设备重置,但不会使 Windows 崩溃。

着色器派生对象和差异索引

如果在 2x2 戳中执行的像素着色器调用(用于支持派生计算)选择不同的纹理索引以从描述符表之外采样,并且如果所选采样器配置和任何给定像素的纹理需要利用纹理坐标派生进行的 LOD 计算,则 LOD 计算和纹理采样过程通过 2x2 戳中的每个纹理查找的硬件独立完成,这样会影响性能。

描述符表