在计算着色器中更新 SSBO

Update SSBO in Compute shader

我目前正在尝试将 SSBO linked/bound 更新为 Computeshader。这样做,我只将第一个 32 字节写入 out_picture,因为我只有 memcpy 那么多 (sizeof(pstruct)).

计算着色器:

#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 调用拆分为数组和浮点数?如果是的话怎么办?我可以复制第一部分,但不允许我向 ptr.

添加偏移量

首先,

float picture[1920*1080*3];

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

第二个:

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

这个定义在任何方面都不符合你着色器中的定义。 std::vector 对象只是一个元对象,在内部管理向量使用的数据存储。 memcpy 将其传递给 GL 缓冲区并将其传递给 GPU 根本没有意义。

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