Vulkan描述符绑定

Vulkan描述符绑定,vulkan,Vulkan,在我的vulkan应用程序中,当所有网格都使用相同的纹理时,我常常这样绘制网格 Updatedescriptorsets(texture) Command buffer record { For each mesh Bind transformubo Draw mesh } 但现在我希望每个网格都有一个独特的纹理,所以我尝试了这个 Command buffer record { For each mesh Bind transformubo

在我的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文档,发现在命令缓冲区记录期间无法更新描述符集。那么,如何为每个网格创建唯一的纹理呢?

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

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

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

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


如果有扩展VK_KHR_push_描述符可用,那么可以将对描述符的更改直接集成到命令缓冲区中。当然,这比推常量机制好多少取决于实现。

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

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

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