OpenGL 计算着色器 SSBO

Posted

技术标签:

【中文标题】OpenGL 计算着色器 SSBO【英文标题】:OpenGL Compute Shader SSBO 【发布时间】:2015-08-19 11:45:46 【问题描述】:

我想要一个在输出缓冲区中写入 1 的计算着色器。我编译着色器并将其附加到程序没有问题,然后我调用 glDispatchCompute() 函数并等待直到计算着色器结束。但是当我看到数组时,只有 0。

谁能告诉我错在哪里?

这是我的计算着色器代码:

#version 430 core

layout  (local_size_x  =  2)  in;

layout(std430, binding=0) writeonly buffer Pos
    float Position[];
;

void main()
    Position[gl_GlobalInvocationID.x] = 1.0f;

这是我的一些主要内容:

GLuint program_compute = 0, SSBO = 0;

//...(Create, compile and link the program with the shader)...

vector<GLfloat> initPos;
int num_numeros = 12;

for (int i = 0; i < num_numeros; i++)
    initPos.push_back(0.0f);


glUseProgram(program_compute);

glGenBuffers(1, &SSBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, SSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, num_numeros * sizeof(GLfloat), &initPos, GL_DYNAMIC_DRAW);

glDispatchCompute(num_numeros/2, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);

for (int i = 0; i < num_numeros; i++)
    cout << "p" << i << ": " << initPos[i] <<  endl;

cout << endl;

编辑:终于成功了。谢谢 BDL。

正如 BDL 所说,我忘记了从 GPU 内存中读回缓冲区。现在它起作用了。这是新代码:

GLuint program_compute = 0, SSBO = 0;

// ...The same code as above

glDispatchCompute(num_numeros/2, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);

glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);

GLfloat *ptr;
ptr = (GLfloat *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
initPos.clear();

for (int i = 0; i < num_numeros; i++)
    initPos.push_back(ptr[i]);


glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);

for (int i = 0; i < num_numeros; i++)
    cout << "p" << i << ": " << initPos[i] <<  endl;

cout << endl;

编辑:谢谢 Andon M. Coleman。

我从只写缓冲区读取。这是固定的行:

ptr = (GLfloat *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);

【问题讨论】:

等等...这里有严重问题。您不会将内存映射为只写,然后转身除了读取该内存之外什么都不做。你需要尽快解决这个问题。你应该映射它GL_READ_ONLY;您正在从未定义的内存中读取数据。 【参考方案1】:

glBufferData 复制 initPos 的内容到 SSBO。然后着色器在缓冲区上操作,而不是在 cpu 内存阵列上。除非你在某处将缓冲区从 GPU 读回 CPU 内存,否则 initPos 永远不会改变。

【讨论】:

以上是关于OpenGL 计算着色器 SSBO的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL着色器存储缓冲区/memoryBarrierBuffer

计算着色器不会写入缓冲区

从顶点着色器中修改着色器存储缓冲区对象

opengl ---几何着色器

计算着色器 OpenGL 写入纹理

OpenGL4.3新特性: 计算着色器 Compute Shader