Hello.
I'm having problems with a compute shader. It seems like the compute shader is randomly run more than once, which screws up my test shader. Note that I'm using Java, so the syntax of some commands (glMapBufferRange() for example) are slightly different.
I have a persistently mapped coherent buffer which I use for uploads and downloads:
buffer = glGenBuffers();
glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
glBufferStorage(GL_SHADER_STORAGE_BUFFER, BUFFER_LENGTH * ATTRIBUTE_SIZE, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
mappedBuffer = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, BUFFER_LENGTH * ATTRIBUTE_SIZE, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT, null);
The buffer length is 16 and attribute size is 4, to fit 16 integers.
Each frame, the buffer is initialized to all 0:
//Reset persistent buffer to 0
int total = 0;
for(int i = 0; i < BUFFER_LENGTH; i++){
int v = 0;
mappedBuffer.putInt(v);
total += v;
}
System.out.println("Before: " + total); //prints 0
mappedBuffer.clear(); //Resets the Java ByteBuffer wrapper around the pointer
I then run my compute shader:
//Add 1 to first 8 values in buffer.
computeShader.bind();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
glDispatchCompute(1, 1, 1);
I wait for the GPU to finish running the shader.
//Wait for the GPU to finish running the compute shader
GLSync syncObject = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glClientWaitSync(syncObject, GL_SYNC_FLUSH_COMMANDS_BIT, 1000*1000*1000);
glFinish(); //Should not be needed, but there just in case for now.
And finally I read back the data:
//Read back result from persistent buffer
System.out.println("Result:");
total = 0;
for(int i = 0; i < BUFFER_LENGTH; i++){
int v = mappedBuffer.getInt();
total += v;
System.out.println(v); //Print value
}
System.out.println("After: " + total);
mappedBuffer.clear(); //Reset Java wrapper around pointer
And here's my compute shader:
#version 430
layout (binding = 0, rgba16f) uniform image2D img;
layout(std430, binding = 0) buffer Data{
int data[];
} dataBuffer;
layout (local_size_x = 16, local_size_y = 1, local_size_z = 1) in;
void main(){
int offset = int(gl_GlobalInvocationID.x);
//int offset = int(gl_WorkGroupSize.x * gl_WorkGroupID.x + gl_LocalInvocationID.x);
if(offset < 8){
//dataBuffer.data[offset]++;
atomicAdd(dataBuffer.data[offset], 1);
}
}
The result is a buffer which 99% of the time contains the value 2 instead of 1!!!
Before: 0
Result:2222222200000000After: 16Before: 0Result:2222222200000000After: 16Before: 0Result:1111111100000000After: 8Before: 0Result:1111111100000000After: 8
This randomly occurs regardless of if the shader uses an atomicAdd() or not. It seems like the compute shader is actually run twice for each element in the buffer instead of once, but I see no possible way of how this could happen. What is going on?!