Adreno OpenGL ES 2.0 介绍(7)
调试OpenGL ES应用程序(2)
着色器调试
可能会出现以下情况:渲染故障不是由不正确的OpenGL ES API使用引起的,而是由隐藏在构成绘画调用所用程序的着色器之一中某个地方的错误引起的。 以下是有关如何处理此类情况的一些技巧。
- 首先确保为顶点着色器定义的所有输入属性都传递正确的值。 例如,如果照明无法正常工作,请首先验证用于计算的常规数据是否有效,例如,通过将未修改的常规数据传递给片段着色器进行检查,以通过目视检查来验证每个顶点 被分配了正确的向量值。
注意:修改着色器时要小心。 例如,如果开发人员注释掉了现有的实现并将其替换为将法线向量传递给片段着色器的代码,则可能导致许多现有的输入属性和制服失效。 根据应用程序和着色器的编写方式,这可能会使错误更难以跟踪。 而不是删除整个主体,而是安排可能对结果值有贡献的所有其他变量乘以非常小的值,例如对于内部格式(每个组件使用8位)的1.0 / 256.0,这样它们就不会隐藏 目视检查的结果值。
- 对着色器使用的所有制服执行相同的操作。 要特别注意统一的区组成员。 确保着色器定义与应用程序相同的统一块布局。
- 如果怀疑某些计算可能执行不正确,请使用变换反馈将数据从渲染管道传输回该流程。 变换反馈允许检查数据是否正确地通过了整个渲染管道,但片段着色器阶段除外。 当开始使用几何和/或细分控制/评估着色器时,这一点尤其重要。
- 如果平台支持几何体着色器,请使用它们来发出辅助几何体,例如法线向量。
- 如果某些纹理未正确采样,则很可能认为它们不完整。 最简单的检查方法是选择GL_NEAREST缩小过滤,并将GL_TEXTURE_BASE_LEVEL和GL_TEXTURE_MAX_LEVEL设置为已上传的Mipmap的索引。
- 如果仍然无法访问纹理,请确保没有采样器对象覆盖已绑定该纹理的纹理单元的纹理参数。 验证采样器制服是否设置为使用相应的纹理单位。
- 使用Adreno Profiler工具编辑着色器并实时调查结果。
剖析OpenGL ES应用程序
如果应用程序表现不佳,则第一步是确定花费太长时间的渲染管线部分。 不幸的是,鉴于OpenGL ES是异步工作的,仅记录每个渲染过程前后的时间并检查时间差是不够的,给出的值通常仅显示驱动程序在命令中存储请求所花的时间 缓冲。
以下是几种衡量渲染管线特定部分占用的GPU时间的方法:
- 从OpenGL ES 2.0开始,如果要测量一组给定的API调用所花费的时间,请使用glFinish调用来分隔该区域。 记录刚好在第一次glFinish调用之后的开始时间,以及刚好在第二次glFinish调用之后的结束时间。 时间差将告诉您执行该块所需的时间。 此方法的准确性不如以下方法高,因为在将执行流返回给调用方之前需要进行更长的往返行程。 由于第一个glFinish调用必须等待,直到所有先前排队的命令在GPU上完成执行,这也会导致整体渲染性能进一步下降。
- 如果使用OpenGL ES 3.0,一种更有效的方法是将同步对象用作重量级glFinish调用的轻量级替代方案。 这样做,请遵循第一个解决方案中使用的相同模式,但将每个glFinish调用替换为以下代码:
GLsync sync;
sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glClientWaitSync(sync);
注意:完成测量后,请不要忘记使用glDeleteSync释放同步对象。