Issue with glBindBufferRange() OpenGL 3.1

这篇博客讨论了在OpenGL3.1中遇到的使用glBindBufferRange()绑定 Uniform Buffer Object (UBO) 时出现的错误。问题在于offset值必须是GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT的倍数,而作者尝试直接为每个vec4提供16字节的数据,导致GL_INVALID_VALUE错误。解决方案包括查询UBO的布局和大小,遵循std140布局规则,并确保缓冲区大小和偏移量符合对齐要求。此外,还提醒了在未指定std140布局时,需要查询每个成员的布局信息。

Issue with glBindBufferRange() OpenGL 3.1

My vertex shader is ,

uniform Block1{    vec4 offset_x1;   vec4 offset_x2;}block1;

out float value;

in vec4 position;

void main()
{
    value = block1.offset_x1.x + block1.offset_x2.x;            

    gl_Position = position;
}

The code I am using to pass values is :

GLfloat color_values[8];// contains valid values

glGenBuffers(1,&buffer_object);

glBindBuffer(GL_UNIFORM_BUFFER,buffer_object);

glBufferData(GL_UNIFORM_BUFFER,sizeof(color_values),color_values,GL_STATIC_DRAW);

glUniformBlockBinding(psId,blockIndex,0);

glBindBufferRange(GL_UNIFORM_BUFFER,0,buffer_object,0,16);                                              

glBindBufferRange(GL_UNIFORM_BUFFER,0,buffer_object,16,16);

Here what I am expecting is, to pass 16 bytes for each vec4 uniform. I get GL_INVALID_VALUE error for offset=16 , size = 16. I am confused with offset value. Spec says it is corresponding to "buffer_object".

 

1 Answer

There is an alignment restriction for UBOs when binding. Any glBindBufferRange/Base's offset must be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. This alignment could be anything, so you have to query it before building your array of uniform buffers. That means you can't do it directly in compile-time C++ logic; it has to be runtime logic.

Speaking of querying things at runtime, your code is horribly broken in many other ways. You did not define a layout qualifier for your uniform block; therefore, the default is used: shared. And you cannot use `shared* layout without querying the layout of each block's members from OpenGL. Ever.

If you had done a query, you would have quickly discovered that your uniform block is at least 32 bytes in size, not 16. And since you only provided 16 bytes in your range, undefined behavior (which includes the possibility of program termination) results.

If you want to be able to define C/C++ objects that map exactly to the uniform block definition, you need to use std140 layout and follow the rules of std140's layout in your C/C++ object.

Nicol Bolas

378k5353 gold badges633633 silver badges829829 bronze badges

  • Thanks a lot for the answer ! I wasn't aware about GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. I had already queried my Uniform Block for its size (32 bytes), but I thought by specifying 16 bytes I could supply data for the second "vec4" component of Uniform Block, which I presume is wrong. I think I should treat the second "vec4" component as an individual uniform. Just to add information , if layout is not std140 then offset has to be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. Consequently the bound buffer also has to be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT in size . – maverick9888 Oct 25 '12 at 10:17

  • Cont. - Consequently the bound buffer also has to be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT in size provided we are using a single buffer object to supply data to multiple uniform blocks. – maverick9888 Oct 25 '12 at 10:20

  • "if layout is not std140 then offset has to be a multiple of GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT." No; the offset always must be a multiple of that. std140 layout just means you don't have to query the buffer's size or the offset of any individual uniforms, because you can compute them directly. The buffer can be whatever size you want, but when you bind a range, the offset must be a multiple of that alignment. – Nicol Bolas Oct 25 '12 at 16:59

  • Still a bit confused. Lets say my shader contains 2 uniform blocks: uniform Block1{ vec4 offset_x1; }block1; uniform Block2{ vec4 offset_x3; vec4 offset_x4;}block2; And I want to supply data to both of them using a single buffer object. What will be my glBindBufferRange() call in that case ? Assume I am using std140 layout

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值