第四十章 调试总结

调试没有文本输出控制台,GLSL中没有断点,无法检测GPU的运行状态。
glGetError函数可以查询错误标记,会检测错误标记集,在OpenGL确实出错的时候返回一个错误值,原型如下:
GLenum glGetError();————要么会返回错误标记之一,要么返回无错误。
GL_NO_ERROR 0 自上次调用glGetError以来没有错误
GL_INVALID_ENUM 1280 枚举参数不合法
GL_INVALID_VALUE 1281 值参数不合法
GL_INVALID_OPERATION 1282 一个指令的状态对指令的参数不合法
GL_STACK_OVERFLOW 1283 压栈操作造成栈上溢(Overflow)
GL_STACK_UNDERFLOW 1284 弹栈操作时栈在最低点(译注:即栈下溢(Underflow))
GL_OUT_OF_MEMORY 1285 内存调用操作无法调用(足够的)内存
GL_INVALID_FRAMEBUFFER_OPERATION 1286 读取或写入一个不完整的帧缓冲
补充:
当一个错误标记被返回的时候,将不会报告其它的错误标记。换句话说,当glGetError被调用的时候,它会清除所有的错误标记(在分布式系统上只会清除一个,见下面的注释)。
这也就是说如果你在每一帧之后调用glGetError一次,它返回一个错误,但你不能确定这就是唯一的错误,并且错误的来源可能在这一帧的任意地方。
举例:
glBindTexture(GL_TEXTURE_2D, tex);
std::cout << glGetError() << std::endl; // 返回 0 (无错误)

glTexImage2D(GL_TEXTURE_3D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
std::cout << glGetError() << std::endl; // 返回 1280 (非法枚举)

glGenTextures(-5, textures);
std::cout << glGetError() << std::endl; // 返回 1281 (非法值)

std::cout << glGetError() << std::endl; // 返回 0 (无错误)
通常我们会写一个助手函数来简便地打印出错误字符串以及错误检测函数调用的位置:
GLenum glCheckError_(const char *file, int line)
{
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = “INVALID_ENUM”; break;
case GL_INVALID_VALUE: error = “INVALID_VALUE”; break;
case GL_INVALID_OPERATION: error = “INVALID_OPERATION”; break;
case GL_STACK_OVERFLOW: error = “STACK_OVERFLOW”; break;
case GL_STACK_UNDERFLOW: error = “STACK_UNDERFLOW”; break;
case GL_OUT_OF_MEMORY: error = “OUT_OF_MEMORY”; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = “INVALID_FRAMEBUFFER_OPERATION”; break;
}
std::cout << error << " | " << file << " (" << line << “)” << std::endl;
}
return errorCode;
}
#define glCheckError() glCheckError_(FILE, LINE)
补充:
__FILE__和__LINE__这两个预处理指令,会在编译的时候被替换成编译时对应的文件和行号
注意:
glGetError显示的错误会发生在该次调用与上次调用之间,如果间隔太大的话需要检查的地方就太多了

GLEW有一个bug,调用glewInit()会设置一个GL_INVALID_ENUM的错误标记,第一次调用glGetError会返回错误码。如果要修复,可以在调用
glewInit后立即调用glGetError消除该标记:
glewInit();
glGetError();

另外还有一个叫调试输出的OpenGL扩展 工具。在4.3版本后是核心OpenGL的一部分。
通过使用调试输出扩展,OpenGL会直接发送一个比glGetError更完善的错误或告警信息给用户,不仅提供了更多信息,也能帮助使用调试器捕捉错误源头。
补充:OpenGL低于4.3 的话,可以查询ARB_debug_output或AMD_debug_output拓展来获取其功能。
当前学习一些GLFW的调试输出:只需要传递一个提醒到GLFW,告诉其需要一个调试输出上下文即可。
需要在调用glfwCreateWindow之前完成该请求:glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TURE);

一旦GLFW初始化完成,如果使用的OpenGL版本是4.3的话,就有了一个调试上下文,否则需要使用OpenGL拓展来请求调试输出。
要检查是否成功地初始化了调试上下文,可以对OpenGL进行查询:
GLint flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
{
// 初始化调试输出
}
调试输出工作的方式是:首先将一个错误记录函数的毁掉传递给OpenGL,在回调函数中可以自由地处理错误数据,将输出有用的错误数据到控制台。原型如下:
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, 
                            GLuint id, 
                            GLenum severity, 
                            GLsizei length, 
                            const GLchar *message, 
                            void *userParam)
{
    // 忽略一些不重要的错误/警告代码
    if(id == 131169 || id == 131185 || id == 131218 || id == 131204) return; 

    std::cout << "---------------" << std::endl;
    std::cout << "Debug message (" << id << "): " <<  message << std::endl;

    switch (source)
    {
        case GL_DEBUG_SOURCE_API:             std::cout << "Source: API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:   std::cout << "Source: Window System"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cout << "Source: Shader Compiler"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY:     std::cout << "Source: Third Party"; break;
        case GL_DEBUG_SOURCE_APPLICATION:     std::cout << "Source: Application"; break;
        case GL_DEBUG_SOURCE_OTHER:           std::cout << "Source: Other"; break;
    } std::cout << std::endl;

    switch (type)
    {
        case GL_DEBUG_TYPE_ERROR:               std::cout << "Type: Error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cout << "Type: Deprecated Behaviour"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:  std::cout << "Type: Undefined Behaviour"; break; 
        case GL_DEBUG_TYPE_PORTABILITY:         std::cout << "Type: Portability"; break;
        case GL_DEBUG_TYPE_PERFORMANCE:         std::cout << "Type: Performance"; break;
        case GL_DEBUG_TYPE_MARKER:              std::cout << "Type: Marker"; break;
        case GL_DEBUG_TYPE_PUSH_GROUP:          std::cout << "Type: Push Group"; break;
        case GL_DEBUG_TYPE_POP_GROUP:           std::cout << "Type: Pop Group"; break;
        case GL_DEBUG_TYPE_OTHER:               std::cout << "Type: Other"; break;
    } std::cout << std::endl;

    switch (severity)
    {
        case GL_DEBUG_SEVERITY_HIGH:         std::cout << "Severity: high"; break;
        case GL_DEBUG_SEVERITY_MEDIUM:       std::cout << "Severity: medium"; break;
        case GL_DEBUG_SEVERITY_LOW:          std::cout << "Severity: low"; break;
        case GL_DEBUG_SEVERITY_NOTIFICATION: std::cout << "Severity: notification"; break;
    } std::cout << std::endl;
    std::cout << std::endl;
}

函数glDebugMessageControl可以潜在地过滤出需要的错误类型。如果想OpenGL API显示高严重等级错误消息,可以设置为:
glDebugMessageControl(GL_DEBUG_SOURCE_API,
GL_DEBUG_TYPE_ERROR,
GL_DEBUG_SEVERITY_HIGH,
0, nullptr, GL_TRUE);

补充:
调试输出还有一个技巧是:回溯调试错误源。通过DebugOutput中特定的错误类型上设置一个断点,调试器会捕捉到抛出的错误,可以向上查找调用栈直接找到消息发出的源头。

下面看下自定义错误输出:可以使用glDebugMessageInsert将信息推送到调试输出系统:
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,
GL_DEBUG_SEVERITY_MEDIUM, -1, “error message here”);

下面看下调试着色器输出
GLSL来说,不能访问glGetError函数,也不能通过步进的方式运行着色器代码,如果是一个黑屏,要知道是着色器代码是否有问题,很难。
技巧:将着色器中所有相关变量的值直接发送到片段着色器的输出通道。通过直接输出着色器变量到输出颜色通道,直接能看出颜色效果来获取有用的信息。

下面看下 OPenGL GLSL参考编译器
可能会出现在一台机器上的着色器到另外一台机器上可能会由于驱动差异不能正常工作。
不同GPU供应商之间有细微差别,可以通过GLSL语言校验器进行检查着色器代码,只需要把着色器文件作为程序的第一个参数即可。GLSL语言校验器是通过下列
国定的后缀名来决定着色器的类型:https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
.vert:顶点着色器(Vertex Shader)
.frag:片段着色器(Fragment Shader)
.geom:几何着色器(Geometry Shader)
.tesc:细分控制着色器(Tessellation Control Shader)
.tese:细分计算着色器(Tessellation Evaluation Shader)
.comp:计算着色器(Compute Shader)
运行GLSL参考编译器需要在cmd中执行:glsllangvalidator shaderFile.vert
没有检测到错误就不会有输出,否则会打印出错误。是直接对着GLSL规范进行检查的

下面看下帧缓冲输出的调试
在OpenGL程序中一块特定区域显示帧缓冲的内容。
注意:当前说的帧缓冲显示内容,只能在纹理附件上使用,而不能应用于渲染缓冲对象。

使用一个非常简单,只显示纹理的着色器,可以写一个助手函数快速在屏幕右上角显示任何纹理:
// 顶点着色器
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 texCoords;

out vec2 TexCoords;

void main()
{
gl_Position = vec4(position, 0.0f, 1.0f);
TexCoords = texCoords;
}

// 片段着色器
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;

uniform sampler2D fboAttachment;

void main()
{
FragColor = texture(fboAttachment, TexCoords);
}

void DisplayFramebufferTexture(GLuint textureID)
{
    if(!notInitialized)
    {
        // 在屏幕右上角,使用NDC顶点坐标初始化着色器和VAO
        [...]
    }

    glActiveTexture(GL_TEXTURE0);   
    glUseProgram(shaderDisplayFBOOutput);
        glBindTexture(GL_TEXTURE_2D, textureID);
        glBindVertexArray(vaoDebugTexturedRect);
            glDrawArrays(GL_TRIANGLES, 0, 6);
        glBindVertexArray(0);
    glUseProgram(0);
}

int main()
{
    [...]
    while (!glfwWindowShouldClose(window))
    {
        [...]
        DisplayFramebufferTexture(fboAttachment0);

        glfwSwapBuffers(window);
    }
}

下面分享下外部调试软件
1.gDebugger
是跨平台OpenGL程序调试工具。会在运行的OpenGL程序边上,提供状态的详细概况。可以随时暂停程序来检查当前状态,纹理内容和缓冲使用。
http://www.gremedy.com/
用法:创建一个工程,给其OpenGL程序的位置的工作目录就行。
2.RenderDoc
是一个完全开源的独立调试工具。当要检查一个特定的帧的时候,只需要让RenderDoc在程序当前状态下捕捉一个或多个帧即可。
在捕捉的帧当中,可以观察管线状态,所有OpenGL指令,缓冲存储,以及使用的纹理。
3.CodeXL
是AMD开发的一款GPU调试工具,具有独立版本,也有vs的插件版本。但不支持OpenCL
4.NVIDIA Nsight
是vs和Eclipse的插件。使用其调试或性能测试指令启动程序的时候,它会在程序自身中运行。
优点:在程序中渲染了一套GUI系统,可以使用它获取程序信息,可以是运行时的,也可以是逐帧分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章OK6410 简介..................................................................................................................... 6 第二章安装RVDS2.2 开发环境.................................................................................................. 9 2-1 安装RVDS2.2 到Windows XP 中.................................................................................. 9 第三章JLINK 驱动的安装..........................................................................................................16 第四章JLINK 的连接方法..........................................................................................................21 第五章RVDS2.2 介绍..................................................................................................................22 5-1 RVDS 开发工具介绍...................................................................................................... 22 5-2 集成开发环境(IDE)...................................................................................................22 第六章RVDS2.2 的使用方法以及调试方法、调试的原理................................................... 23 6-1 CodeWarrior for RVDS....................................................................................................23 6-1-1 打开CodeWarrior................................................................................................23 6-1-2 新建OK6410 裸机工程的方法.........................................................................24 6-1-3 为工程添加源码文件......................................................................................... 29 6-1-4 为工程进行必要的设置.....................................................................................31 6-1-5 工程编译方法......................................................................................................35 6-2 设置AXD1.3.1................................................................................................................ 37 6-2-1 打开AXD1.3.1....................................................................................................37 6-2-2 针对JLINK 设置AXD...................................................................................... 37 6-2-3 更新Jlink 固件....................................................................................................39 6-2-4 检测目标CPU.....................................................................................................40 6-3 仿真一下,小试牛刀......................................................................................................42 第七章Jlink...................................................................................................................................45 7-1 全速运行.......................................................................................................................... 45 7-2 断点调试.......................................................................................................................... 45 7-3 单步调试.......................................................................................................................... 46 第八章S3C6410 GPIO.................................................................................................................47 第九章利用GPIO 控制OK6410 的LED.................................................................................48 9-1 实验目的.......................................................................................................................... 48 9-2 实验设备.......................................................................................................................... 48 9-3 实验内容.......................................................................................................................... 48 9-4 实验原理.......................................................................................................................... 48 9-5 实验电路.......................................................................................................................... 49 9-6 实验程序.......................................................................................................................... 49 9-7 实验步骤.......................................................................................................................... 50 9-8 实验结果.......................................................................................................................... 51 第十章GPIO 控制OK6410 的蜂鸣器.......................................................................................52 10-1 实验目的...................................................................................................................... 52 10-2 实验设备...................................................................................................................... 52 10-3 实验内容...................................................................................................................... 52 10-4 实验原理...................................................................................................................... 52 10-5 实验电路...................................................................................................................... 53 10-6 实验程序...................................................................................................................... 53 10-7 实验步骤...................................................................................................................... 54 10-8 实验结果...................................................................................................................... 55 第十一章GPIO 检测OK6410 的按键操作...............................................................................56 11-1 实验目的...................................................................................................................... 56 11-2 实验设备...................................................................................................................... 56 11-3 实验内容...................................................................................................................... 56 11-4 实验原理...................................................................................................................... 56 11-5 实验电路...................................................................................................................... 57 11-6 实验程序...................................................................................................................... 58 11-7 实验步骤...................................................................................................................... 60 11-8 实验结果...................................................................................................................... 61 第十二章利用定时器制作精确延时来控制OK6410 的LED...............................................62 12-1 实验目的...................................................................................................................... 62 12-2 实验设备...................................................................................................................... 62 12-3 实验内容...................................................................................................................... 62 12-4 实验原理...................................................................................................................... 62 12-5 实验电路...................................................................................................................... 63 12-6 实验程序...................................................................................................................... 63 12-7 实验步骤...................................................................................................................... 66 12-8 实验结果...................................................................................................................... 66 第十三章利用定时器精确控制OK6410 的蜂鸣器频率........................................................67 13-1 实验目的...................................................................................................................... 67 13-2 实验设备...................................................................................................................... 67 13-3 实验内容...................................................................................................................... 67 13-4 实验原理...................................................................................................................... 67 13-5 实验电路...................................................................................................................... 68 13-6 实验程序...................................................................................................................... 68 13-7 实验步骤...................................................................................................................... 70 13-8 实验结果...................................................................................................................... 70 第十四章总结...............................................................................................................................71

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值