添加 >= 2^16 数字时的 OpenGL 缓冲区问题

OpenGL buffer problem when adding >= 2^16 numbers

我在使用 OpenGL 缓冲区时遇到了一些奇怪的困难。我试图将问题缩小到最少的源代码,因此我创建了在每次迭代中递增 FloatBuffer 的每个数字的程序。当我向 FloatBuffer 添加少于 2^16 个浮点数时,一切正常,但是当我添加 >= 2^16 个数字时,数字不会递增并且在每次迭代中保持不变。

渲染器:

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++;
        }
    }

    ...
}

计算缓冲区

#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;
}
glDispatchCompute(numbersCount, 1, 1);

不得分派计算着色器工作组数量超过相应的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,这样在开发过程中很容易发现如此明显的错误。