均匀的缓冲阵列元素不正确

Uniform buffered array elements are incorrect

本文关键字:元素 不正确 阵列 缓冲      更新时间:2023-10-16

我一直在使用gl3.3编写一些统一缓冲区的东西,并使用其中的信息来选择碎片着色器中的精灵瓷砖。它正在使用NVIDIA GTX780,在我的桌面上工作,但是我的基于AMD的笔记本电脑(A6-44555M)有一些问题。两者都是最新(或最近)的驱动程序。

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

前两个UINT没有问题。我还在着色器中有一些可读的数组,只有一个问题。数据乘以四个!目前,数组只是一些测试数据,初始化为其索引,因此SpriteArr [1] == 1,SpriteArr [34] == 34等。但是,在着色器中访问它,Spritearr [10]给出40。这一直到Spritearr [143] == 572。我不知道为什么这是什么,但这似乎是不正确的偏移。

我使用的是共享统一的布局,并从GL本身中获得统一的偏移,因此它们应该是正确的。我确实注意到AMD卡上的偏移量要大得多,就好像它增加了更多的填充。它们在桌面上总是0,4,8,但笔记本电脑上的0,16,32。

如果有任何区别,则有另一个UBO(绑定点0),用于视图和投影矩阵。这些工作原本。但是,它不在片段着色器中使用。它也是在此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数组的方式吗?

为什么AMD驱动程序处理此操作如此不同?

因为那是您要的:

layout (shared) uniform SpriteMatchData

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

当您对值查询值时,您进行了不是查询数组步幅:字节偏移数组中元素的字节偏移。规范中没有任何要求shared布局紧密包装数组。

实际上,几乎没有理由不使用std140布局。您可以避免对偏移的所有查询,并简单地设计C 结构,这些结构可以由GLSL直接消费。