DirectX 12更新描述符堆

DirectX 12更新描述符堆,directx,directx-12,Directx,Directx 12,我目前正在为DirectX12编写自己的图形框架(我已经为个人游戏引擎编写了几个DirectX11框架),目前正在进行资源绑定 我对处理SRV/CBV/UAV堆的每个对象资源绑定的最佳方法感到困惑。我看过几次GDC演示,它们似乎都掩盖了这一点 一次只能绑定1个SRV/CBV/UAV堆,并且在命令列表中间切换当前绑定堆可能会对某些硬件的性能造成不利影响。因此,处理使用新描述符更新堆的最佳方法是什么?在我看来,似乎每个命令列表都会: 为自己获得一个SRV/CBV/UAV堆 对于对象子集中的每个对象,

我目前正在为DirectX12编写自己的图形框架(我已经为个人游戏引擎编写了几个DirectX11框架),目前正在进行资源绑定

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

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

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

  • 话虽如此,一些在线来源()建议使用一个大型SRV/CBV/UAV堆,并使用CPU可见堆复制到其中。我假设他们没有尝试使用异步
    copydescriptor
    ,而是
    CopyBufferRegion
    。我尝试使用
    CopyBufferRegion
    来更新每个对象的数据,但在我看来,在
    D3D12\u资源\u状态\u顶点\u和\u常量\u缓冲区
    D3D12\u资源\u状态\u复制\u目的地
    之间有如此多的转换,这似乎无法实现。我是不是误解了什么?请澄清。

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

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


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

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

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


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

    请务必查看这两种方法以及处理此问题的一些示例代码。请务必查看这两种方法以及处理此问题的一些示例代码。因此,如果我使用
    CopyDescriptor
    ,它何时更新GPU端的堆?当我调用setgraphicsrootdescriptorable时?否,CopyDescriptor是即时的,一旦返回,复制就完成了。唯一棘手的是根签名1.0和1.1。1.0和volatile table不假定描述符在CPU上使用时已准备就绪,而是假定在关闭命令列表时描述符将在这里。1.1使用静态表时,假设描述符在您将其设置为触发绘图时已准备就绪,并且此后不会更改。因此,如果我渲染多个对象,每个对象都具有唯一的cbuffer数据,我会调用
    CopyDescriptors
    以更新每个对象在不同偏移处的描述符堆?是的,没错,你像一个大的环形缓冲区一样在堆中运行,根据渲染操作的需要分配表,因为描述符必须在gpu完成它们之前生存。在
    copyDescriptor上的CPU暂停似乎非常昂贵,每个对象打开/关闭一次到gpu的管道。有什么我遗漏的吗?那么如果我使用
    CopyDescriptors
    ,它什么时候更新GPU端的堆?当我调用setgraphicsrootdescriptorable时
    ?否,CopyDescriptor是即时的,一旦返回,复制就完成了。唯一棘手的是根签名1.0和1.1。1.0和volatile table不假定描述符在CPU上使用时已准备就绪,而是假定在关闭命令列表时描述符将在这里。1.1使用静态表时,假设描述符在您将其设置为触发绘图时已准备就绪,并且此后不会更改。因此,如果我渲染多个对象,每个对象都具有唯一的cbuffer数据,我会调用
    CopyDescriptors
    以更新每个对象在不同偏移处的描述符堆?是的,没错,你像一个大的环形缓冲区一样在堆中行走,根据渲染操作的需要分配表,因为描述符必须在gpu完成它们之前生存下来