什么是debuggingOpenGL的最佳方法?
我发现很多时候,OpenGL会通过不绘制任何东西来显示它失败。 我试图find方法来debuggingOpenGL程序,通过检查转换matrix堆栈等。 什么是debuggingOpenGL的最佳方法? 如果代码看起来像顶点在正确的位置,你怎么能确定它们是?
没有直接的答案。 这一切都取决于你想了解什么。 由于OpenGL是状态机,有时它不会做你期望的状态,因为没有设置状态或类似的东西。
一般来说,使用glTrace / glIntercept(查看OpenGL调用跟踪),gDebugger(可视化纹理,着色器,OGL状态等)和纸/铅笔:)等工具。 有时候可以帮助理解你如何设置相机以及它正在观看的内容,被剪辑的内容等等。我个人比以前的两种方法更依赖于它。 但是当我认为深度是错误的时候,有助于观察痕迹。 gDebugger也是可以有效用于分析和优化OpenGL应用程序的唯一工具。
除了这个工具之外,大多数时候,人们错误的math运算是不正确的,使用任何工具都无法理解。 在OpenGL.org上发布newgroup代码的具体评论,你永远不会失望。
希望这回答你的问题!
GLIntercept是你最好的select。 从他们的网页:
- 将所有OpenGL函数调用保存为文本或XML格式,并使用选项logging单个帧。
- 免费相机。 绕过发送到显卡的几何graphics,并启用/禁用线框/背面剔除/查看平截头体渲染
- 保存并跟踪显示列表。 保存OpenGL帧缓冲区(颜色/深度/模板)前后渲染调用。 保存前后图像的“差异”的能力也是可用的。
Apitrace是Valve的一些相对较新的工具,但是它的工作很棒! 试试看: https : //github.com/apitrace/apitrace
我发现你可以检查使用glGetError
每行代码后,你的嫌疑犯将是错误的,但做了之后,代码看起来不是很干净,但它的工作原理。
对于Mac上的那些,OpenGLdebugging器中的buit也很棒。 它可以让你检查缓冲区,状态,并帮助find性能问题。
gDebugger是一个很好的免费工具,但不再支持。 然而,AMD已经拿起了自己的开发,而这个debugging器现在被称为CodeXL 。 它既可以作为独立应用程序使用,也可以作为Visual Studio插件使用 – 既可用于本机C ++应用程序,也可用于使用OpenGL绑定的Java / Python应用程序,这两种应用程序均可用于NVidia和AMD GPU。 这是一个工具的地狱。
什么是debuggingOpenGL的最佳方法?
不考虑额外和外部工具(其他答案已经这样做)。
那么一般的方法是广泛调用glGetError()
。 但更好的select是使用debugging输出 ( KHR_debug , ARB_debug_output )。 这为您提供了为不同严重级别消息设置callback的function。
为了使用debugging输出, 必须使用WGL/GLX_DEBUG_CONTEXT_BIT
标志创build上下文。 使用GLFW,可以使用GLFW_OPENGL_DEBUG_CONTEXT
窗口提示进行设置 。
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
请注意,如果上下文不是debugging上下文,则不能保证接收所有甚至任何消息。
通过检查GL_CONTEXT_FLAGS
可以检测到是否有debugging环境:
GLint flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags); if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) // It's a debug context
然后您将继续并指定一个callback:
void debugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam) { // Print, log, whatever based on the enums and message }
在这里可以看到枚举的每个可能的值。 特别要记住检查严重性,因为有些消息可能只是通知而不是错误。
您现在可以提前完成注册callback。
glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); glDebugMessageCallback(debugMessage, NULL); glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
你甚至可以使用glDebugMessageInsert()
注入自己的消息。
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Vary dangerous error");
对于着色器和程序,您总是希望检查GL_LINK_STATUS
, GL_LINK_STATUS
和GL_VALIDATE_STATUS
。 如果它们中的任何一个反映了某些错误,那么另外总是检查glGetShaderInfoLog()
/ glGetProgramInfoLog()
。
GLint linkStatus; glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); if (!linkStatus) { GLchar *infoLog = new GLchar[infoLogLength + 1]; glGetProgramInfoLog(program, infoLogLength * sizeof(GLchar), NULL, infoLog); ... delete[] infoLog; }
glGetProgramInfoLog()
返回的string将以null结尾。
你也可以走得更加极端,在debugging版本中使用一些debuggingmacros。 因此,使用glIs*()
函数来检查预期types是否也是实际types。
assert(glIsProgram(program) == GL_TRUE); glUseProgram(program);
如果debugging输出不可用,而您只想使用glGetError()
,那么您当然可以自由地这样做。
GLenum err; while ((err = glGetError()) != GL_NO_ERROR) printf("OpenGL Error: %u\n", err);
由于数字错误代码不是那么有用,我们可以通过将数字错误代码映射到消息来使其更具人性化。
const char* glGetErrorString(GLenum error) { switch (error) { case GL_NO_ERROR: return "No Error"; case GL_INVALID_ENUM: return "Invalid Enum"; case GL_INVALID_VALUE: return "Invalid Value"; case GL_INVALID_OPERATION: return "Invalid Operation"; case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation"; case GL_OUT_OF_MEMORY: return "Out of Memory"; case GL_STACK_UNDERFLOW: return "Stack Underflow"; case GL_STACK_OVERFLOW: return "Stack Overflow"; case GL_CONTEXT_LOST: return "Context Lost"; default: return "Unknown Error"; } }
然后检查它是这样的:
printf("OpenGL Error: [%u] %s\n", err, glGetErrorString(err));
这仍然不是很有帮助,或者说更直观,就好像你在这里和那里撒了几个glGetError()
。 然后find哪一个logging错误可能是麻烦的。
macros再次来拯救。
void _glCheckError(const char *filename, int line) { GLenum err; while ((err = glGetError()) != GL_NO_ERROR) printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err)); }
现在简单地定义一个这样的macros:
#define glCheckError() _glCheckError(__FILE__, __LINE__)
现在你可以调用glCheckError()
在你想要的东西之后,如果有错误,它会告诉你确切的文件和它被检测到的行。
还有免费的glslDevil: http : //www.vis.uni-stuttgart.de/glsldevil/
它允许您广泛debuggingglsl着色器。 它也显示失败的OpenGL调用。
但是它缺less检查纹理和屏幕外缓冲区的function。
如果你有一个NVidia卡, Nsight是一个很好的debugging工具。
dynamic更新窗口标题对我来说很方便。
示例(使用GLFW,C ++ 11):
glfwSetWindowTitle(window, ("Now Time is " + to_string(glfwGetTime())).c_str());