简体   繁体   English

了解GLSL统一缓冲区块对齐

[英]Understanding GLSL Uniform Buffer Block Alignment

I'm having trouble understanding the std140 layout for GLSL uniform buffer objects. 我无法理解GLSL统一缓冲区对象的std140布局。 I'm under the impression that in the following uniform block, the int will begin at offset 0 and the matrix will begin at offset 16. The following uniform is giving me a bad matrix, apparent because nothing draws on-screen. 我的印象是在下面的统一块中,int将从偏移量0开始,矩阵将从偏移量16开始。以下均匀性给出了一个糟糕的矩阵,很明显,因为没有任何东西在屏幕上绘制。

layout (std140) uniform Camera
{
    int renderMode;
    mat4 projection;
} camera;

The point of renderMode is that it tells me that the uniform update code doesn't work. renderMode是它告诉我统一更新代码不起作用。

I have the following code (homegrown) to help me along. 我有以下代码(本土)来帮助我。 This is the code that makes the Open GL calls in my C++ application. 这是在我的C ++应用程序中进行Open GL调用的代码。 This code is inside a class called UniformBufferObject . 此代码位于名为UniformBufferObject的类中。

#define UpdateExData(o, s, d) glBindBuffer(GL_UNIFORM_BUFFER, _uboId); \
    glBufferSubData(GL_UNIFORM_BUFFER, o, s, d); \
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

int Alignment(int offset, int alignment)
{
    int leftOver = offset % alignment;
    if (leftOver > 0)
    {
        return offset + (alignment - leftOver);
    }
    else
    {
        return offset;
    }
}

template<typename T, typename... Args>
void UpdateEx(int offset, const std::vector<T>& data, Args&... args)
{
    auto mySize = sizeof(T) * data.size();
    int myAlignment = Alignment(offset, 16); // fixed for vectors of vec4 for now
    UpdateExData(myAlignment, mySize, data.data());
    UpdateEx(myAlignment + mySize, args...);
}

template<typename... Args>
void UpdateEx(int offset, int& data, Args&... args)
{
    auto mySize = sizeof(int);
    int myAlignment = Alignment(offset, mySize); // assume 4 byte alignment for ints
    UpdateExData(myAlignment, mySize, &data);
    UpdateEx(myAlignment + mySize, args...);
}

template<typename... Args>
void UpdateEx(int offset, const glm::mat4& data, Args&... args)
{
    auto mySize = sizeof(glm::mat4);
    int myAlignment = Alignment(offset, 16); // assume 16-byte alignment for mat4
    UpdateExData(myAlignment, mySize, &data);
    UpdateEx(myAlignment + mySize, args...);
}

The line of code that initiates the update is as follows. 启动更新的代码行如下。 m is an integer. m是整数。 cam is glm::mat4. cam是glm :: mat4。 The purpose of this piece is to update the camera in my shaders. 这篇文章的目的是更新着色器中的相机。

cameraUbo->UpdateEx(0, m, cam);

If I flip the uniform around such that the matrix is first, and update the call above to cameraUbo->UpdateEx(0, cam, m) , the matrix updates but renderMode no longer works. 如果我翻转制服以使矩阵为第一个,并将上面的调用更新为cameraUbo->UpdateEx(0, cam, m) ,则矩阵会更新,但renderMode不再有效。

I really have no idea what's wrong and what really confuses me is that GL_UNIFORM_BLOCK_DATA_SIZE returns well beyond the 80 that I expect. 我真的不知道出了什么问题,让我感到困惑的是GL_UNIFORM_BLOCK_DATA_SIZE远远超出我期望的80。 I get different values, above 1000, across the 5 shaders it's in. 我在它的5个着色器中获得了超过1000的不同值。

I do have another uniform that appears to work perfectly, and has the same size across the two shaders in appears in. 我确实有另一件看起来完美的制服,并且在两个着色器中具有相同的尺寸。

struct TowerLight
{
    vec4 position;
    vec4 color;
};

layout(std140) uniform Towers
{
    int lightCount;
    TowerLight lights[MaxLights];
};

With the following code. 使用以下代码。 count is an integer and lights is std::vector<struct_of_2_vec4> . count是一个整数, lightsstd::vector<struct_of_2_vec4>

ubo->UpdateEx(0, towerCount, lights);

[Edit] [编辑]

This might be a bug in my video card driver. 这可能是我的视频卡驱动程序中的错误。 I have a Radeon 6870. If I use the default uniform block layout or drop my shader version to 430 from 440, I get a block size of 80 across all shaders. 我有一个Radeon 6870.如果我使用默认的统一块布局或将我的着色器版本从440中删除到430,我会在所有着色器中获得80的块大小。

This page explains well how alignment works http://learnopengl.com/#!Advanced-OpenGL/Advanced-GLSL 这个页面很好地解释了对齐的工作原理http://learnopengl.com/#!Advanced-OpenGL/Advanced-GLSL

layout (std140) uniform ExampleBlock
{
    //               // base alignment  // aligned offset
    float value;     // 4               // 0 
    vec3 vector;     // 16              // 16  (must be multiple of 16 so 4->16)
    mat4 matrix;     // 16              // 32  (column 0)
                     // 16              // 48  (column 1)
                     // 16              // 64  (column 2)
                     // 16              // 80  (column 3)
    float values[3]; // 16              // 96  (values[0])
                     // 16              // 112 (values[1])
                     // 16              // 128 (values[2])
    bool boolean;    // 4               // 144
    int integer;     // 4               // 148
}; 

Video card driver thing. 显卡驱动器的事情。 Doesn't support Open GL 4.5. 不支持Open GL 4.5。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM