未能专门化使用螺旋的OpenGl着色器

ycggw6v2  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(117)

我试图编译glsl着色器到spirv使用glslang,编译过程工作正常。但是由于某些原因,glSpecializeShader使整个应用程序崩溃,我查看了glShaderBinary顶点着色器的GL_COMPILE_STATUS,看起来它失败了。不知道为什么会失败。
也许我做错了什么?
代码:

#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <SPIRV/GlslangToSpv.h>
#include <glslang/Public/ShaderLang.h>
#include <glslang/Public/ResourceLimits.h>

const char *vertexShaderSource = "#version 450 core\n"
                                "layout (location = 0) in vec3 aPos;\n"
                                "void main()\n"
                                "{\n"
                                "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
                                "}\0";
const char *fragmentShaderSource = "#version 450 core\n"
                                  "layout (location = 0) out vec4 FragColor;\n"
                                  "void main()\n"
                                  "{\n"
                                  "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
                                  "}\n\0";

bool CompileGLSLShader(const char *shaderSource, EShLanguage shaderType, std::vector<unsigned int> &spirvCode) {
    glslang::InitializeProcess();
    glslang::TShader shader(shaderType);
    shader.setStrings(&shaderSource, 1);
    shader.setEnvInput(glslang::EShSource::EShSourceGlsl, shaderType, glslang::EShClient::EShClientOpenGL, 450);
    shader.setEnvClient(glslang::EShClient::EShClientOpenGL, glslang::EShTargetClientVersion::EShTargetOpenGL_450);
    shader.setEnvTarget(glslang::EShTargetLanguage::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_0);

    const int defaultVersion = 100;
    EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
    if (!shader.parse(GetDefaultResources(), defaultVersion, false, messages)) {
        std::cerr << "Error in shader compilation:\n" << shader.getInfoLog() << std::endl;
        std::cerr << "Error in shader source:\n" << shaderSource << std::endl;
        glslang::FinalizeProcess();
        return false;
    }

    glslang::TProgram program;
    program.addShader(&shader);
    if (!program.link(messages)) {
        std::cerr << "Error while linking shaders:\n" << program.getInfoLog() << std::endl;
        glslang::FinalizeProcess();
        return false;
    }

    glslang::TIntermediate *intermediate = program.getIntermediate(shaderType);
    if (!intermediate) {
        std::cerr << "Failed to get SPIR-V intermediate code." << std::endl;
        glslang::FinalizeProcess();
        return false;
    }

    spv::SpvBuildLogger logger;
    glslang::SpvOptions spvOptions;
    glslang::GlslangToSpv(*intermediate, spirvCode, &logger, &spvOptions);

    glslang::FinalizeProcess();
    return true;
}

GLFWwindow *InitGLFWWindow(int width, int height, const char *title) {
    if (!glfwInit()) {
        std::cerr << "GLFW initialization failed." << std::endl;
        return nullptr;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);

    GLFWwindow *window = glfwCreateWindow(width, height, title, nullptr, nullptr);
    if (!window) {
        std::cerr << "Failed to create GLFW window." << std::endl;
        glfwTerminate();
        return nullptr;
    }

    glfwMakeContextCurrent(window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "Failed to initialize GLAD" << std::endl;
        exit(1);
    }

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

int main() {
    const int screenWidth = 800;
    const int screenHeight = 600;
    const char *windowTitle = "GLFW Window with Triangle";

    std::vector<unsigned int> vertexSpirv, fragmentSpirv;
    if (!CompileGLSLShader(vertexShaderSource, EShLangVertex, vertexSpirv) || !CompileGLSLShader(fragmentShaderSource, EShLangFragment, fragmentSpirv)) {
        return -1;
    }

    GLFWwindow *window = InitGLFWWindow(screenWidth, screenHeight, windowTitle);
    if (!window) {
        return -1;
    }

    float vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f, 0.5f, 0.0f
    };

    GLuint VBO;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
    glEnableVertexAttribArray(0);

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderBinary(1, &vertexShader, GL_SHADER_BINARY_FORMAT_SPIR_V, vertexSpirv.data(), vertexSpirv.size() * sizeof(unsigned int));

    int status = 0;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
    if (!status) {
        GLint infoLogLength = 0;
        glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
        std::vector<GLchar> infoLog(infoLogLength);
        glGetShaderInfoLog(vertexShader, infoLogLength, nullptr, infoLog.data());
        std::cerr << GL_INFO_LOG_LENGTH << " Shader program compile error:\n" << infoLog.data() << std::endl;
        glfwTerminate();
        return -1;
    }

    glSpecializeShader(vertexShader, "main", 0, nullptr, nullptr);
    
    std::cout << "UNREACHABLE \n";

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderBinary(1, &fragmentShader, GL_SHADER_BINARY_FORMAT_SPIR_V, fragmentSpirv.data(), fragmentSpirv.size() * sizeof(unsigned int));
    glSpecializeShader(fragmentShader, "main", 0, nullptr, nullptr);

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);

    GLint linkStatus;
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkStatus);
    if (!linkStatus) {
        GLint infoLogLength;
        glGetProgramiv(shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
        std::vector<GLchar> infoLog(infoLogLength);
        glGetProgramInfoLog(shaderProgram, infoLogLength, nullptr, infoLog.data());
        std::cerr << "Shader program linking error:\n" << infoLog.data() << std::endl;
        glfwTerminate();
        return -1;
    }

    glClear(GL_COLOR_BUFFER_BIT);
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);
    }

    glDeleteProgram(shaderProgram);
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    glDeleteBuffers(1, &VBO);
    glDeleteVertexArrays(1, &VAO);
    glfwTerminate();

    return 0;
}

字符集

smdncfj3

smdncfj31#

嗯,找到解决方案,由于某种原因,我需要分别使用glSpecializeShaderARBGL_SHADER_BINARY_FORMAT_SPIR_V_ARB而不是GL_SHADER_BINARY_FORMAT_SPIR_V

相关问题