Adreno OpenGL ES 2.0 介绍(6)

46 篇文章 22 订阅
43 篇文章 6 订阅

Adreno OpenGL ES 2.0 介绍(6)

调试OpenGL ES应用程序(1)

1 使用glGetError

OpenGL ES API是严格的C API,这意味着它检测到的任何错误都将通过异常报告。 OpenGL ES应用程序检测错误的基本方法是使用glGetError调用。 可以在绑定了渲染上下文的任何线程中发出此调用。

如果进行了无效的调用,则可以返回一系列不同的错误代码。 通常的规则是,如果OpenGL ES检测到错误,则违规命令不会导致OpenGL ES状态的任何修改,也不会栅格化任何样本。 错误代码GL_OUT_OF_MEMORY在这里是一个明显的异常。 当驱动程序端的内存分配请求失败时,将报告此错误。 如果应用程序检测到此错误,则应假定OpenGL ES状态已变为未定义。 可能采取的最安全的步骤是终止该过程。

OpenGL ES可以报告的所有错误代码是:

  • GL_INVALID_ENUM –传递给函数的GLenum参数之一无效。造成这种情况的一个常见原因是,当扩展名实际上不可用时,开发人员将其定义为OpenGL ES扩展的一部分。另一个原因是
    该值根本不正确。
  • GL_INVALID_FRAMEBUFFER_OPERATION –要求完成绘制和/或读取帧缓冲区的API函数,但并非如此。请注意,并非所有API函数都要求这样做。如果OpenGL ES也可以报告此错误代码
    实现不支持渲染到特定的帧缓冲区配置,在这种情况下,应用程序应为相关的帧缓冲区使用不同的内部格式集。
  • GL_INVALID_OPERATION –考虑到当前OpenGL ES状态配置,尝试执行的操作无效。该错误代码含糊不清,必须缩小有问题的命令以查找错误原因。特别是对于大型应用程序,这可能不是一件容易的事。
  • GL_INVALID_VALUE –传递给函数的数字参数无效。通常由于与GL_INVALID_ENUM中所述类似的原因而发生。
  • GL_OUT_OF_MEMORY –驱动程序尝试执行命令时内存不足。应用程序应尽快终止,因为不能再假定工作环境是稳定的。

上面给出了错误的一般性描述,但是更具体的解释取决于导致错误的命令。

glGetError不会告诉应用程序哪个命令报告了错误,并且可以由驱动程序隐式调用的OpenGL ES命令报告错误。 例如,当驾驶员先前已决定推迟诸如绘图呼叫之类的呼叫,并且现在在处理另一个命令的过程中内部发出该呼叫时。

在内部,当驱动程序在API调用中检测到错误时,它会引发与代码之一相对应的标志。 如果检测到其他错误,则它们不会影响记录的错误状态。 调用glGetError时,将返回缓存的错误代码,并降低该标志,以便后续的glGetError调用返回GL_NO_ERROR。

由于Adreno驱动程序将API调用缓存在命令缓冲区中,因此glGetError调用可以认为是昂贵的,因为它们会刷新管道并等待所有缓冲的命令完成。 除非性能对应用程序不重要,否则建议不要在每个API调用之后插入glGetError调用,至少在发行版本中不建议插入。 一个不错的折衷方法是在关键位置插入后卫glGetError调用,仅用于调试版本。 使用这种方法的性能在生产版本中不会受到影响,并且在出现错误报告的情况下,团队很快就可以准备可用于定位导致问题的渲染管道部分的调试版本。

使用GL_KHR_debug
使用glGetError有一些明显的限制。

  • 错误代码不能传达有关错误类型的准确信息。
  • 要解决问题,程序员必须首先弄清楚哪个OpenGL ES API调用导致了引发错误,然后必须查看更大的图片(例如OpenGL ES状态),以了解为什么是错误代码在 生成的。 这占用了开发时间,而开发时间本来可以花在实现新功能上。
  • 没有办法让驱动程序对应用程序进行回调,以便程序员可以插入断点来找出问题所在和出处。

Adreno驱动程序支持名为GL_KHR_debug的特殊扩展,该扩展旨在满足这些需求,并包括许多功能,以增强OpenGL ES开发人员的调试体验。

以下部分重点介绍与调试OpenGL ES应用程序最相关的功能,并将概述API。 有关更多详细信息,请参见https://www.opengl.org/registry/specs/KHR/debug.txt

当支持GL_KHR_debug扩展时,应用程序可以通过调用glDebugMessageCallbackKHR来注册驱动程序回调。 该函数允许注册回调函数指针和可选的用户指定参数。 OpenGL ES使用该回调来以人可读的,以NULL终止的字符串的形式向应用程序提供反馈。 反馈可以包含有关为什么会生成错误代码的详细信息,以及以下类型的信息:

  • 有关使用不推荐使用的功能或在规范中标记为未定义的警告
  • 与实现有关的性能警告
  • 有关以特定于供应商的方式使用扩展或着色器的警告
  • 用户注入的消息
  • 调试组堆栈通知(在下面发现)
    每个反馈消息都带有一组枚举,这些枚举提供有关以下内容的信息:
  • 消息的来源(驱动程序,着色器编译器,窗口系统等)
  • 消息的ID
  • 消息的类型(错误报告,性能警告,可移植性提示等)
  • 消息的严重性级别(高,中,低,通知)

仅当通过调用glEnable启用GL_DEBUG_OUTPUT_STATE_KHR时,才会发生回调。 要再次禁用该功能,请为相同的状态枚举调用glDisable。

应用程序可以通过调用glDebugMessageInsertKHR将自己的消息注入调试流。 这对于中间件特别有用,中间件可以使用该机制向开发人员提供提示或检测到任何错误情况的通知。

驱动程序生成的所有消息或使用glDebugMessageInsertKHR插入命令流的所有消息均被写入活动的调试组,该组是调试组堆栈的顶部。 可以通过调用gl-PushDebugGroupKHR将新的调试组(由用户指定的消息标识)推入堆栈。 可以通过调用glPopDebugGroupKHR将现有的调试组弹出堆栈。 每当将调试组推入调试组堆栈或从中弹出时,与该组关联的消息都将插入到流中。 一个示例用例是使用调试组来标记每个渲染过程的开始和结束。

该应用程序可以通过调用glDebugMessageControlKHR过滤掉不需要的消息。 消息的任何属性都可以用作过滤键。 这称为音量控制。 音量控制设置适用于活动的调试组,如果将新的调试组推入堆栈,则将继承该设置。

如果应用程序未注册回调函数,但启用了GL_DEBUG_OUTPUT_STATE_KHR,则消息将存储在消息日志中。 该日志最多可容纳GL_MAX_DEBUG_LOGGED_MESSAGES条消息。 一旦存储空间已满,所有后续生成的消息都将被丢弃,直到应用程序通过获取一个或多个消息释放一些空间为止。 可以通过调用glGetDebugMessageLogKHR来获取消息,该函数将返回消息字符串和每个消息的相关属性。

GL_KHR_debug扩展提供的另一个有用的功能是能够以两种不同的模式提供回调信息:

  • 异步模式(默认情况下处于活动状态)– OpenGL ES实现可以从多个线程(包括当前未绑定生成消息的上下文的线程)并发地调用调试回调例程(示例包括但不限于其他线程 上下文是绑定的,或者是驱动程序内部使用的线程)。 在生成消息的OpenGL ES命令已经返回之后,它也可以异步发出回调。 当异步模式处于活动状态时,应用程序负责确保线程安全。
  • 同步模式–每个渲染上下文不允许驱动程序一次发出多个回调。 回调将在允许生成调试消息的OpenGL ES命令返回之前进行。 同步模式会导致所有调用都被隐式刷新,因此性能会大大降低。 但是,考虑到回调是在OpenGL ES API调用时发生的,该模式极大地简化了开发人员的调试过程。

可以通过调用glEnable为显式启用同步模式
GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR模式。 为了使应用程序返回到异步调试模式,可以为相同的枚举调用glDisable。

GL_KHR_debug扩展还允许开发人员使用glObjectLabelKHR和glObjectPtrLabelKHR函数以NULL终止的字符串标记OpenGL ES对象。 以后可以使用glGetObjectLabelKHR glGetObjectPtrLabelKHR检索标签。 这可以帮助您在调试过程中轻松识别OpenGL ES对象,而无需遍历应用程序的内部数据模型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值