在我的vulkan应用程序中,当所有网格使用相同的纹理时,我曾经像这样绘制网格
Updatedescriptorsets(texture)
Command buffer record
{
For each mesh
Bind transformubo
Draw mesh
}
Run Code Online (Sandbox Code Playgroud)
但现在我希望每个网格都有一个独特的纹理,所以我尝试了这个
Command buffer record
{
For each mesh
Bind transformubo
Updatedescriptorsets (textures[meshindex])
Draw mesh
}
Run Code Online (Sandbox Code Playgroud)
但它给出了一个错误,说明了描述符被销毁或更新.我查看了vulkan文档,发现在命令缓冲区记录期间我无法更新descriptorset.那么我怎样才能为每个网格提供独特的纹理?
vkUpdateDescriptorSets
没有与任何东西同步.因此,您无法在使用时更新描述符集.您必须确保使用相关描述符集的所有呈现操作都已完成,并且没有命令放在使用相关集的命令缓冲区中.
它基本上就像一个全局变量; 没有某种同步,你不能让人们从众多线程中访问全局变量.Vulkan不会同步对描述符集的访问.
有几种方法可以解决这个问题.您可以为每个对象提供自己的描述符集.这通常通过使频繁变化的描述符集数据具有比不太频繁变化的数据更高的索引来完成.这样,您不会更改每个对象的每个描述符,只会更改基于每个对象的更改.
您可以使用推送常量数据来索引大型表/数组纹理.因此描述符集将具有数组纹理或纹理数组(如果您对纹理数组具有动态索引).推送常量将提供一个索引,着色器使用该索引从数组纹理/纹理数组中获取该特定对象的纹理.这使得频繁更改相当便宜,并且相同的索引也可用于为每个对象提供其自己的转换矩阵(通过提取到矩阵数组中).
如果您具有可用的扩展VK_KHR_push_descriptor,则可以将对描述符的更改直接集成到命令缓冲区中.这比推送常量机制好多少当然是依赖于实现的.