【发布时间】:2015-03-07 21:32:07
【问题描述】:
我已经从 Anton 的 opengl 教程配套代码中改编了一些代码,这里可以找到: https://github.com/capnramses/antons_opengl_tutorials_book/blob/master/02_shaders/main.c
在测试 print_all 或 dump_all 函数以打印有关着色器的所有内容时,我注意到在我的日志中 glGetProgramiv(shader_program, GL_ACTIVE_UNIFORMS, &params) 将放置一个非常负的垃圾值(并且由于 for 循环检查而没有做任何事情) 或非常积极并在glGetActiveUniform(shader_program, i, MAX_LENGTH, &actual_length, &size, &type, name) 处使我的程序崩溃,因为它只应该处理i 到NUM_ACTIVE_UNIFORMS - 1 的值;我敢肯定,预计数字不会超过 100 万。调用后我还检查了 glGetError 的结果,没有设置错误标志。
这是我的转储功能和我的日志图片:
void dump_all(FILE* file, GLuint shader_program)
{
int params = -1;
fprintf(file, "--------------------\nshader program %i info:\n", shader_program);
glGetProgramiv (shader_program, GL_LINK_STATUS, ¶ms);
fprintf(file, "GL_LINK_STATUS = %i\n", params);
glGetProgramiv (shader_program, GL_ATTACHED_SHADERS, ¶ms);
fprintf(file,"GL_ATTACHED_SHADERS = %i\n", params);
glGetProgramiv (shader_program, GL_ACTIVE_ATTRIBUTES, ¶ms);
fprintf(file, "GL_ACTIVE_ATTRIBUTES = %i\n", params);
const int MAX_LENGTH = 64;
int i;
for (i = 0; i < params; i++)
{
char name[MAX_LENGTH];
int actual_length = 0; // not used atm.
int size = 0;
GLenum type;
glGetActiveAttrib (shader_program, i, MAX_LENGTH, &actual_length, &size, &type, name);
if (size > 1)
{
int j;
for (j = 0; j < size; j++)
{
char long_name[MAX_LENGTH];
int location;
sprintf (long_name, "%s[%i]", name, j);
location = glGetAttribLocation (shader_program, long_name);
fprintf (file, " %i) type:%s name:%s location:%i\n",
i, gl_type_to_string(type), long_name, location);
}
}
else
{
int location = glGetAttribLocation (shader_program, name);
fprintf(file, " %i) type:%s name:%s location:%i\n", i, gl_type_to_string (type), name, location);
}
}
printf("\nbefore the active uniform call\n");
glGetProgramiv (shader_program, GL_ACTIVE_UNIFORMS, ¶ms);
GLenum error = glGetError();
printf("\nThere is an error (0 for no error and 1 for an error): %d\n", error != GL_NO_ERROR);
printf("\nglGetError: %d\n", error);
printf("\nafter the get active uniform call\n");
fprintf(file, "GL_ACTIVE_UNIFORMS = %i\n", params);
for (i = 0; i < params; i++)
{
char name[MAX_LENGTH];
int actual_length = 0; // not used atm.
int size = 0;
GLenum type;
printf("\nright before the thing\n");
glGetActiveUniform (shader_program, i, MAX_LENGTH, &actual_length, &size, &type, name);
printf("\nright after the thign\n");
if (size > 1)
{
printf("\nin the if block\n");
int j;
for (j = 0; j < size; j++)
{
char long_name[MAX_LENGTH];
int location;
sprintf (long_name, "%s[%i]", name, j);
location = glGetUniformLocation (shader_program, long_name);
fprintf(file, " %i) type:%s name:%s location:%i\n",
i, gl_type_to_string (type), long_name, location);
}
}
else
{
printf("\nin the else block\n");
int location = glGetUniformLocation (shader_program, name);
fprintf(file, " %i) type:%s name:%s location:%i\n",
i, gl_type_to_string (type), name, location);
}
}
print_program_info_log(file, shader_program);
}
值为负时我的日志:http://i.stack.imgur.com/Xu9nq.png
当价值巨大并且程序崩溃时我的日志:http://i.stack.imgur.com/QBP1o.png
注意:我从找不到文件的目录运行应用程序。此外,我还没有在任何地方调用 glUseProgram() 。因此,我正在转储尚未成功链接的着色器的内容,甚至没有附加任何成功编译的着色器。
这是一个间歇性问题;大多数情况下,日志会正确打印出活动制服的 0。到目前为止,我已经看到了三个结果; 1.) 数字太大而崩溃。 2.)这个数字是疯狂的负数,不会崩溃。 3.)这个数字很大但不是太大,并且在崩溃调用下面的循环中花费了大量时间,只是打印出垃圾。
这是驱动程序错误,还是我在做一些本质上未定义的事情?
编辑 1:
如果对glGetProgramiv(shader_program, GL_ACTIVE_UNIFORMS, &params) 的调用返回一个巨大的数字,则对glGetActiveUniform (shader_program, i, MAX_LENGTH, &actual_length, &size, &type, name) 的调用在它下面的for 循环的第一次迭代中崩溃,i 的值为零。但是,当glGetProgramiv 为活动制服返回 0 时,使用 0 为i 调用glGetActiveUniform 不会崩溃(我将 for 循环硬编码为一次)。这让我觉得这里发生的不仅仅是未初始化的数据返回给我。
编辑 2 根据要求,这是一个给出奇怪值的最小示例程序:
#include <stdio.h>
#undef main
int main(int argc, char ** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_Window *window = SDL_CreateWindow("Example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_OPENGL);
if(!window)
{
printf("no window created : %s\n", SDL_GetError());
}
SDL_GLContext context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, context);
SDL_GL_SetSwapInterval(1);
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if(err != GLEW_OK)
{
printf("glew failed to init: %s", glewGetErrorString(err));
return -1;
}
GLuint program = glCreateProgram();
glLinkProgram(program); // I can create and attach shaders, compile them, or whatever; I get the same result.
GLint num;
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &num);
printf("NUM UNIFORMS: %d", num);
int run_loop = 1;
while(run_loop)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
SDL_Quit();
run_loop = 0;
break;
default:
break;
}
}
SDL_GL_SwapWindow(window);
}
return 0;
}
【问题讨论】:
标签: c++ c opengl driver undefined-behavior