如何将一组统一缓冲区对象加载到着色器中?

how can i load an array of uniform buffer objects into the shader?

着色器代码:

// UBO for MVP matrices   
layout (binding = 0) uniform UniformBufferObject {
        mat4 model;
        mat4 view;
        mat4 proj;
} ubo;

这很好用,因为它只有一个结构,我可以将 VkWriteDescriptorSet.descriptorCount 设置为 1。但是我如何创建这些结构的数组?

// Want to do something like this
// for lighting calculations
layout (binding = 2) uniform Light {
    vec3 position;
    vec3 color;
} lights[4];

我将所有四盏灯的数据存储在一个缓冲区中。当我将 VkWriteDescriptorSet.descriptorCount 设置为四时, 我必须创建四个 VkDescriptorBufferInfo 吗?如果是这样,我不知道将什么放入偏移量和范围。

统一缓冲区数组中的所有块都位于同一个描述符中。但是,它们仍然是不同的块;他们得到一个不同的 VkDescriptorBufferInfo 信息对象。所以这些块不必来自连续的存储区域。

注意:KHR_vulkan_glsl 扩展名 gets this wrong,如果你看的话请密切注意。它指出,不透明类型的数组应该放入单个描述符中,但接口块的数组则不需要。实际的 glslangValidator 编译器(以及 SPIR-V 和 Vulkan)确实按照我的描述处理它。

但是,除了动态统一表达式之外,您无法访问接口块数组的元素。甚至 that 也需要有特定的功能可用;没有该功能,您只能使用 constant 表达式访问数组。

您可能想要的是 within 块的数组,而不是 of 块的数组:

struct Light
{
  vec4 position; //(NEVER use `vec3` in blocks)
  vec4 color;
};

layout (set = 0, binding = 2, std140) uniform Lights {
  Light lights[4];
};

这意味着您在绑定槽 2 中只有一个描述符(descriptorCount 为 1)。并且缓冲区的数据应该是 4 个顺序结构。