c++ - 对齐 SSBO 的内存,即包含数组的结构数组?
问题描述
我正在展平八叉树并使用 SSBO 将其发送到我的片段着色器,我相信我遇到了一些内存对齐问题。我正在使用std430
布局并将体素向量绑定到这个 SSBO,这是我的着色器中的结构。我正在使用 GLSL 4.3 仅供参考
struct Voxel
{
bool data; // 4
vec4 pos; // 16
vec4 col; // 16
float size; // 4
int index; // 4
int pIndex; // 4
int cIdx[8]; // 4, 16 or 32 bytes?
};
layout (std430, binding=2) buffer octreeData
{
Voxel voxels[];
};
我不是 100% 确定,但我认为我在使用int cIdx[8]
结构内部的数组时遇到了问题,查看规范(第 124 页,第 7.6 节)
- 如果成员是标量或向量数组,则根据规则 (1)、(2) 和 (3) 设置基本对齐方式和数组跨度以匹配单个数组元素的基本对齐方式,并向上取整为vec4 的基本对齐方式。数组末尾可能有填充;数组后面的成员的基本偏移量向上舍入到基本对齐的下一个倍数。
我不完全确定对齐是什么,我知道 vec4 占用 16 个字节的内存,但我的数组有多少?如果只是sizeof(int)*8
32,但它说它被设置为单个数组元素的大小,然后四舍五入到 vec4 对吗?那么这是否意味着我的 cIdx 数组具有 16 个字节的基本对齐方式?没有后续成员,所以是否有填充添加到我的结构中?
所以总结构内存 = 52 个字节(如果我们只为 cIdx 分配 4 个字节),这是否意味着我需要添加 12 个字节的填充,这可能会导致我出现问题?如果它分配 16 个字节,那么结构总共是 64 个字节,并且没有内存对齐问题吗?
我对应的c++结构
struct Voxel
{
bool data;
glm::vec4 pos;
glm::vec4 col;
float size;
int index;
int pIndex;
int cIdx[8];
};
然后我填写我的std::vector<Voxel>
并将它传递给我的着色器,就像这样
glGenBuffers(1, &octreeSSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, octreeSSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, voxelData.size()*sizeof(Voxel), voxelData.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, octreeSSBO);
直接从voxelData
向量中读取,我可以确认数据被正确填充,我什至可以偶尔看到数据被传递给着色器,但与我期望看到的值相比表现不正确我'米看着。
看起来这里有内存对齐问题吗?
解决方案
我不完全确定对齐方式是什么
该规范非常清楚事物的基本对齐方式。您的问题不在第 4 项中(std430
无论如何都不会进行第 4 项中指定的舍入)。
你的问题在#2:
如果成员是一个二元或四元向量,其分量消耗 N 个基本机器单元,则基本对齐分别为 2N 或 4N。
在 GLSL 中,vec4
基本对齐为 16。这意味着任何vec4
必须在 16 字节边界上分配。
pos
必须在 16 字节的边界上。但是,data
只有4个字节。因此,必须在 和 之间插入 12 个字节的填充data
,pos
以满足 std430 的对齐要求。
但是,glm::vec4
C++ 对齐为 4。因此 C++ 编译器不会data
在和之间插入一堆填充pos
。因此,两种语言中的类型不一致。
alignas
您应该使用 C++11 的关键字显式对齐 C++ 结构中要匹配 GLSL 的所有 GLM 向量:
struct Voxel
{
bool data;
alignas(16) glm::vec4 pos;
alignas(16) glm::vec4 col;
float size;
int index;
int pIndex;
int cIdx[8];
};
另外,我不会假设 C++ 类型bool
和 GLSL 类型bool
具有相同的大小。
推荐阅读
- ios - 如何配置 Mailgun 以与 Sign in with Apple 和 Apple 的中继服务一起使用?
- amazon-web-services - 使用 nodeJs 将文件上传到 s3 存储桶而不使用 AWS 控制台
- python - 如何将列分隔符添加到 Pandas 数据框显示
- python - 不同模型的训练精度不同,但测试精度相同
- spring-boot - 如何处理 Elasticsearchn CRUD 操作的负 JUNIT 测试用例
- python - 如何在python中打印出txt文件的字典值的完整列表
- docker - 解决命令在 pod Kubernetes 中以退出代码 137 终止
- regex - 在 Python 中通过多个分隔符将一列拆分为两列
- sql - 如何以编程方式在 SQL LIKE 中转义通配符?
- python - 使用快速傅里叶变换的 3d 振动数据