c++ - 统一缓冲数组元素不正确

标签 c++ opengl buffer

我一直在使用 GL3.3 编写一些东西,它采用统一缓冲区,并使用其中的信息在碎片着色器中选择 Sprite 图 block 。它在我的台式机上运行,​​配备 Nvidia GTX780,但我基于 AMD 的笔记本电脑 (A6-4455M) 存在一些问题。两者都是最新的(或非常新的)驱动程序。

回到代码,它首先设置了一个统一的缓冲区,它由两个uint和一个uint数组组成。然后它们被填充,并在着色器中访问。起初我在笔记本电脑上遇到了 GL 错误,因为我没有分配足够的内存,但是考虑到填充的临时更改已经解决了这个问题,现在数据实际上正在缓冲。

前两个单位没有问题。我还在着色器中得到了一些可读的数组,只有一个问题;数据乘以四!目前数组只是一些测试数据,初始化为它的索引,所以 spriteArr[1] == 1,spriteArr[34] == 34,等等。但是,在着色器中访问它,spriteArr[10] 给出 40。这一直到 spriteArr[143] == 572。除此之外还有其他东西。我不知道这是为什么,但它似乎是一个不正确的偏移量。

我正在使用共享统一布局,并从 GL 本身获取统一偏移量,因此它们应该是正确的。我确实注意到 AMD 卡上的偏移量要大得多,就好像它在添加更多的填充一样。它们在台式机上始终为 0、4、8,但在笔记本电脑上始终为 0、16、32。

如果有什么不同,还有另一个 UBO(绑定(bind)点 0),用于 View 和投影矩阵。这些按预期工作。但是它不在片段着色器中使用。它也是在这个 UBO 之前创建的。

UBO初始化代码:

GLuint spriteUBO;
glGenBuffers(1, &spriteUBO);
glBindBuffer(GL_UNIFORM_BUFFER, spriteUBO);
unsigned maxsize = (2 + 576 + 24) * sizeof(GLuint);
/*Bad I know, but temporary. AMD's driver adds 24 bytes of padding. Nvidias has none.
 Not the cause of this problem. At least ensures we have enough allocated. */

glBufferData(GL_UNIFORM_BUFFER, maxsize, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
//Set binding point
GLuint spriteUBOIndex = glGetUniformBlockIndex(programID, "SpriteMatchData");
glUniformBlockBinding(programID, spriteUBOIndex, 1);


static const GLchar *unames[] = 
{
    "width", "height", 
    //"size", 
    "spriteArr"
};

GLuint uindices[3];
GLint offsets[3];
glGetUniformIndices(programID,3,unames,uindices);
glGetActiveUniformsiv(programID, 3, uindices, GL_UNIFORM_OFFSET, offsets);

//buffer stuff
glBindBufferBase(GL_UNIFORM_BUFFER, 1, spriteUBO);
glBufferSubData(GL_UNIFORM_BUFFER,offsets[0], sizeof(GLuint), tm.getWidth());
glBufferSubData(GL_UNIFORM_BUFFER, offsets[1], sizeof(GLuint), tm.getHeight());
glBufferSubData(GL_UNIFORM_BUFFER, offsets[2], tm.getTileCount() * sizeof(GLuint), tm.getSpriteArray());

片段着色器:

layout (shared) uniform SpriteMatchData{
uint width, height;
uint spriteArr[576];};

然后我用这样的数组来试验:

if(spriteArr[10] == uint(40))
{
debug_colour = vec4(0.0,1.0,0.0,0.0);//green
}
else
{
debug_colour = vec4(1.0,0.0,0.0,0.0); //red
}

在这种情况下,debug_colour 变为绿色。

有没有什么办法可以用同时适用于这两个系统的东西来解决这个问题?为什么 AMD 驱动程序的处理方式如此不同?这可能是它处理统一 uint 数组的方式的错误吗?

最佳答案

Why is the AMD driver handling this so differently?

因为那是你要求的:

layout (shared) uniform SpriteMatchData

您明确要求使用共享 布局。该布局是实现定义的。因此,允许两种不同的实现方式为您提供两种不同的布局。因此,如果您想以平台无关的方式使用 SpriteMatchData,您必须在链接后从程序中查询其布局。

虽然您查询了值的偏移量,但您没有查询数组跨度:数组中元素到元素的字节偏移量。规范中没有任何内容要求共享布局紧密打包数组。

实际上,几乎没有理由不使用 std140 布局。您可以避免所有这些偏移量查询,而只需设计可由 GLSL 直接使用的 C++ 结构。

关于c++ - 统一缓冲数组元素不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37925587/

相关文章:

c++ - LPBYTE 宏在编译时生成错误 - C++

java - LibGDX 相机平滑翻译

c - 在 OpenGL 中处理文件

javascript - 从文件中获取 4 个字节并将其转换为时间戳

c++ - 如何获得两个数组的交集

c++ - 如何将 MJPEG 解码为原始 RGB(或 YUV)数据

你能帮忙解释一下这个缓冲区逻辑是如何工作的吗

Java - 将 int 转换为 4 字节的字节数组?

android - 如何从 Android 中 native 编译的 C++ 二进制文件访问相机

java - LWJGL Javadoc 及其描述?