部分更新 D3D11 常量缓冲区

Partially updating D3D11 constant buffer

在业余时间,我正在使用 D3D11 开发 3D 引擎。为了获得 3D 效果,我在我的 HLSL 着色器中使用了典型的模型视图投影矩阵乘法。这些矩阵被上传到 d3d11 常量缓冲区。投影矩阵仅在调整视口大小时发生变化,但模型和视图矩阵可以逐帧变化(当模型或相机移动时)。矩阵中的这些更改必须上传到相同的常量缓冲区,以便在着色器中使用。上传这些更改时,投影矩阵(通常)没有改变,所以我不想重新上传这个矩阵。所以简而言之,我需要通过仅更新缓冲区中的特定部分(偏移量)来部分更新常量缓冲区。

在 openGL 中,我们有统一的缓冲区,它们的工作方式(我认为)与 d3d11 常量缓冲区的工作方式相同。但是,如果要更新统一缓冲区的特定部分,可以使用 openGL 函数 glBufferSubData。我尝试在 D3D11 中寻找类似的方法来执行此操作,但我没有找到任何东西。我确实找到了有类似问题的人,但他使用的是 D3D11.1。 link 到原来的 post:How to partially update constant buffer in DirectX 11.1。也有人说,在D3D11中,如果要更改特定部分,需要将所有数据上传到常量缓冲区中。但这可能会导致在 CPU 端(RAM)保留我的缓冲区的完整副本。一定有更好的方法吧?

tldr;如何在特定偏移量上更新我的 d3d11 常量缓冲区?

为什么不用多个常量缓冲区?这将使您拥有一个很少改变的,而其他的可以在每一帧中改变。我很确定我已经在一些示例中看到过它(虽然我没有去看)。

您有多种选择来管理它们。

最简单的方法是为每个更新速率创建一个常量缓冲区(因此您将有一个缓冲区用于世界矩阵,每个对象都会更改,一个用于视图,每帧更新一次,另一个用于投影,更新非常快)偶尔。

就是说,我从来没有发现拆分视图和投影矩阵有那么大的好处(我的意思是我们说的是每帧 64 字节的额外数据更新,这真的没什么,特别是考虑到常量缓冲区对齐256 字节边界)。

如果您将开始添加阴影贴图(如果您进行平截头体拟合,您的阴影相机投影矩阵会在每一帧发生变化),则更是如此。

此外,如果您以后打算制作其他 post 效果(如 ao、景深...),您还需要为相机添加额外的数据(位置、逆向视图、逆向投影) , projection inverse), 所以每帧更新一次所有相机数据通常更有益(我通常使用保留的 cbuffer 插槽作为相机缓冲区,所以我不必一直重新绑定它)。