为什么我的 glBindBufferRange 偏移对齐不正确?

Why is my glBindBufferRange offset alignment incorrect?

我很难理解 glBindBufferRange 偏移/对齐在 Nvidia 示例项目中的工作原理 gl_commandlist_basic我读到偏移量需要是 GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 的倍数,即 256 and/or 偏移量和对齐对于 glBindBuffer 范围非常重要。。我有一个使用 mat4/vec4 的示例 UBO 和一个使用 mat4/mat3/vec4 的非工作示例。在这两种情况下,UBO 加起来都不是 256 的倍数。我尝试发送 vec4(0.f, 1.f, 0.f, 1.f)。

如果 mat4 = 64 字节,mat3 = 36 字节,vec4 = 16 字节,那么工作示例有 64+16=80 字节,这不是 256 的倍数.非工作示例有 64+36+16 = 116 个字节。

NV 使用名为 uboAligned 的内联,定义为

inline size_t uboAligned(size_t size) { return ((size + 255) / 256) * 256; }

从 working/non 中删除它没有任何区别。

我假设我需要以 float/vec2/vec3/vec4 等形式向 UBO 添加一些 "padding"。如果我想使用mat4/mat3/vec4最终受益人?

/* APPLICATION */
typedef struct
{
    glm::mat4 MM;
    // glm::mat3 NM;
    glm::vec4 Cs;
} myData0;

Gluint objectUBO;
glCreateBuffers(1, &objectUBO);
glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData) * 2), 0, GL_STATIC_DRAW); //

for (unsigned int i = 0; i < allObj.size(); ++i)
{
    myData0 myDataTemp;
    myDataTemp.Cs = glm::vec4(0.f, 1.f, 0.f, 1.f);
    glNamedBufferSubData(objectUBO, sizeof(abjObjectData) * i, sizeof(abjObjectData), &objDataInit);
}

//hot loop
for (unsigned int i = 0; i < allObj.size(); ++i)
{
    glBindBufferRange(GL_UNIFORM_BUFFER, 1, objectUBO, uboAligned(sizeof(abjObjectData)) * i, sizeof(abjObjectData));
    //draw
}

/* HW */
out vec4 Ci;

struct ObjectData
{
    mat4 MM;
    // mat3 NM;
    vec4 Cs;
};

layout (std140, binding = 1) uniform objectBuffer { ObjectData object; };

void main()
{
    Ci = object.Cs;
}

OpenGL 使用特定的对齐方式。假设你正在使用 std140 布局,例如,这是 Cpp 中定义的结构:

struct PointLight
{
    glm::vec3 position;
    int padding; //this is needed for alignement
    glm::vec3 color; // because a vec3 has to be aligned
    float intensity; //no need for alignment because a float can be read directly without alignement
};

您可以在着色器中传递给这样的结构制服:

uniform light
{
    vec3 Position;
    vec3 Color;
    float Intensity;
} PointLight;

我会测试类似的东西:

struct ObjectData
{
    mat4 MM;
    mat3 NM;
    vec3 padding; //I think you have to add 3 floats of padding
    vec4 Cs;
};

但是我找不到更多关于它的信息,我不记得我是在哪里找到它的。

你有不同类型的内存布局,你可以检查它们,std140 在规范中定义内存布局here and I advise you to use this layout. If you don't, shared layout will be used and you have to query the layout. You can use OpenGL to query the layout to know what padding you should add BlockLayoutQuery

关于glBindBufferRange,我从来没有听说过256位对齐。这是我如何使用它的示例:

const int pointLightCount = SomeNumber;
int pointLightBufferSize = sizeof(PointLight) * pointLightCount + sizeof(int) * 4;

glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER, pointLightBufferSize, 0, GL_DYNAMIC_COPY);
void * lightBuffer = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
((int*) lightBuffer)[0] = pointLightCount;
 for (int i = 0; i < pointLightCount; ++i) {
        PointLight p = { something };
        ((PointLight*) ((int*) lightBuffer + 4))[i] = p;
    }
    glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
    glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, ssbo[0], 0, pointLightBufferSize); //Bind all the buffer

glNamedBufferData 的简单拼写错误。变化自

glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData) * 2), 0, GL_STATIC_DRAW);

glNamedBufferData(objectUBO, uboAligned(sizeof(abjObjectData)) * 2, 0, GL_STATIC_DRAW);

修复了偏移/对齐问题。