OpenGL glLinkProgram返回false但信息日志为空;检查一切

时间:2011-12-22 04:58:44

标签: c++ opengl linker glsl shader

我必须承认这是我第一次实现着色器,之前我只使用过固定功能管道;但是,虽然我确信我所做的一切都是正确的 - 但一定有错误。

glLinkProgram(program) - 在查询GL_FALSE时返回GL_LINK_STATUS。此外,信息日志为空(当我查询日志长度 - 它是1,这是每个文档的空终止符,它检出)。所以链接器错误,没有日志。另外,我刚刚发现链接器问题一旦我在顶点着色器中使用gl_Position变量,就会在赋值期间和我用它进行计算时出现。我尝试了各种着色器变体,它出错了,但它无法生成日志 - 只要触摸GL_FALSE,它似乎就会返回gl_Position。有趣的是,片段着色器不会引起任何问题。

片段和顶点着色器都可以正常编译而没有错误。当我引入语法错误时,会检测,打印它们,并在程序创建之前中止该过程(因此它似乎工作正常)。我调试并确保文件正确加载,源为空终止,大小正确,我在附件后检查附加程序的数量,它是2(正确的大声笑)。为清楚起见,它被删除了,我有checkForErrors()方法来检查和打印opengl错误 - 没有检测到。

我很难过,请有人帮忙!我已经失去了2天的睡眠......

这是加载着色器的代码:

FILE *file = fopen(fileName.c_str(), "rb");

if(file == NULL)
{
    Log::error("file does not exist: \"" + fileName + "\"");
    return NULL;
}

// Calculate file size
fseek(file , 0 , SEEK_END);
int size = ftell(file);
rewind(file);

// If file size is 0
if(size == 0)
{
    Log::error("file is empty: \"" + fileName + "\"");
    return NULL;
}

char **source = new char*[1];
source[0] = new char[size+1];
source[0][size] = '\0';

// If we weren't able to read the entire file into memory
int readSize = fread(source[0], sizeof(char), size, file);
if(size != readSize)
{
    int fileError = ferror(file);

    // Free the source, log an error and return false
    delete source[0];
    delete [] source;
    fclose(file);
    Log::error("couldn't load file into memory [ferror(" + toString<int>(fileError) + ")]: \"" + fileName + "\" (Size: " + toString<int>(readSize) + "/" + toString<int>(size) + " bytes)");
    return NULL;
}

// Close the file
fclose(file);




// Create the shader object


// shaderType is GLenum that is set based on the file extension. I assure you it is correctly set to either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
GLuint shaderID = glCreateShader(shaderType);

// If we could not create the shader object, check for OpenGL errors and return false
if(shaderID == 0)
{
    checkForErrors();
    Log::error("error creating shader \"" + name);
    delete source[0];
    delete [] source;
    return NULL;
}

// Load shader source and compile it
glShaderSource(shaderID, 1, (const GLchar**)source, NULL);
glCompileShader(shaderID);

GLint success;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
if(!success)
{
    GLchar error[1024];
    glGetShaderInfoLog(shaderID, 1024, NULL, error);
    Log::error("error compiling shader \"" + name + "\"\n    Log:\n" + error);
    delete source[0];
    delete [] source;
    return NULL;
}
else
{
    Log::debug("success! Loaded shader \"" + name + "\"");
}

// Clean up
delete source[0];
delete [] source;

快速说明:glShaderSource - 我转换为(const GLchar **),因为GCC抱怨const为非const char指针;否则,我相信我完全顺从。

顺便说一下,那里没有错误。着色器(下面)编译时没有任何错误。

顶点着色器:

void main()
{
    // If I comment the line below, the link status is GL_TRUE.
    gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
}

Fragment Shader:

void main()
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

下面是创建着色器程序,附加对象和链接等的代码:

// Create a new shader program
GLuint program = glCreateProgram();
if(program == 0)
{
    Log::error("RenderSystem::loadShaderProgram() - could not create OpenGL shader program; This one is fatal, sorry.");
    getContext()->fatalErrorIn("RenderSystem::loadShaderProgram(shader1, shader2)", "OpenGL failed to create object using glCreateProgram()");
    return NULL;
}

// Attach shader objects to program
glAttachShader(program, vertexShaderID);
glAttachShader(program, fragmentShaderID);

// Link the program
GLint success = GL_FALSE;
glLinkProgram(program);
checkForErrors();
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(success == GL_FALSE)
{
    GLchar errorLog[1024] = {0};
    glGetProgramInfoLog(program, 1024, NULL, errorLog);
    Log::error(std::string() + "error linking program: " + errorLog);
    return NULL;
}

success = GL_FALSE;
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &success);
if(success == GL_FALSE)
{
    GLchar errorLog[1024] = {0};
    glGetProgramInfoLog(program, 1024, NULL, errorLog);
    checkForErrors();
    Log::error(std::string() + "error validating shader program; Details: " + errorLog);
    return NULL;
}

通常它甚至没有达到验证程序的程度......我对此非常沮丧,很难不庸俗。

我们需要您的帮助,我们非常感谢您的帮助!

编辑:我在Intel HD 3000上运行一切(支持OpenGL高达3.1)。我的目标OpenGL版本是2.0。

EDIT2:我还要注意,如果在fopen中设置“r”或“rt”标志,我在从文本文件中读取着色器时会遇到一些问题 - 读取大小比实际大小小10个字节(始终在所有文件上) - 并且feof()将返回true。当我切换到二进制(“rb”)读取时,问题消失了,文件被完全读取。我确实尝试了几种替代实现,并且它们在链接期间都产生了相同的错误(我在读取文件之后立即将着色器源打印到控制台以确保它看起来正确,确实如此。)。

1 个答案:

答案 0 :(得分:15)

好吧,我知道当我发帖时这会让人感到尴尬,但这很糟糕:通常伴随英特尔驱动程序的英特尔图形配置应用程序有3D设置标签;现在,未选中“自定义设置”复选框,但“顶点处理”设置下的灰色选项拼写为“启用软件处理”。即使它未经检查且一切都显示为灰色,我只需输入自定义设置并将所有内容检查到“应用程序设置”。

修好了!一切都像它应该的链接!不知道是谁想到了那个选项,为什么会有用呢?!它是唯一看起来非常不合适的选择。

我经历了几次驱动程序重新安装,强烈的调试和配置研究,我不得不推测并绝对猜测一切!太可怕了,不希望我的最坏的敌人。