我的计算着色器没有任何外部效果

问题描述 投票:0回答:1

我正在尝试使用 OpenGL、GLFW、GLEW 和 GLM 在 GLSL 中编写计算着色器。问题在于计算着色器未运行或未修改任何缓冲区。我有最新的 NVIDIA 4060 Ti 驱动程序,并且正在使用 Mesa 在 Windows 上开发 WSL。

代码(这个和glew.c(我知道,hacky)进入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 = "\n\
#version 430\n\
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n\
layout(std430, binding = 0) buffer u_buffer_vertices\n\
{\n\
    vec4 output_vertices[];\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 | [etc. to 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 |

(虽然每次都不同,有些尝试全是零或输出中有 NaN)

c++ opengl glsl compute-shader shader-storage-buffer
1个回答
0
投票

几个问题:

  • glBegin()
    /
    glEnd()
    在核心环境中不起作用;删除它们。

  • size
    glNamedBufferStorage()
    参数以字节为单位,而不是元素。 因此,您不仅需要
    buffer_size
    ,还需要
    buffer_size * sizeof(glm::vec4)
    :

    glNamedBufferStorage(buffer_vertices, buffer_size * sizeof(glm::vec4), nullptr, GL_DYNAMIC_STORAGE_BIT);
    
  • glGetBufferSubData()
    调用的参数使您看起来像是打算使用
    glNamedBufferStorage()
    ;它还受到以前的字节与元素问题的困扰。 更正:

    glGetNamedBufferSubData(buffer_vertices, 0, buffer_size * sizeof(glm::vec4), &vertices);
    

一起(对GLAD转换表示歉意,这是我手头的东西):

#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
#include <iostream>

void CheckStatus( GLuint obj, bool isShader )
{
    GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
    ( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
    if( status == GL_TRUE ) return;
    ( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
    std::cerr << (GLchar*)log << "\n";
    std::exit( EXIT_FAILURE );
}

void AttachShader( GLuint program, GLenum type, const char* src )
{
    GLuint shader = glCreateShader( type );
    glShaderSource( shader, 1, &src, NULL );
    glCompileShader( shader );
    CheckStatus( shader, true );
    glAttachShader( program, shader );
    glDeleteShader( shader );
}

const char* const comp = R"GLSL(
#version 430
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(std430, binding = 0) buffer u_buffer_vertices
{
    vec4 output_vertices[];
};

void main() {
    for (float i = 0.0; i < 10.0; i++) {
        output_vertices[int(i)] = vec4(i,i,i,i);
    }
}
)GLSL";

int main( int, char** )
{
    glfwSetErrorCallback( []( int, const char* desc ) { std::cerr << desc << "\n"; std::exit( EXIT_FAILURE ); } );

    glfwInit();
    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 6 );
    glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE );
    glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
    GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
    glfwMakeContextCurrent( window );
    gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress );

    GLuint prog = glCreateProgram();
    AttachShader( prog, GL_COMPUTE_SHADER, comp );
    glLinkProgram( prog );
    CheckStatus( prog, false );
    glUseProgram( prog );

    // 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 * sizeof(glm::vec4), nullptr, GL_DYNAMIC_STORAGE_BIT);

    //Bind buffer
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer_vertices);

    //Run shader.
    glDispatchCompute(1, 1, 1);
    glMemoryBarrier(GL_ALL_BARRIER_BITS);

    glm::vec4 vertices[10];
    glGetNamedBufferSubData(buffer_vertices, 0, buffer_size * sizeof(glm::vec4), &vertices);

    printf("Vertex data after: \n");
    for (int i = 0; i < 10; i++)
        printf("%f %f %f %f \n", vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]);
    printf("\n");

    glfwTerminate();
    return 0;
}

输出:

Vertex data after:
0.000000 0.000000 0.000000 0.000000
1.000000 1.000000 1.000000 1.000000
2.000000 2.000000 2.000000 2.000000
3.000000 3.000000 3.000000 3.000000
4.000000 4.000000 4.000000 4.000000
5.000000 5.000000 5.000000 5.000000
6.000000 6.000000 6.000000 6.000000
7.000000 7.000000 7.000000 7.000000
8.000000 8.000000 8.000000 8.000000
9.000000 9.000000 9.000000 9.000000
© www.soinside.com 2019 - 2024. All rights reserved.