C++ 如何使用着色器存储缓冲区和std430建立glBindBufferRange()偏移量?

C++ 如何使用着色器存储缓冲区和std430建立glBindBufferRange()偏移量?,c++,opengl,C++,Opengl,我想在ssbo数据之间切换,以绘制具有不同设置的东西。为了实现这一点,我需要使用带有适当偏移量的glBindBufferRange()。 我已经了解到,ubo的偏移量需要是GL\u UNIFORM\u BUFFER\u offset\u ALIGNMENT的倍数,但由于使用std430而不是std140,ssbo的情况可能会发生变化 我试着用最简单的方法做这件事 struct-Color { 浮子r,g,b,a; }; 结构V2 { 浮动x,y; }; 结构统一 { 颜色c1; 颜色c2; v2

我想在ssbo数据之间切换,以绘制具有不同设置的东西。为了实现这一点,我需要使用带有适当偏移量的
glBindBufferRange()
。 我已经了解到,ubo的偏移量需要是
GL\u UNIFORM\u BUFFER\u offset\u ALIGNMENT
的倍数,但由于使用std430而不是std140,ssbo的情况可能会发生变化

我试着用最简单的方法做这件事

struct-Color
{
浮子r,g,b,a;
};
结构V2
{
浮动x,y;
};
结构统一
{
颜色c1;
颜色c2;
v2v2;
浮子r;
浮动f;
int t;
};
GLuint-ssbo=0;
std::矢量均匀;
int main()
{
//创建窗口、上下文等。
glCreateBuffers(1和ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER,ssbo);
均匀u;
u、 c1={255,0,255,255};
u、 c2={255,0,255,255};
u、 v2={0.0f,0.0f};
u、 r=0.0f;
u、 f=100.0f;
u、 t=0;
制服。向后推(u);
u、 c1={255,255,0255};
u、 c2={255,255,0255};
u、 v2={0.0f,0.0f};
u、 r=100.0f;
u、 f=100.0f;
u、 t=1;
制服。向后推(u);
u、 c1={255,0,0,255};
u、 c2={255,0,0,255};
u、 v2={0.0f,0.0f};
u、 r=100.0f;
u、 f=0.0f;
u、 t=0;
制服。向后推(u);
glNamedBufferData(ssbo,sizeof(Uniform)*Uniform.size(),Uniform.data(),GL\u STREAM\u DRAW);
对于(int i=0;i
#版本460核心
布局(位置=0)输出vec4 f_颜色;
布局(std430,绑定=1)缓冲区Unif
{
vec4-c1;
vec4-c2;
vec2v2;
浮子r;
浮动f;
int t;
};
void main()
{       
f_color=vec4(t,0,0,1);
}
当然有vao、vbo、顶点结构等,但它们不影响ssbo

但我得到了
GL\u无效\u值
glBindBufferRange()
错误。这必须来自偏移量,因为我的下一次尝试传输数据,但顺序错误

我的下一个尝试是使用
GL\u着色器\u存储\u缓冲区\u偏移量\u对齐
还有我在网上找到的一个公式

int align=4;
glGetIntegerv(GL_着色器_存储_缓冲区_偏移量_对齐和对齐);
int-ssboSize=sizeof(统一)+align-sizeof(统一)%align;
所以只要更改
glNamedBufferData
glBindBufferRange
就可以了

glNamedBufferData(ssbo,ssboSize*uniform.size(),uniform.data(),GL\u STREAM\u DRAW);
glBindBufferRange(GL_SHADER_STORAGE_BUFFER,1,ssbo,ssboSize*i,sizeof(统一));
这样,它几乎成功了。如您所见,
t
s是

0;
1;
0;
所以opengl应该用颜色绘制3个形状-

vec4(0,0,0,1);
vec4(1,0,0,1);
vec4(0,0,0,1);
它把他们拉错了顺序

vec4(1,0,0,1);
vec4(0,0,0,1);
vec4(0,0,0,1);
如何使其以正确的方式传输数据?

在“6.1.1将缓冲区对象绑定到索引目标点”一节中,陈述了以下内容,重新评估了
glBindBufferRange
的错误条件:

  • 如果
    buffer
    无效,则
    BindBufferRange
    会生成
    无效\u值
    错误 如第6.7.1节所述,非零
    偏移量
    大小
    分别不满足指定目标参数的约束条件。
第6.7.1节“索引缓冲区对象限制和绑定查询”说明SSBO:

  • 开始偏移量:
    SHADER\u STORAGE\u BUFFER\u START
  • 偏移限制:着色器存储缓冲区偏移对齐值的倍数
  • 绑定大小
    SHADER\u存储\u缓冲\u大小
根据表23.64“依赖于实现的聚合着色器限制”:

256[带有以下脚注]:着色器存储缓冲偏移对齐的值是允许的最大值,而不是最小值


因此,如果偏移量不是256的倍数(事实并非如此),那么这段代码根本无法保证工作。您可以根据正在运行的实现查询实际限制,并相应地调整缓冲区内容,但您必须做好准备,使其高达256字节。

我最终使用了
结构对齐(128)统一
。我想我的下一个目标是不要使用硬编码对齐。

您的代码非常混乱。您将SSBO绑定到绑定索引1,但着色器说它应该来自索引3。你说你正在渲染一些东西,但是你的着色器从来没有实际写入过
gl\u位置
,所以它不可能绘制任何东西(它可以进行变换反馈,但不可能进行光栅化)。基本上,这段代码有很多错误,在我们讨论SSBO问题之前,你需要把它提高到一个水平。是的,索引只是一个复制粘贴错误。已经修好了。着色器从不写入
gl\u位置
,因为它是片段着色器,并且写入
f\u颜色
。添加更多的代码,如顶点着色器、vao、vbo等,会使我无法发布它,因为代码多于描述。
glGetIntegerv(GL\u着色器\u存储\u缓冲区\u偏移量\u对齐,&align)为我返回32。我误解了什么吗?是的。您忽略了“着色器、存储、缓冲、偏移和对齐的倍数”部分。52不是32的倍数。因此,如果我将结构填充为64,它将正常工作?对于您的特定实现:是。关于另一个实现:不能保证工作。我如何能够独立于实现?