如何避免关于未使用的顶点输入的验证层错误?

How to avoid validation layer errors about unused vertex inputs?

我遇到很多错误,例如:

The Pipeline State Object (0x51) expects that this Command Buffer's vertex binding Index 10 should be set via vkCmdBindVertexBuffers. This is because VkVertexInputBindingDescription struct at index 10 of pVertexBindingDescriptions has a binding value of 10.'

原因是我有一个着色器,其中根据某些专业化常量的值使用某些顶点输入,例如:

layout(constant_id = 0) const bool flag = false;
layout(location    = 0) in vec3 input;

void main() {
  if (flag) {
    f(input);
  } else {
    // ignore input
  }
}

尽管如此,一切正常,因为我实际上并没有使用 input

ignore/silence 这些错误的正确处理方法是什么?将虚拟空缓冲区绑定到这些绑定是否可以?

目前,我的解决方案是创建一个虚拟缓冲区,绑定内存并将一些数据复制到其中。这会消除来自验证层的错误。

绑定内存和复制一些数据是必要的,否则我会得到一个警告:Cannot read invalid region of memory allocation XXX for bound Buffer object XXX, please fill the memory before using.

不过,我想知道是否有更清洁的解决方案。

所有 vkCmdDraw 命令的有效用法为:

All vertex input bindings accessed via vertex input variables declared in the vertex shader entry point’s interface must have valid buffers bound

这与通过描述符处理的其他资源绑定的规则非常相似:

Descriptors in each bound descriptor set, specified via vkCmdBindDescriptorSets, must be valid if they are statically used by the bound VkPipeline object, specified via vkCmdBindPipeline

关于要求根据专业化常量执行死代码消除的规范是一致的。如果没有 DCE,对 f(input) 的调用仍然存在于着色器中,即使它永远不会被执行。所以input变量仍然在接口中静态使用/声明,上面的有效用法适用。

所以你必须有一个缓冲区限制。但是,它可能非常小,因为您从未真正从中读取过数据,也不必用数据填充它。它可以包含随机的未初始化垃圾(如果验证层抱怨这一点,它应该只是作为警告,不是错误)。