Vulkan UniformBuffer 内存对齐不正确 [重复]

Posted

技术标签:

【中文标题】Vulkan UniformBuffer 内存对齐不正确 [重复]【英文标题】:Incorrect Vulkan UniformBuffer Memory Alignment [duplicate] 【发布时间】:2019-11-28 11:46:26 【问题描述】:

As per the specification 在统一缓冲区中声明的变量必须正确对齐。

我的结构中有以下 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::f32glm::uint32 上方声明即可访问glm::vec3,但是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;
;
position,ambient,diffuse移动后都可以访问 它们位于结构的顶部。

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

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

SSBO 无济于事; vec3s 始终是 16 字节对齐的,即使在 std430 布局中也是如此。 确实如此。但是标量是紧密排列的。 Vec3 几乎从未紧密封装在任何 API 中。将它们提升到 vec4 的开销也比使用标量要小得多。编辑:这个问题的结束并不是那么好,因为它不仅仅是关于 vec3,而且标量数组是 vec4,假设的重复没有解决。

以上是关于Vulkan UniformBuffer 内存对齐不正确 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Vulkan系列教程—VMA教程—虚拟分配器

Vulkan系列教程—VMA教程—虚拟分配器

Vulkan系列教程—VMA教程—虚拟分配器

不取消映射 vulkan 内存

无法将 Cuda 内存导入 Vulkan

Vulkan系列教程—VMA教程—选择内存类型