我试图编译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;
}
字符集
1条答案
按热度按时间smdncfj31#
嗯,找到解决方案,由于某种原因,我需要分别使用
glSpecializeShaderARB
和GL_SHADER_BINARY_FORMAT_SPIR_V_ARB
而不是GL_SHADER_BINARY_FORMAT_SPIR_V