1
0
mirror of https://github.com/LearnOpenGL-CN/LearnOpenGL-CN.git synced 2025-08-23 04:35:28 +08:00

更新“调试”原文内容

This commit is contained in:
1i9h7_b1u3
2025-01-10 22:39:49 +08:00
parent 87a1644727
commit 91d08d2293

View File

@@ -91,13 +91,6 @@ glCheckError();
![](../img/06/01/debugging_glgeterror.png)
还有一个**重要的**事情需要知道GLEW有一个历史悠久的bug调用<fun>glewInit()</fun>会设置一个<var>GL_INVALID_ENUM</var>的错误标记,所以第一次调用的<fun>glGetError</fun>永远会猝不及防地给你返回一个错误代码。如果要修复这个bug我们建议您在调用<fun>glewInit</fun>之后立即调用<fun>glGetError</fun>消除这个标记:
```c++
glewInit();
glGetError();
```
<fun>glGetError</fun>并不能帮助你很多,因为它返回的信息非常简单,但不可否认它经常能帮助你检查笔误或者快速定位错误来源。总而言之,是一个非常简单但有效的工具。
## 调试输出
@@ -115,7 +108,7 @@ glGetError();
在GLFW中请求一个调试输出非常简单我们只需要传递一个提醒到GLFW中告诉它我们需要一个调试输出上下文即可。我们需要在调用<fun>glfwCreateWindow</fun>之前完成这一请求。
```c++
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
```
一旦GLFW初始化完成如果我们使用的OpenGL 版本为4.3或以上的话我们就有一个调试上下文了如果不是的话则祈祷系统仍然能够请求一个调试上下文吧。如果还是不行的话我们必须使用它的OpenGL拓展来请求调试输出。
@@ -137,21 +130,19 @@ if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
调试输出工作的方式是这样的我们首先将一个错误记录函数的回调类似于GLFW输入的回调传递给OpenGL在这个回调函数中我们可以自由地处理OpenGL错误数据在这里我们将输出一些有用的错误数据到控制台中。下面是这个就是OpenGL对调试输出所期待的回调函数的原型
```c++
void APIENTRY glDebugOutput(GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar *message, void *userParam);
void APIENTRY glDebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity,
GLsizei length, const char *message, const void *userParam);
```
注意在OpenGL的某些实现中最后一个参数为`const void*`而不是`void*`。
有了这一大堆的数据,我们可以创建一个非常有用的错误打印工具:
```c++
void APIENTRY glDebugOutput(GLenum source,
GLenum type,
GLuint id,
unsigned int id,
GLenum severity,
GLsizei length,
const GLchar *message,
const char *message,
void *userParam)
{
// 忽略一些不重要的错误/警告代码
@@ -196,6 +187,20 @@ void APIENTRY glDebugOutput(GLenum source,
当调试输出检测到了一个OpenGL错误它会调用这个回调函数我们将可以打印出非常多的OpenGL错误信息。注意我们忽略掉了一些错误代码这些错误代码一般不能给我们任何有用的信息比如NVidia驱动中的`131185`仅告诉我们缓冲成功创建了)。
既然我们已经有了回调函数,那么是时候初始化调试输出了:
```c++
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
{
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(glDebugOutput, nullptr);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
}
```
在这里我们告诉OpenGL启用调试输出调用<fun>glEnable(GL_DEBUG_SYNCRHONOUS)</fun>告诉OpenGL在发生错误时直接调用回调函数。
### 过滤调试输出
有了<fun>glDebugMessageControl</fun>你可以潜在地过滤出你需要的错误类型。在这里我们不打算过滤任何来源类型或者严重等级。如果我们仅希望显示OpenGL API的高严重等级错误消息你可以设置为以下这样
@@ -230,7 +235,7 @@ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,
如果你正在利用其它使用调试输出上下文的程序或OpenGL代码进行开发这会非常有用。其它的开发者能快速了解你自定义OpenGL代码中任何**报告出来的**Bug。
总而言之,调试输出(如果你能使用它)对与快速捕捉错误是非常有用的,完全值得你花一点时间来配置,它能够省下你非常多的开发时间。你可以在[这里](http://learnopengl.com/code_viewer_gh.php?code=src/6.in_practice/1.debugging/debugging.cpp)找到源码,里面<fun>glGetError</fun>和调试输出上下文都有配置;看看你是否能够修复所有的错误。
总而言之,调试输出(如果你能使用它)对与快速捕捉错误是非常有用的,完全值得你花一点时间来配置,它能够省下你非常多的开发时间。你可以在[这里](http://learnopengl.com/code_viewer_gh.php?code=src/7.in_practice/1.debugging/debugging.cpp)找到源码,里面<fun>glGetError</fun>和调试输出上下文都有配置;看看你是否能够修复所有的错误。
## 调试着色器输出
@@ -256,7 +261,7 @@ void main()
![](../img/06/01/debugging_glsl_output.png)
从视觉效果来看,我们可以看见法向量应该是正确的,因为纳米装的右侧大部分都是红色的这表明法线大概正确地指向正x轴并且类似的纳米装的前方大部分都为蓝色即正z轴方向。
从视觉效果来看,我们可以看见世界空间的法向量应该是正确的,因为背包模型的右侧大部分都是红色的这表明法线大概正确地指向正x轴同样的,背包的前方大部分都为蓝色即正z轴方向。
这一方法可以很容易拓展到你想要测试的任何变量。一旦你卡住了或者怀疑你的着色器有问题,尝试显示多个变量和/或中间结果,看看哪部分算法什么的没加上或者有错误。
@@ -289,7 +294,7 @@ glsllangvalidator shaderFile.vert
## 帧缓冲输出
你的调试工具箱中另外一个技巧就是在OpenGL程序中一块特定区域显示帧缓冲的内容。你可能会比较频繁地使用[帧缓冲](../04 Advanced OpenGL/05 Framebuffers.md),但由于帧缓冲的魔法通常在后进行,有时候想要知道出什么问题会非常困难。在你的程序中显示帧缓冲的内容是一个很有用的技巧,帮助你快速检查错误。
你的调试工具箱中另外一个技巧就是在OpenGL程序中一块特定区域显示帧缓冲的内容。你可能会比较频繁地使用[帧缓冲](../04 Advanced OpenGL/05 Framebuffers.md),但由于帧缓冲的操作通常在后进行,有时候想要知道出什么问题会非常困难。在你的程序中显示帧缓冲的内容是一个很有用的技巧,帮助你快速检查错误。
!!! important
@@ -367,14 +372,6 @@ int main()
我在下面列出了一些流行的调试工具,选几个尝试一下,看看哪个最适合你。
### gDebugger
gDebugger是一个非常易用的跨平台OpenGL程序调试工具。gDebugger会在你运行的OpenGL程序边上提供OpenGL状态的详细概况。你可以随时暂停程序来检查当前状态纹理内容以及缓冲使用。你可以在[这里](http://www.gremedy.com/)下载gDebugger。
运行gDebugger只需要打开程序创建一个工程给它你OpenGL程序的位置于工作目录即可。
![](../img/06/01/debugging_external_gdebugger.png)
### RenderDoc
RenderDoc是另外一个很棒的完全[开源](https://github.com/baldurk/renderdoc)的独立调试工具。和gDebugger类似你只需要设置捕捉的程序以及工作目录就行了。你的程序会正常运行当你想要检查一个特定的帧的时候你只需要让RenderDoc在程序当前状态下捕捉一个或多个帧即可。在捕捉的帧当中你可以观察管线状态所有OpenGL指令缓冲储存以及使用的纹理。
@@ -383,15 +380,15 @@ RenderDoc是另外一个很棒的完全[开源](https://github.com/baldurk/re
### CodeXL
[CodeXL](http://developer.amd.com/tools-and-sdks/opencl-zone/codexl/)是由AMD开发的一款GPU调试工具它有独立版本也有Visual Studio插件版本。CodeXL可以给你非常多的信息对于图形程序的性能测试也非常有用。CodeXL在NVidia与Intel的显卡上也能运行不过会不支持OpenCL调试。
[CodeXL](https://gpuopen.com/compute-product/codexl/)是由AMD开发的一款GPU调试工具它有独立版本也有Visual Studio插件版本。CodeXL可以给你非常多的信息对于图形程序的性能测试也非常有用。CodeXL在NVidia与Intel的显卡上也能运行不过会不支持OpenCL调试。
![](../img/06/01/debugging_external_codexl.png)
我没有太多的CodeXL使用经验我个人觉得gDebugger和RenderDoc会更容易使用一点但我仍把它列在这里因为它仍是一个非常可靠的工具并且主要是由最大的GPU制造商之一AMD开发的。
我没有太多的CodeXL使用经验我个人觉得RenderDoc会更容易使用一点但我仍把它列在这里因为它仍是一个非常可靠的工具并且主要是由最大的GPU制造商之一开发的。
### NVIDIA Nsight
NVIDIA流行的[Nsight](https://developer.nvidia.com/nvidia-nsight-visual-studio-edition) GPU调试工具并不是一个独立程序而是一个Visual Studio IDE或者Eclipse IDE的插件 (NVIDIA现在也提供独立版本了)。Nsight插件对图形开发者来说非常容易使用因为它给出了GPU用量逐帧GPU状态大量运行时的统计数据。
NVIDIA流行的[Nsight](https://developer.nvidia.com/nvidia-nsight-visual-studio-edition) GPU调试工具并不是一个独立程序而是一个Visual Studio IDE或者Eclipse IDE的插件 (NVIDIA现在也提供[独立版本](https://developer.nvidia.com/nsight-graphics)了)。Nsight插件对图形开发者来说非常容易使用因为它给出了GPU用量逐帧GPU状态大量运行时的统计数据。
当你在Visual Studio或Eclipse使用Nsight的调试或者性能测试指令启动程序的时候Nsight将会在程序自身中运行。Nsight非常棒的一点就是它在你的程序中渲染了一套GUI系统你可以使用它获取你程序各种各样有用的信息可以是运行时也可以是逐帧分析。
@@ -399,7 +396,7 @@ NVIDIA流行的[Nsight](https://developer.nvidia.com/nvidia-nsight-visual-studio
Nsight是一款非常有用的工具在我看来比上述其它工具都有更好的表现但它仍有一个非常重要的缺点它只能在NVIDIA的显卡上工作。如果你正在使用一款NVIDIA的显卡并且使用Visual StudioNsight是非常值得一试的。
我知道我可能遗漏了一些其它的调试工具比如我还能想到有Valve的[VOGL](https://github.com/ValveSoftware/vogl)和[APItrace](https://apitrace.github.io/)),但我觉得这个列表已经给你足够多的工具来实验了。我并不是之前提到的任何一个工具的专家,所以如果我在哪里讲错了请在评论区留言,我会很乐意改正。
我知道我可能遗漏了一些其它的调试工具比如我还能想到有Valve的[VOGL](https://github.com/ValveSoftware/vogl)和[APItrace](https://apitrace.github.io/)),但我觉得这个列表已经给你足够多的工具来实验了。
## 附加资源