I'm writing a piece of code that will test all data points against a collision volume, using a compute shader. If the point is inside to collision volume it changes the label to 1, otherwise, it remains as 0.
My approach is to have two buffers, one containing all vertices, the other buffer contain all labels in order of the vertices. Then in each workgroup, the compute shader will process the point with index X and set the label at index X accordingly.
However the result is strange, it did change some labels to 1, but not the ones inside the collision box, it scatters around every part of the whole data points...I'm pretty sure the collision detection and bounding boxes passed to the shaders are okay, they work in all other parts of the program with the same format of the points, could it because the execution order of a compute shader workgroup is completely random?
I'm really grateful for anyone that can take a look at it...it has been my nightmare for the past 3 days...
First in my C++ code, I allocated and assigned buffers like this,
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo); // vertices
glGenBuffers(1, &cbo); // colors
glGenBuffers(1, &lbo); // labels
glGenBuffers(1, &ssvbo); // shader storage vbo for compute shader
glGenBuffers(1, &sslbo); // shader storage lbo for compute shader
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssvbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * vertices.size() * 3, &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, sslbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * labels.size(), &labels[0], GL_STATIC_DRAW);
glBindVertexArray(vao);
// Vertices
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size() * 3, &vertices[0], GL_STATIC_DRAW); // xyz
// set attribute for the first argument
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); // pos
glBindBuffer(GL_ARRAY_BUFFER, cbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size() * 3, &colors[0], GL_STATIC_DRAW); // rgb
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); //color
glBindBuffer(GL_ARRAY_BUFFER, lbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * labels.size(), &labels[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_INT, GL_FALSE, sizeof(GLint), (GLvoid*)0); // label
// illustration : 1 1 1 1 1 1 1
// name: |pos | clr | label
// location: | 0 | 1 | 2
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
And this is how I run the compute shader program,
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m->ssvbo);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m->sslbo);
glUseProgram(compute_label_program);
GLint vNormals = glGetUniformLocation(compute_label_program, "normals");
GLint vPts = glGetUniformLocation(compute_label_program, "pts");
glUniform3fv(vNormals, 6, &norms[0].x);
glUniform3fv(vPts, 8, &pt[0].x);
glDispatchCompute(static_cast<int>(m->vertices.size()) / WORK_GROUP_SZ + 1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
// now, assume the above code changed the labels in sslbo, copy the sslbo,ssvbo values back to client
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m->sslbo);
m->labels.clear();
m->labels.resize(m->vertices.size());
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(int) * m->vertices.size(), &m->labels[0]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m->ssvbo);
m->vertices.clear();
m->vertices.resize(m->labels.size());
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(point) * m->vertices.size(), &m->vertices[0]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// re-upload labels buffer
m->UpdateBuffers();
And this is the compute shader code,
#version 430 compatibility
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable
layout (std140, binding = 4) readonly buffer Position
{
vec3 pos[];
};
layout (std140, binding = 5) writeonly buffer Label
{
int label[];
};
layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
uniform vec3 normals[6];
uniform vec3 pts[8];
bool Oobb(in vec3 norms[6], in vec3 pt[8], in vec3 po)
{
// some collision checking code
}
void main()
{
uint gid = gl_GlobalInvocationID.x;
if(Oobb(normals, pts, pos[gid].xyz))
label[gid] = 1;
}