OpenGL计算着色器中输出缓冲区的热填充

gg0vcinb  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(187)

我想在计算着色器中计算一些值,并将它们返回到CPU端的堆分配缓冲区。
我用我的计算着色器发送了一个名为“input_buffer”的数组中的5个浮点数到GPU,我想在该数组中将所有值乘以3和6。
问题是我不能填充我的输出缓冲区,即使我绑定它正确的相应绑定索引在我的计算着色器代码。
这是我的密码--〉

const char* compute_shader = "\n" \
        "#version 430 core\n" \
        "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" \
        "layout(std430, binding = 0) buffer input_layout\n" \
        "{\n" \
        "   float Elements[];\n" \
        "};\n" \
        "layout(std430, binding = 1) buffer output_layout\n" \
        "{\n" \
        "   float Elements2[];\n" \
        "};\n" \
        "void main()\n" \
        "{\n" \
        "   const uint idx = gl_GlobalInvocationID.x;\n" \
        "   Elements2[idx] = Elements[idx] * 3.0f;\n" \
        "   Elements[idx] = Elements[idx] * 6.0f;\n" \
        "}\n" \
        "\n";

    uint32_t shader = CreateShader(compute_shader);
    glUseProgram(shader);

    //int len = width * height;
    int len = 5;
    float* input_buffer = new float[len];
    float* output_buffer = new float[len];

    for (size_t idx = 0; idx < len; idx++)
    {
        input_buffer[idx] = 65.0f;
        output_buffer[idx] = -1001.0f;
    }

    GLuint SSBO;  //Shader Storage Buffer Object
    glGenBuffers(1, &SSBO);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);
    glBufferData(GL_SHADER_STORAGE_BUFFER, len * sizeof(float), (GLvoid*)input_buffer, GL_DYNAMIC_COPY);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, SSBO);

    GLuint SSBO2;
    glGenBuffers(1, &SSBO2);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO2);
    glBufferData(GL_SHADER_STORAGE_BUFFER, len * sizeof(float), (GLvoid*)output_buffer, GL_DYNAMIC_COPY);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, SSBO2);

    glUseProgram(shader);

    glDispatchCompute(len, 1, 1);
    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT);

    float* dummy_out = nullptr;
    dummy_out = (float*)glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_WRITE);
    
    printf("\nInput Buffer: ");
    for (int idx = 0; idx < len; idx++)
    {
        printf("%f ", input_buffer[idx]);
    }
    printf("\n");

    printf("\nOutput Buffer: ");
    for (int idx = 0; idx < len; idx++)
    {
        printf("%f ", output_buffer[idx]);
    }
    printf("\n");

    if (nullptr != dummy_out)
    {
        printf("\nDummy_Output: ");
        for (int idx = 0; idx < len; idx++)
        {
            printf("%f ", dummy_out[idx]);
        }
        printf("\n");
    }

    glDeleteProgram(shader);
    delete[] input_buffer, output_buffer, dummy_out;

输出为--〉

OpenGL Version: 4.3.0 - Build 31.0.101.2114

Input Buffer: 50.000000 50.000000 50.000000 50.000000 50.000000

Output Buffer: -1001.000000 -1001.000000 -1001.000000 -1001.000000 -1001.000000

Dummy_Output: 150.000000 150.000000 150.000000 150.000000 150.000000

为什么我看不到我的缓冲区“output_buffer”的变化?有没有什么方法可以专门填充它?这就是我需要的。
我尝试了其他Glenum标志来获取数据。

wlwcrazw

wlwcrazw1#

你似乎误解了OpenGL中缓冲区的工作原理。缓冲区包含了传递给glBufferData的数组的副本,它们没有在缓冲区和数组之间建立任何连接。因此,当缓冲区被更改时,这些更改不会反映在原始数组中。
如果您希望在CPU端使用GPU生成的数据,则必须使用glGetBufferSubData读回缓冲区内容,例如:

glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO2);
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, len * sizeof(float), (GLvoid*)output_buffer);

另请注意,您可能需要在着色器执行后添加内存屏障,以确保GPU在阅读回内容之前已经完成。

相关问题