Reputation: 57
I am trying to do a simple calculation on a Compute Shader, where after doing one round of computation I give the result of that round back to the Shader as an Input for the second round.
My Compute shader looks like this:
#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];
}
Her is my OpenGL code:
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;
}
After initializing the ssbo's and calling glDispatchCompute()
and glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)
I read out the result and saving it in std::vector<float>result_container
. This fills the container with 1.0f as expected for the first run, ssbo_result.handle
beeing my out_picture
ssbo
I then try feeding the result back in as an input into out_picture
the same way I read the data out of it by just flipping the memcpy dest and source, as I understand it that I now have my previous result in the out_picture
GPU Memory
As you can see I am trying to add a value (here 1.0f) to the out_picture
and feed it back as an input into out_picture
for the next computation. The Idea is to just add the result as an input for the next run.
I tryed doing the same with glCopyBufferSubData
with the same outcome. Only 1.0 as output everytime instead of a 1, 2, 3 ...
Upvotes: 2
Views: 1212
Reputation: 210998
In the while loop 0 is bound to the binding point 0, after the compute shader was launched:
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);
....
}
but ssbo_result.handle
is never bound to the binding point 0 again. This causes that the computation operates only in the first cycle of the loop, because the binding to the shader storage buffer is broken in the further cycles of the loop.
It is completely superfluous to break the binding of the buffer, since the binding point is not used for anything else.
Delete the line glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
in the loop, to solve the issue. (Of course binding the buffer continuously at the begin of the while
loop, would do the job, too - add glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo_result.handle);
before glDispatchCompute
)
Upvotes: 1