Search code examples
openglbufferfloatbuffer

OpenGL buffer problem when adding >= 2^16 numbers


I'm facing some strange difficulties with OpenGL buffer. I tried to shrunk the problem to the minimum source code, so I created program that increment each number of the FloatBuffer in each iteration. When I am adding less than 2^16 float numbers to the FloatBuffer, everything works just fine, but when I add >= 2^16 numbers, then the numbers are not incrementing and stays the same in each iteration.

Renderer:

public class Renderer extends AbstractRenderer {
    int computeShaderProgram;
    int[] locBuffer = new int[2];
    FloatBuffer data;
    int numbersCount = 65_536, round = 0; // 65_535 - OK, 65_536 - wrong

    @Override
    public void init() {
        computeShaderProgram = ShaderUtils.loadProgram(null, null, null, null, null,
                "/main/computeBuffer");
        glGenBuffers(locBuffer);
        // dataSizeInBytes = count of numbers to sort * (float=4B + padding=3*4B)
        int dataSizeInBytes = numbersCount * (1 + 3) * 4;

        data = ByteBuffer.allocateDirect(dataSizeInBytes)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        initBuffer();
        printBuffer(data);

        glBindBuffer(GL_SHADER_STORAGE_BUFFER, locBuffer[0]);
        glBufferData(GL_SHADER_STORAGE_BUFFER, data, GL_DYNAMIC_DRAW);
        glShaderStorageBlockBinding(computeShaderProgram, 0, 0);

        glViewport(0, 0, width, height);
    }

    private void initBuffer() {
        data.rewind();
        Random r = new Random();
        for (int i = 0; i < numbersCount; i++) {
            data.put(i*4,  r.nextFloat());
        }
    }

    @Override
    public void display() {
        if (round < 5) {
            glUseProgram(computeShaderProgram);
            glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, locBuffer[0]);
            glDispatchCompute(numbersCount, 1, 1);
            glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
            glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, data);
            printBuffer(data);
            round++;
        }
    }

    ...
}

Compute buffer

#version 430
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable

layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

layout(binding = 0) buffer Input {
    float elements[];
}input_data;

void main () {
    input_data.elements[gl_WorkGroupID.x ] = input_data.elements[gl_WorkGroupID.x] + 1;
}

Solution

  • glDispatchCompute(numbersCount, 1, 1);
    

    You must not dispatch a compute shader workgroup count exceeding the corresponding GL_MAX_GL_MAX_COMPUTE_WORK_GROUP_COUNT for each dimension. The spec guarantees that limit to be at least 65535, so it is very likely that you just exceed the limit on your implementation. Actually, you should be getting a GL_INVALID_VALUE error for that call, and you should really consider using a debug context and debug message callback to have such obvious errors easily spotted during development.