将多个网格绘制到不同的位置(DirectX 12)

时间:2016-09-30 17:31:41

标签: c++ graphics directx-12

我遇到了DirectX 12的问题。我制作了一个小型3D渲染器。模型在顶点着色器中转换为3D空间,基本的World View Projection矩阵处于常量缓冲区。

要更改当前使用memcpy(pMappedConstantBuffer + alignedSize * frame, newConstantBufferData, alignedSize)的常量缓冲区的数据,此命令会立即替换常量缓冲区的数据。

所以问题就出现了,绘图被记录到一个命令列表中,该列表稍后会被发送到gpu执行。

示例:

/* Now i want to change the constant buffer to change the next draw call's position to (0, 1, 0) */
memcpy(/*Parameters*/);

/* Now i want to record a draw call to the command list */
DrawInstanced(/*Parameters*/);

/* But now i want to draw other mesh to other position so i have to change the constant buffer. After this memcpy() the draw position will be (0, -1, 0) */
memcpy(/*Parameters*/);

/* Now i want to record new draw call to the list */
DrawInstanced(/*Parameters*/);

在此之后我将命令列表发送到gpu执行,但是quess所有网格将在同一位置,因为所有memcpys都会在命令列表发送到gpu之前执行。所以基本上最后一个memcpy会覆盖以前的memcpy。

所以基本上问题是如何将网格绘制到不同的位置或如何在命令列表中替换常量缓冲区的数据,以便常量缓冲区在gpu上的每个绘制调用之间发生变化?

由于

不再需要帮助我自己解决了。我为每个网格创建了常量缓冲区。

1 个答案:

答案 0 :(得分:0)

关于执行顺序,你完全正确,memcpy调用会立即更新缓冲区,但是在你将命令列表推入队列之前不会处理命令(你不会确切知道何时会发生这种情况)。

在Direct3D11中,当您在缓冲区上使用Map时,会为您处理(如果需要,将分配一些空间以避免这种情况)。

所以在Direct3D12中你有几个选择,我认为你想要绘制N个对象,并且你想在你的cbuffer中为每个对象存储一个矩阵。

首先是为每个对象创建一个缓冲区并独立设置数据。如果你只有少数几个,这很容易维护(由于资源分配会有额外的内存占用空间)

其他选项是创建一个大缓冲区(可以包含N个矩阵),并创建N个常量缓冲区视图,指向每个对象的内存位置。 (请注意,在这种情况下您还必须考虑256字节对齐,请参阅CreateConstantBufferView)。

您还可以使用StructuredBuffer并将所有数据复制到其中(在这种情况下,您不需要对齐),并使用顶点着色器中的索引来查找正确的矩阵。 (可以在着色器中设置uint值,并使用SetGraphicsRoot32BitConstant直接应用它。)