You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GLSL Compute Shader未修改缓冲区问题求助

问题:Compute Shader未修改目标缓冲区(WSL+Mesa环境)

环境说明

  • 开发库:OpenGL、GLFW、GLEW、GLM
  • 运行环境:Windows子系统(WSL)搭配Mesa
  • 硬件:NVIDIA 4060 Ti(驱动为最新版本)
  • 现象:编写的Compute Shader未按预期修改目标缓冲区,读取到的是随机垃圾值(或全零、NaN)

完整代码

主文件与glew.c放在src目录,GLM置于include目录:

#include <iostream>
#include <cstring>
#include <GLFW/glfw3.h>
#include "glm.hpp"
#include <GL/gl.h>

int main(int argc, char **argv) {
    //Window width and height
    int window_w = 640, window_h = 480;

    printf("Startup\n");

    //Init and create window
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, false);
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
    std::cout << "Trying to create window" << std::endl;
    GLFWwindow* window = glfwCreateWindow(window_w, window_h, "Marching Cubes", nullptr, nullptr);
    std::cout << "Just tried to create window\n" << std::endl;

    if (window == nullptr)
    {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    else {
        std::cerr << "Succeeded at creating window" << std::endl;
    }

    //More init
    glfwMakeContextCurrent(window);
    printf("Made the window the current context\n");

    glEnable              ( GL_DEBUG_OUTPUT );

    glewInit();

    // The buffer for use in the compute shader
    uint32_t buffer_vertices;
    uint32_t buffer_size = 10;

    glCreateBuffers(1, &buffer_vertices);
    glNamedBufferStorage(buffer_vertices, buffer_size, nullptr, GL_DYNAMIC_STORAGE_BIT);

    printf("Buffers have been created\n");

    // Create the VAO for drawing the resulting triangles
    uint32_t vao_draw;
    glCreateVertexArrays(1, &vao_draw);

    glEnableVertexArrayAttrib(vao_draw, 0);
    glEnableVertexArrayAttrib(vao_draw, 1);

    glVertexArrayVertexBuffer(vao_draw, 0, buffer_vertices, 0, sizeof(glm::vec4));
      
    glVertexArrayAttribFormat(vao_draw, 0, 4, GL_FLOAT, false, 0);
    glVertexArrayAttribFormat(vao_draw, 1, 4, GL_FLOAT, false, 0);
       
    glVertexArrayAttribBinding(vao_draw, 0, 0);
    glVertexArrayAttribBinding(vao_draw, 1, 1);

    std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;

    glClearColor(1.0, 1.0, 1.0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBegin(GL_TRIANGLES);

    // The compute shader
    char* smcsource = "\
#version 430\n\
\n\
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n\
\n\
layout(std430, binding = 0) buffer u_buffer_vertices\n\
{\n\
    vec4 output_vertices[];\n\
};\n\
\n\
\n\
void main() {\n\
    for (float i = 0.0; i < 10.0; i++) output_vertices[int(i)] = vec4(i,i,i,i);\n\
}\n\
";

    //Compile the shader
    GLint length = strlen(smcsource);
    GLuint compute_shader = glCreateShader(GL_COMPUTE_SHADER);
    glShaderSource(compute_shader, 1, &smcsource, &length);
    glCompileShader(compute_shader);
    GLint smcsuccess = 0;
    glGetShaderiv(compute_shader, GL_COMPILE_STATUS, &smcsuccess);
    GLuint smcprogram;
    if (smcsuccess) {
        printf("Successfully compiled\n");
        smcprogram = glCreateProgram();
        glAttachShader(smcprogram, compute_shader);
        glLinkProgram(smcprogram);
        GLint TotalLength = 0;
        glGetShaderiv(compute_shader, GL_INFO_LOG_LENGTH, &TotalLength);
        std::string logs;
        logs.resize(TotalLength);
        glGetShaderInfoLog(compute_shader, TotalLength, NULL, &logs[0]);
        std::cout << "Shader output log:\n" << logs << std::endl;
    }
    else {
        printf("Failed compile\n");
        GLint TotalLength = 0;
        glGetShaderiv(compute_shader, GL_INFO_LOG_LENGTH, &TotalLength);
        std::string logs;
        logs.resize(TotalLength);
        glGetShaderInfoLog(compute_shader, TotalLength, NULL, &logs[0]);
        std::cout << "Shader output log:\n" << logs << std::endl;
    }

    //Select shader
    glUseProgram(smcprogram);

    //Bind buffer
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer_vertices);
    printf("Buffer binded\n");

    //Run shader. Problem happens here: nothing happens to the buffer when I run this
    glDispatchCompute(1, 1, 1);
    glMemoryBarrier(GL_ALL_BARRIER_BITS);

    //Test and print the buffer data
    //If this is working as intended, it should count up in groups of four, something like:
    //0.0 0.0 0.0 0.0 | 1.0 1.0 1.0 1.0 | 2.0 2.0 2.0 2.0 | 3.0 3.0 3.0 3.0 | etc.
    glm::vec4 vertices[16];
    glGetBufferSubData(buffer_vertices, 0, 16, &vertices);
    printf("Vertex data after: ");
    for (int i = 0; i < 10; i++)
        printf("%f %f %f %f | ", vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]);
    printf("\n");

    glEnd();
    glfwSwapBuffers(window);

    return 0;
}

编译命令

g++ src/main.cpp src/glew.c -Iinclude -lGLEW -lglut -lglfw -lGL -lX11 -lc -o shader-compiler-bug

预期输出

0.0 0.0 0.0 0.0 | 1.0 1.0 1.0 1.0 | 2.0 2.0 2.0 2.0 | 3.0 3.0 3.0 3.0 | [以此类推到第10组]

实际输出

每次运行结果不同,多为随机垃圾值,示例:

-11653242706460672.000000 0.000000 0.000000 0.000000 | -496068722688.000000 0.000000 -496183017472.000000 0.000000 | -496015245312.000000 0.000000 -496055091200.000000 0.000000 | -496050896896.000000 0.000000 -496059285504.000000 0.000000 | -496066625536.000000 0.000000 -447767117824.000000 0.000000 | 0.000000 0.000000 0.000000 -0.000000 | 0.000000 0.000000 0.000000 0.000000 | 0.000000 0.000000 0.000000 0.000000 | 0.000000 0.000000 0.000000 0.000000 | -496055091200.000000 0.000000 -496025731072.000000 0.000000 |

内容的提问来源于stack exchange,提问作者kronosta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:45:58