Vulkan描述符绑定

时间:2018-04-24 15:07:45

标签: vulkan

在我的vulkan应用程序中,当所有网格使用相同的纹理时,我曾经像这样绘制网格

Updatedescriptorsets(texture)

Command buffer record
{
 For each mesh
        Bind transformubo
        Draw mesh
}

但是现在我希望每个网格都有一个独特的纹理,所以我尝试了这个

Command buffer record
{
 For each mesh
        Bind transformubo
        Updatedescriptorsets (textures[meshindex])
        Draw mesh
}

但它给出了一个错误,说明描述符被销毁或更新。我查看了vulkan文档,发现我无法在命令缓冲区记录期间更新descriptorset。那么我怎样才能为每个网格提供独特的纹理呢?

2 个答案:

答案 0 :(得分:7)

vkUpdateDescriptorSets未与任何内容同步。因此,您无法在使用时更新描述符集。您必须确保使用相关描述符集的所有渲染操作都已完成,并且没有命令放置在使用相关集的命令缓冲区中。

它基本上就像一个全局变量;没有某种同步,你不能让人们从众多线程中访问全局变量。 Vulkan不会同步对描述符集的访问。

有几种方法可以解决这个问题。您可以为每个对象提供自己的描述符集。这通常通过使频繁变化的描述符集数据具有比不太频繁变化的数据更高的索引来完成。这样,您不会更改每个对象的每个描述符,只会更改基于每个对象的描述符。

您可以使用推送常量数据来索引大型表/数组纹理。因此描述符集将具有数组纹理或纹理数组(如果您对纹理数组具有动态索引)。推送常量将提供一个索引,着色器使用该索引从数组纹理/纹理数组中获取该特定对象的纹理。这使得频繁更改相当便宜,同样的索引也可用于为每个对象提供自己的转换矩阵(通过提取到矩阵数组中)。

如果您具有可用的扩展VK_KHR_push_descriptor,则可以将对描述符的更改直接集成到命令缓冲区中。这比推送常量机制好多少当然是依赖于实现的。

答案 1 :(得分:1)

如果更新描述符集,则此描述符集绑定的所有命令缓冲区将变为无效。无法提交或由GPU执行无效的命令缓冲区。

您基本上需要做的是在绑定它们之前更新描述符集。

这种奇怪的行为是因为在vkCmdBindDescriptorSets中某些实现采用了vulkan描述符集,将其转换为本机描述符表,然后将其存储在命令缓冲区中。因此,如果在vkCmdBindDescriptorSets之后更新描述符集,则命令缓冲区将看到过时数据。 VK_EXT_descriptor_indexing扩展在某些情况下放宽了此行为。