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

Glsl 如何避免有关未使用顶点输入的验证层错误?,glsl,vulkan,Glsl,Vulkan,我犯了很多错误,比如: 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 b

我犯了很多错误,比如:

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


忽略/消除这些错误的正确方法是什么?将一个虚拟空缓冲区绑定到这些绑定上可以吗?

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

绑定内存和复制一些数据是必要的,否则我会得到一个警告:
无法读取绑定缓冲区对象XXX的内存分配XXX的无效区域,请在使用前填充内存。


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

所有
vkCmdDraw
命令的有效用法如下所示:

通过顶点着色器入口点界面中声明的顶点输入变量访问的所有顶点输入绑定必须绑定有效的缓冲区

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

如果通过vkCmdBindDescriptorSets指定的绑定描述符集中的描述符被通过vkCmdBindPipeline指定的绑定VkPipeline对象静态使用,则这些描述符必须有效

规范一致认为不需要基于专门化常量执行死代码消除。如果没有DCE,对
f(输入)
的调用仍然存在于着色器中,即使它永远不会执行。因此,
input
变量仍然在接口中静态使用/声明,并且上述有效用法适用


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

我应该说,只要在创建缓冲区时正确设置用法,就可以将顶点缓冲区绑定完全指向其他缓冲区(如统一缓冲区)你在用它做别的东西。你不需要有一个完全未使用的缓冲区。没有DCE,对f(输入)的调用仍然存在于着色器中,即使它永远不会被执行。但是条件
if(flag)
是否每次都进行评估,还是由于专门化而优化了?(我希望是后者)驱动程序的着色器编译器很可能优化了条件和对f(input)的调用,因此这样做可能不会降低性能。但是这种优化并不能保证,所以规范必须是保守的,并且说您必须将某些东西绑定到输入。验证层只是根据规范中的说明进行检查;他们无法知道驱动程序是否需要缓冲区绑定。(即使他们确实知道,因为某些驱动程序可能不会这样做,他们仍然会让您知道您有一个可移植性缺陷。)