在计算着色器中更新SSBO

时间:2018-08-23 17:54:10

标签: opengl glsl shader compute-shader

我当前正在尝试更新链接/绑定到Computeshader的SSBO。这样,我只将前32个字节写入out_picture,因为我只memcpy个那么多(sizeof(pstruct))。

Computeshader:

#version 440 core

struct Pstruct{
  float picture[1920*1080*3];
  float factor;
};

layout(std430, binding = 0) buffer Result{
  float out_picture[];
};
layout(std430, binding = 1) buffer In_p1{
  Pstruct in_p1;
};
layout(local_size_x = 1000) in;

void main() {

    out_picture[gl_GlobalInvocationID.x] = out_picture[gl_GlobalInvocationID.x]  +
                                           in_p1.picture[gl_GlobalInvocationID.x] * in_p1.factor;

}

GLSL:

struct Pstruct{
   std::vector<float> picture;
   float factor;
};

Pstruct tmp;
tmp.factor = 1.0f;
for(int i = 0; i < getNUM_PIX(); i++){
   tmp.picture.push_back(5.0f);
}

SSBO ssbo;
glGenBuffers(1, &ssbo.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo.handle);
glBufferData(GL_SHADER_STORAGE_BUFFER, (getNUM_PIX() + 1) * sizeof(float), NULL, GL_DYNAMIC_DRAW);

...

glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo.handle);
Pstruct* ptr = (Pstruct *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
memcpy(ptr, &pstruct, sizeof(pstruct));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);

...

glUseProgram(program);
glDispatchCompute(getNUM_PIX() / getWORK_GROUP_SIZE(), 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

如何同时复制picture arrayfloat factor? 我是否必须将memcpy调用拆分为array和float?如果是的话如何?我可以复制第一部分,但是不允许向ptr添加偏移量。

1 个答案:

答案 0 :(得分:1)

首先

float picture[1920*1080*3];
显然,

应该是纹理(无论如何也只能从中读取)或至少是图像。

第二:

struct Pstruct{
   std::vector<float> picture;
   float factor;
};

此定义与着色器中的定义完全不匹配。 std::vector对象将只是内部管理矢量使用的数据存储的元对象。 memcpy传递给GL缓冲区并将其传递给GPU根本没有任何意义。

正确的方法是将向量的 contents 分别复制到缓冲区内的适当位置,或者只给我们一个客户端上的结构定义,该定义实际上与您的结构匹配在着色器中重新使用(并考虑std430的所有规则)。但是,正如我首先提到的那样,这里的正确解决方案最有可能使用纹理或图像对象代替。