不正确的 Vulkan 统一缓冲区内存对齐

Incorrect Vulkan UniformBuffer Memory Alignment

本文关键字:缓冲区 内存 对齐 Vulkan 不正确      更新时间:2023-10-16

根据规范,在统一缓冲区内声明的变量必须正确对齐。

我的结构中有以下 GLM 变量:

struct UniformBufferObject_PointLights {
glm::f32 constant[64]{};
glm::f32 linear[64]{};
glm::f32 quadratic[64]{};
glm::vec3 position[64]{};
glm::vec3 ambient[64]{};
glm::vec3 diffuse[64]{};
glm::int32 count{};
};
  • 尝试从着色器中访问任何变量的行为 好像它们的值都是 0。问题集中在glm::f32glm::uint32声明。

glm::vec3都可以通过简单地在glm::f32glm::uint32上方声明它们来访问,但是,glm::uint32glm::f32仍然无法访问。在这一点上,我认为这一定是一个对齐问题

//  After rearrangement.
struct UniformBufferObject_PointLights {
glm::vec3 position[64]{};
glm::vec3 ambient[64]{};
glm::vec3 diffuse[64]{};
glm::f32 constant[64]{};
glm::f32 linear[64]{};
glm::f32 quadratic[64]{};
glm::uint32 count{};
};
  • positionambientdiffuse在移动后都可以访问 它们到结构的顶部。

我已经设置了#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES但它似乎不适用于glm::f32glm::uint32,可能也适用于其他人。我需要做什么才能让这些变量在我的统一缓冲区中工作?我尝试在声明之前放置alignas(4)alignas(8)alignas(16)alignas(32),但没有组合工作。

统一缓冲区中的数组必须按照 std140 对齐,这基本上是 vec4 对齐的。

这意味着您的均匀缓冲区太小。至于着色器,浮点 foo[64] 实际上与 vec4 foo[64] 的大小相同。Alignas 限定符不允许您更改它。

要么使用存储缓冲区,这可能更慢,要么只在数组中使用 vec4。