Vulkan:有没有办法在DirectX12中的不同位置绘制多个对象?

问题描述:

在DirectX12,渲染使用世界单一统一缓存相当于在不同位置的多个对象的变换,如:Vulkan:有没有办法在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(); 
} 

然而,福尔康,如果你做一个单一的统一的缓存类似的东西全部,

for (auto object : objects) 
{ 
    SetIndexBuffer(); 
    SetVertexBuffer(); 

    UploadUniformBuffer(object->GetWorldProj()); 

    DrawIndexed(); 
} 

有没有一种方法来绘制多个对象,在福尔康一个统一的缓存,就像在DirectX12:对象在过去的世界矩阵的位置呈现?

我知道Sascha Willem的动态统一缓冲区示例(https://github.com/SaschaWillems/Vulkan/tree/master/dynamicuniformbuffer),他将许多矩阵包装在一个大的统一缓冲区中,虽然有用,但并不完全符合我的要求。

在此先感谢您的帮助。

您必须使用Push常量或为每个位置使用单独的统一缓冲区。这些可以与每个动态偏移位置的描述符绑定。

在萨沙的例子中,你可以不仅仅是制服内的一个矩阵。

这意味着在UploadUniformBuffer中,您将新矩阵附加到缓冲区并绑定新位置。

我在D3D 12 API中找不到一个叫SetDynamicConstantBufferView的函数。我认为这是你发明的一些功能,但不知道它的作用,我只能猜测。

它看起来像你正在上传数据到缓冲区对象而渲染。如果是这种情况,那么Vulkan不能那样做。这是一个好东西。上传到您正在阅读的内存需要同步。您必须在读取要覆盖的数据的最后一个渲染命令与下一个渲染命令之间发出障碍。如果你喜欢表演,这不是一个好主意。

但是我再也不确定这个功能到底在做什么,所以我的理解可能是错误的。


在Vulkan中,描述符一般不会在渲染帧的过程中发生变化。然而,Vulkan的制造商意识到用户有时想使用同一个VkBuffer对象的不同子集。这是动态统一/存储缓冲区的用途。

您在技术上没有多个统一缓冲区;你只有一个。但是您可以使用提供给vkCmdBindDescriptorSets的偏移量来移动下一个渲染命令将从其缓冲区获取数据的位置。因此,以不同的数据提供不同的渲染命令是一种轻量级的方式。

基本上,您重新绑定了描述符集,但使用了不同的pDynamicOffset数组值。为了使这些工作,你需要提前计划。您的管道布局必须将这些描述符显式声明为动态描述符。每次你绑定这个集合,你都需要在这个描述符所使用的缓冲区中提供偏移量。这就是说,使统一缓冲区存储更大的矩阵阵列,使用动态偏移量从一个矩阵块跳到另一个矩阵块可能会更好。你需要的是,你要提供的统一数据(取决于硬件)将保留在着色器内存中,除非你做了一些改变偏移量或着色器的内容。上传这些数据有一些小的成本,所以最大限度地减少这种上传的需求可能不是一个坏主意。

所以你应该去上传全部你的对象缓冲数据在一个DMA操作中。然后你发出一个障碍,并进行渲染,使用动态偏移等来告诉每个偏移量在哪里。