在DirectX12中,可以使用世界变换的单个统一缓冲区在不同位置渲染多个对象,如下所示:
// Basic simplified pseudocode
SetRootSignature();
SetPrimitiveTopology();
SetPipelineState();
SetDepthStencilTarget();
SetViewportAndScissor();
for (auto object : objects)
{
SetIndexBuffer();
SetVertexBuffer();
struct VSConstants
{
QEDx12::Math::Matrix4 modelToProjection;
} vsConstants;
vsConstants.modelToProjection = ViewProjMat * object->GetWorldProj();
SetDynamicConstantBufferView(0, sizeof(vsConstants), &vsConstants);
DrawIndexed();
}但是,在Vulkan中,如果您使用单个统一缓冲区执行类似的操作,则所有对象都会在最后一个世界矩阵的位置渲染:
for (auto object : objects)
{
SetIndexBuffer();
SetVertexBuffer();
UploadUniformBuffer(object->GetWorldProj());
DrawIndexed();
}在Vulkan中,有没有一种方法可以像DirectX12一样,用一个统一的缓冲区来绘制多个对象?
我知道Sascha Willem的Dynamic uniform buffer示例(https://github.com/SaschaWillems/Vulkan/tree/master/dynamicuniformbuffer),他在一个大的统一缓冲区中打包了许多矩阵,虽然很有用,但并不是我想要的。
提前感谢您的帮助。
发布于 2017-08-01 10:38:54
我在D3D 12API中找不到名为SetDynamicConstantBufferView的函数。我认为这是你的发明的一些功能,但由于不知道它是做什么的,我只能真正猜测。
它看起来像是在渲染时将数据上传到buffer对象。如果真是这样,那么伏尔坎就不能这么做。这是一件好事。上传到你当前正在读取的内存需要同步。你必须在上一个读取你要覆盖的数据的渲染命令和下一个渲染命令之间设置一个屏障。如果你喜欢性能,这不是一个好主意。
但同样,我不确定该函数到底在做什么,所以我的理解可能是错误的。
在Vulkan中,描述符通常不会在渲染帧的过程中更改。然而,Vulkan的制作者意识到,用户有时希望使用同一VkBuffer对象的不同子集进行绘制。这就是动态统一/存储缓冲区的用途。
从技术上讲,您没有多个统一缓冲区;您只有一个。但您可以使用提供给vkCmdBindDescriptorSets的偏移来移动下一个渲染命令将从该缓冲区中获取数据的位置。因此,这是一种轻量级的方式,可以为不同的渲染命令提供不同的数据。
基本上,您重新绑定了描述符集,但使用了不同的pDynamicOffset数组值。要使这些工作,您需要提前计划。管道布局必须显式地将这些描述符声明为动态描述符。每次绑定集合时,都需要向该描述符使用的缓冲区提供偏移量。
也就是说,让您的统一缓冲区存储更大的矩阵数组可能会更好,使用动态偏移量从一个矩阵块跳到另一个矩阵块。你可能会觉得
这样做的要点是,除非更改偏移或着色器,否则提供的统一数据(取决于硬件)将保留在着色器内存中。上传这类数据需要一些小成本,因此最大限度地减少这种上传的需求可能不是一个坏主意。
因此,您应该在单个DMA操作中上传所有对象缓冲区数据。然后,您发出一个屏障,并使用动态偏移量等进行渲染,以告知每个偏移量的位置。
发布于 2017-08-01 05:37:51
您要么必须使用推常量,要么每个位置都有单独的统一缓冲区。它们可以通过每个动态偏移量位置的描述符进行绑定。
在Sasha的例子中,制服中可以有多个矩阵。
这意味着在UploadUniformBuffer中,您将新矩阵附加到缓冲区并绑定新位置。
https://stackoverflow.com/questions/45425603
复制相似问题