更新 SSBO 内容
Updateing SSBO Contents
我想在计算着色器上做一个简单的计算,在完成一轮计算后,我将该轮的结果作为第二轮的输入返回给着色器。
我的计算着色器看起来像这样:
#version 440 core
layout(std430, binding = 0) buffer Result{
float out_picture[];
};
layout(std430, binding = 1) buffer In_p1{
float in_p1[];
};
layout(local_size_x = 1000) in;
void main() {
in_p1[gl_GlobalInvocationID.x] = 1.0f;
out_picture[gl_GlobalInvocationID.x] = out_picture[gl_GlobalInvocationID.x] + in_p1[gl_GlobalInvocationID.x];
}
她是我的 OpenGL 代码:
int main(int argc, char* argv[]) {
std::vector<float> result_container;
std::vector<SSBO> ssbo_container;
SSBO ssbo_result;
ssbo_result.NUM_PIX = 1920*1080*4;
ssbo_result.WORK_GROUP_SIZE = 1000;
result_container.reserve(ssbo_result.NUM_PIX * sizeof(float));
glGenBuffers(1, &ssbo_result.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo_result.handle);
glBufferData(GL_SHADER_STORAGE_BUFFER, ssbo_result.NUM_PIX * sizeof(float), NULL, GL_DYNAMIC_DRAW);
for(unsigned int i = 1; i < 2; i++){
SSBO ssbo;
glGenBuffers(1, &ssbo.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, ssbo.handle);
glBufferData(GL_SHADER_STORAGE_BUFFER, ssbo_result.NUM_PIX * sizeof(float), NULL, GL_DYNAMIC_DRAW);
ssbo_container.push_back(ssbo);
}
while (!g_win.shouldClose()) {
std::cout << "container:" << result_container[0] << std::endl;
glUseProgram(g_avg_program);
glDispatchCompute(ssbo_result.NUM_PIX / ssbo_result.WORK_GROUP_SIZE, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_result.handle);
GLfloat *ptr = (GLfloat *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
memcpy(result_container.data(), ptr, ssbo_result.NUM_PIX * sizeof(float));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_result.handle);
ptr = (GLfloat *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
memcpy(ptr, result_container.data(), ssbo_result.NUM_PIX * sizeof(float));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
g_win.update();
if (glfwGetKey(g_win.getGLFWwindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS) {
g_win.stop();
}
}
return 0;
}
初始化 ssbo 并调用 glDispatchCompute()
和 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)
后,我读出结果并将其保存在 std::vector<float>result_container
中。这将按照预期为第一个 运行、ssbo_result.handle
发送我的 out_picture
ssbo
用 1.0f 填充容器
然后我尝试将结果作为输入反馈回 out_picture
,就像我通过翻转 memcpy dest 和 source 从中读取数据一样,据我所知,我现在有了我的out_picture
GPU 内存
中的先前结果
如您所见,我正在尝试向 out_picture
添加一个值(此处为 1.0f),并将其作为输入反馈回 out_picture
以进行下一次计算。想法是将结果添加为下一个 运行 的输入。
我尝试对 glCopyBufferSubData
做同样的事情,结果相同。每次只输出 1.0 而不是 1, 2, 3 ...
在while循环中0绑定到绑定点0,计算着色器启动后:
while (!g_win.shouldClose()) {
....
glDispatchCompute(ssbo_result.NUM_PIX / ssbo_result.WORK_GROUP_SIZE, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
....
}
但 ssbo_result.handle
再也不会绑定到绑定点 0。这导致计算仅在循环的第一个循环中运行,因为在循环的后续循环中与着色器存储缓冲区的绑定被破坏。
打破缓冲区的绑定是完全多余的,因为绑定点没有用于任何其他用途。
删除循环中的glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
行,问题解决。 (当然,在 while
循环开始时连续绑定缓冲区,也可以完成这项工作 - 在 glDispatchCompute
之前添加 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo_result.handle);
)
我想在计算着色器上做一个简单的计算,在完成一轮计算后,我将该轮的结果作为第二轮的输入返回给着色器。
我的计算着色器看起来像这样:
#version 440 core
layout(std430, binding = 0) buffer Result{
float out_picture[];
};
layout(std430, binding = 1) buffer In_p1{
float in_p1[];
};
layout(local_size_x = 1000) in;
void main() {
in_p1[gl_GlobalInvocationID.x] = 1.0f;
out_picture[gl_GlobalInvocationID.x] = out_picture[gl_GlobalInvocationID.x] + in_p1[gl_GlobalInvocationID.x];
}
她是我的 OpenGL 代码:
int main(int argc, char* argv[]) {
std::vector<float> result_container;
std::vector<SSBO> ssbo_container;
SSBO ssbo_result;
ssbo_result.NUM_PIX = 1920*1080*4;
ssbo_result.WORK_GROUP_SIZE = 1000;
result_container.reserve(ssbo_result.NUM_PIX * sizeof(float));
glGenBuffers(1, &ssbo_result.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo_result.handle);
glBufferData(GL_SHADER_STORAGE_BUFFER, ssbo_result.NUM_PIX * sizeof(float), NULL, GL_DYNAMIC_DRAW);
for(unsigned int i = 1; i < 2; i++){
SSBO ssbo;
glGenBuffers(1, &ssbo.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, ssbo.handle);
glBufferData(GL_SHADER_STORAGE_BUFFER, ssbo_result.NUM_PIX * sizeof(float), NULL, GL_DYNAMIC_DRAW);
ssbo_container.push_back(ssbo);
}
while (!g_win.shouldClose()) {
std::cout << "container:" << result_container[0] << std::endl;
glUseProgram(g_avg_program);
glDispatchCompute(ssbo_result.NUM_PIX / ssbo_result.WORK_GROUP_SIZE, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_result.handle);
GLfloat *ptr = (GLfloat *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
memcpy(result_container.data(), ptr, ssbo_result.NUM_PIX * sizeof(float));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_result.handle);
ptr = (GLfloat *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
memcpy(ptr, result_container.data(), ssbo_result.NUM_PIX * sizeof(float));
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
g_win.update();
if (glfwGetKey(g_win.getGLFWwindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS) {
g_win.stop();
}
}
return 0;
}
初始化 ssbo 并调用 glDispatchCompute()
和 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)
后,我读出结果并将其保存在 std::vector<float>result_container
中。这将按照预期为第一个 运行、ssbo_result.handle
发送我的 out_picture
ssbo
然后我尝试将结果作为输入反馈回 out_picture
,就像我通过翻转 memcpy dest 和 source 从中读取数据一样,据我所知,我现在有了我的out_picture
GPU 内存
如您所见,我正在尝试向 out_picture
添加一个值(此处为 1.0f),并将其作为输入反馈回 out_picture
以进行下一次计算。想法是将结果添加为下一个 运行 的输入。
我尝试对 glCopyBufferSubData
做同样的事情,结果相同。每次只输出 1.0 而不是 1, 2, 3 ...
在while循环中0绑定到绑定点0,计算着色器启动后:
while (!g_win.shouldClose()) {
....
glDispatchCompute(ssbo_result.NUM_PIX / ssbo_result.WORK_GROUP_SIZE, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
....
}
但 ssbo_result.handle
再也不会绑定到绑定点 0。这导致计算仅在循环的第一个循环中运行,因为在循环的后续循环中与着色器存储缓冲区的绑定被破坏。
打破缓冲区的绑定是完全多余的,因为绑定点没有用于任何其他用途。
删除循环中的glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
行,问题解决。 (当然,在 while
循环开始时连续绑定缓冲区,也可以完成这项工作 - 在 glDispatchCompute
之前添加 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo_result.handle);
)