我们今天来讲调试信息,这个东西讲起来会比较无聊,因为都是一些函数调用,没啥可讲的,函数就是那样用的,不过其效果挺好玩的,同时在程序设计中也是很必要的,所以还是来写一下,不过,就是因为知识比较固定且简单,所以我们 一篇就覆盖三节的内容吧:

1. 获取当前活动的顶点属性和对应索引

2.获取当前活动的uniform量和对应索引

2.Debug

Getting Ready

我们以上一节的旋转三角形的例子来讲这一篇。

当我们的shader program编译连接完成之后,所有的量都已经分配了自己的索引,这时候我们可以查看其信息。

我们默认连接好的shader program的句柄为programHandle

Getting a list of active vertex input attributes and locations

我们需要获取所有顶点属性信息,首先要知道有多少个顶点属性

glGetProgramInterfaceiv用来获取program中的一些状态信息。

它有四个参数:

第一个参数为:program 句柄,确定是哪一个程序中的状态信息

第二个参数为:我们要查询的是程序的哪一类数据资源

第三个参数为:我们要查询的量

第四个参数为:存储获取的信息

glGetProgramInterfaceiv(programHandle, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttribs);

即为,我们要获取programHandle这个着色器程序中有关程序输入(即为顶点属性)的数据信息,将当前处于活动状态的上述资源的数量( GL_ACTIVE_RESOURCES)存储到numAttribs中

接下来,我们需要循环获取顶点属性(数据资源,resource)信息

假如我们的numAttribs的值为6,我们对于每一都如此做:

glGetProgramResourceiv获取单个数据资源的状态信息

它一共有8个参数:

para1:shader program 句柄用于指定处理的是哪一个程序

para2:同上面那个函数的第二个参数,数据资源的类型

para3:查询的是第几个数据资源(0 ~ numAttribs-1)

para5:要查询数据资源的哪些信息,参数类型为枚举数组地址,用于记录要查询的所有查询信息

para4:para5中所传入的数组的size

para6:para8的数组中一个数据资源包含多少个信息元素

para7:第七个参数是一个指向整数的指针,该整数将接收被写入的数据组有多少组,如果para8为二维信息,即有很多组,每组数据为一维,那么需要该参数返回para8中有多少组,以便解析para8中的数据,而我们             这里的para8指定接收资源数据的一组信息,所以,此参数无效,我们可用nullptr来跳过该参数。

para8:用于接收系统返回的数据信息

glGetProgramResourceiv(programHandle, GL_PROGRAM_INPUT, i, 3, properties, 3, nullptr, results);

前两个就不用说了,我们要获取第 i 个数据资源(顶点属性量)的信息,其中一组信息有三种,它们存储在properties数组中:

GLenum properties[]{ GL_NAME_LENGTH, GL_TYPE, GL_LOCATION };        //数据资源的名字的长度,数据资源的数据类型,数据资源的索引值

我们需要将系统传出的数据每3个一组存入results中,返回。由于我们的results只记录一组返回信息,所以数据无需解析分组,所以para7为nullptr,如果为多组的二维信息,我们需要指定一个整型来接受返回数据。

如:glGetProgramResourceiv(programHandle, GL_PROGRAM_INPUT, i, 3, properties, 3, num, results);

num是一个GLint,那么意思是,results中存储着num组数据,每组数据有3个,如同二维数组传递参数一样,低维度的参数必须给定,也就是num前面的3,对吧~

最后,我们通过glGetProgramResourceiv获取数据资源的名字。

我们已经通过上面那个函数获取到了名字的长度,所以,我们创建一个缓冲区来接受字符串。

GLint nameBufSize = results[] + ;
GLchar* name = new char[nameBufSize];
glGetProgramResourceName(programHandle, GL_PROGRAM_INPUT, i, nameBufSize, nullptr, name);

至此,我们获取到了顶点属性量的名字

我们的名字以及索引都得到了,还需要将GL_TYPE获取到的类型枚举值换成字符串

const GLchar* getTypeString(GLenum type)
{
// There are many more types than are covered here, but
// these are the most common in these examples.
switch (type) {
case GL_FLOAT:
return "float";
case GL_FLOAT_VEC2:
return "vec2";
case GL_FLOAT_VEC3:
return "vec3";
case GL_FLOAT_VEC4:
return "vec4";
case GL_DOUBLE:
return "double";
case GL_INT:
return "int";
case GL_UNSIGNED_INT:
return "unsigned int";
case GL_BOOL:
return "bool";
case GL_FLOAT_MAT2:
return "mat2";
case GL_FLOAT_MAT3:
return "mat3";
case GL_FLOAT_MAT4:
return "mat4";
default:
return "?";
}
}

代码如下:

void getVertexAttribList(GLint programHandle)
{
GLint numAttribs;
glGetProgramInterfaceiv(programHandle, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &numAttribs); GLenum properties[]{ GL_NAME_LENGTH,GL_TYPE,GL_LOCATION };
cout << "Active attributes:" << endl;
for (int i = ; i < numAttribs; ++i)
{
GLint results[];
glGetProgramResourceiv(programHandle, GL_PROGRAM_INPUT, i, , properties, , nullptr, results); GLint nameBufSize = results[] + ;
GLchar* name = new char[nameBufSize];
glGetProgramResourceName(programHandle, GL_PROGRAM_INPUT, i, nameBufSize, nullptr, name);
cout << "location:" << results[] << " " << name << "(" << getTypeString(results[]) << ")" << endl;
delete[] name;
}
}

在main主程序中的着色器程序连接完成之后调用此函数即可得到如下测试结果:

没问题,嘻嘻

Getting a list of active uniform variables

void getUniformList(GLint programHandle)
{
GLint numUniforms = ;
glGetProgramInterfaceiv(programHandle, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms); GLenum properties[] = { GL_NAME_LENGTH, GL_TYPE, GL_LOCATION, GL_BLOCK_INDEX }; printf("Active uniforms:\n");
for (int i = ; i < numUniforms; ++i) {
GLint results[];
glGetProgramResourceiv(programHandle, GL_UNIFORM, i, , properties, , NULL, results); if (results[] != -) continue; // Skip uniforms in blocks
GLint nameBufSize = results[] + ;
char * name = new char[nameBufSize];
glGetProgramResourceName(programHandle, GL_UNIFORM, i, nameBufSize, NULL, name);
cout << "location:" << results[] << " " << name << "(" << getTypeString(results[]) << ")" << endl;
delete[] name;
}
}

唯一不同的一点是properties的第四个枚举量

它记录了当前查询的uniform量所在的uniform block,如果该uniform量不属于任何block,那么该元素对应的值为-1

这里,我们只查询单独的uniform量,所以当其GL_BLOCK_INDEX对应的返回值为-1的时候是我们所要的,反之,我们跳过。

Debug

在之前,我们获取调试信息的传统方法是调用glGetError。但是这是一种非常繁琐的方法,其繁琐程度就不再赘述了。

从OpenGL 4.3开始,我们现在支持更现代的调试方法。我们可以整一个调试回调函数,该函数将在发生错误或者生成其他警告提示性消息时执行。

不仅如此,我们还可以发送自己的自定义消息,由同一个回调处理,我们可以使用各种条件过滤消息​​。

注:context有翻译为上下文,有翻译为环境,个人比较倾向于环境一说,下文不做翻译

使用debug context 创建OpenGL程序。 虽然获取debug context 并非绝对必要,但我们可能无法获得与使用debug context 时相同的消息。

要在启用调试的情况下使用GLFW创建OpenGL context,在创建窗口之前要使用以下函数调用。

glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

默认情况下,OpenGL debug context 将启用调试消息。但是,如果需要显式启用调试消息,请使用以下调用。

glEnable(GL_DEBUG_OUTPUT);

我们采用如下步骤进行:
1.创建回调函数以接收调试消息。

该函数必须符合OpenGL文档中描述的特定原型。 我们采用如下方式:

void debugCallback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length,
const GLchar * message, void * param) {
// Convert GLenum parameters to strings
printf("%s:%s[%s](%d): %s\n", sourceStr, typeStr,
severityStr, id, message);
}

2.使用glDebugMessageCallback向OpenGL注册我们的回调:
glDebugMessageCallback(debugCallback,NULL);

3.启用所有消息,所有来源,所有级别和所有ID:
glDebugMessageControl(GL_DONT_CARE,GL_DONT_CARE,
       GL_DONT_CARE,0,NULL,GL_TRUE);

我们来解释一下上述的一些内容:

回调函数debugCallback有几个参数,其中最重要的是调试消息本身(第六个参数,message)。

对于此示例,我们只是将消息打印到标准输出,但我们可以将其发送到日志文件或其他目的地.

debugCallback的前四个参数描述消息的来源,类型,ID号和严重性。

id号是特定于消息的无符号整数。 下表中描述了sourcetypeSeverity参数的可能值。

Source

Generated By

GL_DEBUG_SOURCE_API

Calls to the OpenGL API

GL_DEBUG_SOURCE_WINDOW_SYSTEM

Calls to a window system API

GL_DEBUG_SOURCE_THIRD_PARTY

An application associated with OpenGL

GL_DEBUG_SOURCE_APPLICATION

This application itself.

GL_DEBUG_SOURCE_OTHER

Some other source
Type

Description

GL_DEBUG_TYPE_ERROR

An error from the OpenGL API.

GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR

Behavior that has been deprecated

GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR

Undefined behaviour

GL_DEBUG_TYPE_PORTABILITIY

Some functionality is not portable.

GL_DEBUG_TYPE_PERFORMANCE

Possible performance issues

GL_DEBUG_TYPE_MARKER

An annotation

GL_DEBUG_TYPE_PUSH_GROUP

Messages related to debug group push.

GL_DEBUG_TYPE_POP_GROUP

Messages related to debug group pop.

GL_DEBUG_TYPE_OTHER

Other messages
Severity Meaning

GL_DEBUG_SEVERITY_HIGH

Errors or dangerous behaviour

GL_DEBUG_SEVERITY_MEDIUM

Major performance warnings, other 

warnings or use of deprecated functionality.

GL_DEBUG_SEVERITY_LOW

Redundant state changes,

unimportant undefined behaviour.

GL_DEBUG_SEVERITY_NOTIFICATION

A notification, not an error or performance issue.

length参数是消息字符串的长度,不包括空终止符。 最后一个参数param是用户定义的指针。 我们可以使用它指向一些可能对回调函数有帮助的自定义对象。 例如,如果我们将消息记录到文件中,则可能指向包含文件I / O功能的对象。可以使用glDebugMessageCallback的第二个参数设置此参数。

在debugCallback中,我们将每个GLenum参数转换为字符串,此篇第一节中,我们写过getTypeString这个函数。

然后,我们将所有信息打印到标准输出。
对glDebugMessageCallback的调用使用OpenGL调试系统注册我们的回调函数。

第一个参数是指向我们的回调函数的指针,第二个参数(本例中为NULL)可以是指向我们想要传递给回调的任何对象的指针。

每次调用debugCallback时,此指针都作为最后一个参数传递。

最后,对glDebugMessageControl的调用确定了我们的消息过滤器。

此功能可用于有选择地打开或关闭消息源,类型,ID或严重性的任何组合。 在这个例子中,我们打开了一切。

一些扩展内容,可能不会用到,可跳过

OpenGL还为命名调试组的堆栈提供支持。 基本上这意味着我们可以记住堆栈上的所有调试消息过滤器设置,并在稍后进行一些更改后返回它们。 这可能很有用,例如,如果有一些代码段我们需要过滤某些类型的消息,而其他段我们需要一组不同的消息。涉及的函数是glPushDebugGroup和glPopDebugGroup。 对glPushDebugGroup的调用会生成类型为GL_DEBUG_TYPE_PUSH_GROUP的调试消息,并在堆栈上保留调试过滤器的当前状态。 然后我们可以使用glDebugMessageControl更改我们的过滤器,然后使用glPopDebugGroup返回到原始状态。 类似地,函数glPopDebugGroup生成类型为GL_DEBUG_TYPE_POP_GROUP的调试消息。

第三部分主要是用于我们下一篇的类所用的,暂时没有相关的测试

感觉像是在写说明书,没有办法,这种章节的特点就是这样,但又比较重要~

感谢您的阅读,生活愉快~

OpenGL笔记<5> shader 调试信息获取 Debug的更多相关文章

  1. Keil ARM-CM3 printf输出调试信息到Debug (printf) Viewer

    参考资料:http://www.keil.com/support/man/docs/jlink/jlink_trace_itm_viewer.htm 1.Target Options -> De ...

  2. OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式

    OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 --是什么(答案是具体值) VS 是不是(答案是布尔值) 目录 背景介绍 问题描述 Codea 是 iPad 上的一款很方便 ...

  3. OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型

    OpenGL ES 2.0 Shader 调试新思路(二): 做一个可用的原型 目录 背景介绍 请参考前文OpenGL ES 2.0 Shader 调试新思路(一): 改变提问方式 优化 ledCha ...

  4. C# Debug和Trace:输出调试信息

    在 C# 语言中允许在程序运行时输出程序的调试信息,类似于使用 Console.WriteLine 的方式向控制台输出信息.所谓调试信息是程序员在程序运行时需要获取的程序运行的过程,以便程序员更好地解 ...

  5. C#报错:创建调试信息文件 ……obj\Debug\model.pdb: 拒绝访问

    错误:创建调试信息文件“.......\obj\Debug\model.pdb”时发生错误 --“......\obj\Debug\model.pdb: 拒绝访问. 解决办法如下: 删除该项目下的 b ...

  6. C# trace debug TraceListener调试信息详解

    在C#编程中,可能要碰到把调试信息输出的问题,我们可以自己把信息显示在某个控件上,但是MS自己提供了一套机制帮助我们输出一些调试信息,这些信息有助于我们判断程序的走向,不用自己再去额外写调试代码了. ...

  7. INV 调试: 如何获取库存物料事务处理调试信息

     1. 按如下方式设置系统配置文件值: 系统配置文件值 地点/用户/应用/职责层配置文件值 --汇总 FND: 启用调试日志   是 FND:调试日志层级   陈述 INV: 调试跟踪: 是 IN ...

  8. [QT_QML]qml假如调试信息 qDebug console.debug

    WinSys: win7 Qt Version: 5.8.0 使用Console调试 console.log 打印日志信息console.debug 打印调试信息console.info 打印普通信息 ...

  9. 【转】 C# DEBUG 调试信息打印及输出详解

    [转] C# DEBUG 调试信息打印及输出详解 1.debug只在[debug模式下才执行](运行按钮后面的下拉框可选) 2.debug提供了许多调试指令,如断言          System.D ...

随机推荐

  1. 安装Win8引起Ubuntu启动项丢失的恢复过程

    画电路图的时候手痒,于是将之前做好的Win8PE拿出来装着玩儿.至于Win8的pE很好做,用UltraISO将Win8 的镜像用制作硬盘镜像的方法烧进U盘就行了. Win8的安装过程也很简单.安装前为 ...

  2. php魔术函数 __clone()

    原文地址: http://www.nowamagic.net/librarys/posts/php/32 PHP4面向对象功能一个很大的缺点,是将对象视为另一种数据类型,这使得很多常见的OOP方法无法 ...

  3. C++ Primer 5th 第18章 用于大型程序的工具

    C++大规模程序设计至少存在三个特殊要求: 错误处理 库的引入 复杂建模 以上三种对应C++语言的三种特性:异常处理.命名空间.多重继承. 异常处理 异常处理机制是一种允许偷懒的工具,在出现非正确的情 ...

  4. MongoDB以Windows Service运行

    以Administrator身份打开CMD并输入以下命令 cd D:\Developer\MongoDB\mongodb-win32-x86_64-2.4.6\binD:mongod --logpat ...

  5. 20155303 2016-2017-2 《Java程序设计》第九周学习总结

    20155303 2016-2017-2 <Java程序设计>第九周学习总结 目录 学习内容总结(Linux命令) 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考 ...

  6. 【Nginx】 Nginx实现端口转发

    什么是端口转发 当我们在服务器上搭建一个图书以及一个电影的应用,其中图书应用启动了 8001 端口,电影应用启动了 8002 端口.此时如果我们可以通过 localhost:8001 //图书 loc ...

  7. java 面试算法题

    /** * 设有n个人依围成一圈,从第1个人开始报数,数到第m个人出列,然后从 * 出列的下一个人开始报数,数到第m个人又出列,…,如此反复到所有的人全部出列为 * 止.设n个人的编号分别为1,2,… ...

  8. 1 - django-介绍-MTV-命令-基础配置-admin

    目录 1 什么是web框架 2 WSGI 3 MVC与MTV模式 3.1 MVC框架 3.2 MTV框架 3.3 区别 4 django介绍 4.1 Django处理顺序 4.2 创建django站点 ...

  9. AngularJS中ng-class使用方法

    转自:https://blog.csdn.net/jumtre/article/details/50802136 其他博文ng-class使用方法:https://blog.csdn.net/sina ...

  10. java基础46 IO流技术(输出字符流/缓冲输出字符流)

    一.输出字符流 1.1.输出字符流体系 --------| Writer:输出字符流的基类(抽象类)  ----------| FileWriter:向文件输出数据输出字符流(把程序中的数据写到硬盘中 ...