0

我目前正在为 DirectX12 编写自己的图形框架(我已经为个人游戏引擎编写了几个 DirectX 11 框架),并且我目前正在尝试复制最近的 Hitman 游戏中用于资源绑定的方法。

我对处理 SRV/CBV/UAV 堆的每个对象资源绑定的最佳方式感到困惑。我看过几个 GDC 演示文稿,它们似乎都掩盖了这一点。

一次只能绑定 1 个 SRV/CBV/UAV 堆,并且在命令列表中间切换当前绑定的堆可能会因强制刷新而对某些硬件的性能不利。因此,使用新描述符更新堆的最佳方法是什么?对我来说,似乎每个命令列表都会:

  1. 为自己获取一个 SRV/CBV/UAV 堆。
  2. 对于对象子集中的每个对象,在堆上创建描述符,指向放置在单独上传堆中的每个对象数据。
  3. 之后,另一个命令列表获取这个填充的描述符堆并绑定它,然后发出混合的绘制调用SetGraphicsRootDescriptorTable,以便在当前描述符堆中移动。

话虽如此,一些在线资源(包括另一篇 SO 帖子)建议使用一个大型 SRV/CBV/UAV 堆并使用 CPU 可见堆复制到其中。我假设他们没有尝试使用 asynchronous CopyDescriptors,而是CopyBufferRegion. 我尝试使用CopyBufferRegion来更新每个对象的数据,但对我来说,这似乎表现不佳,因为D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER和之间有如此多的转换D3D12_RESOURCE_STATE_COPY_DEST。我是不是误会了什么?任何清晰度将不胜感激。

4

1 回答 1

2

CopyDescriptors不是异步的,它是在 CPU 上立即执行的 CPU 操作。它可以在为 volatile 描述符执行命令列表之前的任何时间发生(在使用它的命令列表操作被记录之后),或者必须准备好用于静态描述符(根签名 1.1)。

通常的方法是拥有一个大的描述符堆,保留一部分用于静态描述符,然后将其余部分用作环形缓冲区,按需分配描述符表偏移量以复制并使用所需的描述符进行任何绘制/计算操作。

CopyBufferRegion这里无关紧要,记住映射缓冲区也是一个即时操作,因此您还为每个对象常量缓冲区环形缓冲了一大块内存,然后循环进入它。唯一的事情是,您需要确保在内存或描述符仍在使用时不会覆盖它们,因此您必须隔离以防止这种情况。

于 2017-01-16T17:46:12.333 回答