【问题标题】:What is the valid way to bind per-object uniform buffers (e.g. camera matrices)?绑定每个对象统一缓冲区(例如相机矩阵)的有效方法是什么?
【发布时间】:2019-05-21 19:56:44
【问题描述】:

我有一些简单的 vulkan 应用程序:

  • 每个交换链图像的 3 个命令缓冲区(#1、#2、#3)

  • 1 个带有投影矩阵数据的统一缓冲区

我想绑定一次统一缓冲区。我正在使用命令缓冲区 #1 来绑定统一缓冲区:

   begin();
   bindDescriptorSets();
   end();
   submit();
   waitIdle();
   reset();

然后我为每个交换链图像记录命令(3 次):

   begin()
   bindVertexBuffers()
   beginRenderPass()
   bindPipeline()
   draw()
   endRenderPass()
   end();

绘图按预期工作,但验证层记录错误:

[ UNASSIGNED-CoreValidation-DrawState-DescriptorSetNotBound ] Object: 0x1a57aad7910 (Type = 6) | VkPipeline 0x21 uses set #0 but that set is not bound.

如果我将bindDescriptorSets(); 行移动到第二个记录块,如下所示:

   begin()
   bindDescriptorSets();
   bindVertexBuffers()
   beginRenderPass()
   bindPipeline()
   draw()
   endRenderPass()
   end();

验证没问题,但是渲染没有区别。

所以,问题是:我必须为每个缓冲区记录绑定描述符集吗?如果是,为什么当我绑定描述符集一次时应用程序工作正常?

【问题讨论】:

  • "waitIdle" 这是你应该永远不要做的事情

标签: vulkan


【解决方案1】:

我认为这与 Vulkan 应用程序的当前状态有关。让我们看看规范对状态的描述:

2.2.1。队列操作

记录在命令缓冲区中的命令执行操作 (...)、设置状态(绑定管道、描述符集、 和缓冲区,设置动态状态,推送常量,设置渲染 通过/次通过状态),或执行同步(...)。一些命令 执行其中一项以上的任务。状态设置命令更新 命令缓冲区的当前状态。

注意我用粗体标记了绑定描述符集是一个状态命令

您将描述符集绑定到命令缓冲区,结束该缓冲区并提交。接下来,您启动其他命令缓冲区。让我们再看看规范告诉我们关于命令缓冲区的内容:

  1. 命令缓冲区

每个命令缓冲区独立于其他命令缓冲区管理状态。跨主节点没有状态继承 和辅助命令缓冲区,或在辅助命令缓冲区之间。 当命令缓冲区开始记录时,该命令中的所有状态 缓冲区未定义。

因此规范和层告诉您,您必须将描述符绑定到使用该状态的每个命令缓冲区。为什么即使有警告它也能工作?我不知道,可能你的实现允许它,但我不建议保持原样。

【讨论】:

  • 非常感谢!我认为每帧设置状态是一些开销。使用 opengl 就不需要做这样的事情了。这是否意味着opengl驱动程序在后台的每一帧都做同样的事情(设置状态)?
  • 我不知道,我从未编写过 OpenGL。但如果驱动程序记住状态并且是的,每“帧”都设置它,我不会感到惊讶。
  • 有两件事——创建状态和绑定要使用的状态。状态创建很昂贵,状态绑定很便宜。 OpenGL ES 基本上进行动态状态创建和状态绑定(几乎任何东西在绘制时间之前都是可变的)。 Vulkan 会预先创建大多数状态,所以实际上您所要做的就是绑定(这主要是设置一组指针间接,因此非常快)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多