OpenGL ES 框架详细解析(十三) —— Xcode OpenGL ES工具概述

版本记录

版本号 时间
V1.0 2017.10.03

前言

OpenGL ES是一个强大的图形库,是跨平台的图形API,属于OpenGL的一个简化版本。iOS系统可以利用OpenGL ES将图像数据直接送入到GPU进行渲染,这样避免了从CPU进行计算再送到显卡渲染带来的性能的高消耗,能带来来更好的视频效果和用户体验。接下来几篇就介绍下iOS 系统的 OpenGL ES框架。感兴趣的可以看上面几篇。
1. OpenGL ES 框架详细解析(一) —— 基本概览
2. OpenGL ES 框架详细解析(二) —— 关于OpenGL ES
3. OpenGL ES 框架详细解析(三) —— 构建用于iOS的OpenGL ES应用程序的清单
4. OpenGL ES 框架详细解析(四) —— 配置OpenGL ES的上下文
5. OpenGL ES 框架详细解析(五) —— 使用OpenGL ES和GLKit进行绘制
6. OpenGL ES 框架详细解析(六) —— 绘制到其他渲染目的地
7. OpenGL ES 框架详细解析(七) —— 多任务,高分辨率和其他iOS功能
8. OpenGL ES 框架详细解析(八) —— OpenGL ES 设计指南
9. OpenGL ES 框架详细解析(九) —— 调整您的OpenGL ES应用程序
10. OpenGL ES 框架详细解析(十) —— 使用顶点数据的最佳做法
11. OpenGL ES 框架详细解析(十一) —— 并发和OpenGL ES
12. OpenGL ES 框架详细解析(十二) —— 采用OpenGL ES 3.0

Xcode OpenGL ES Tools Overview - Xcode OpenGL ES工具概述

用于调试,分析和调整OpenGL ES应用程序的Xcode工具在开发的所有阶段都很有用。 FPS Debug Gauge和GPU报告总结了每次从Xcode运行时的应用程序GPU性能,因此您可以在设计和构建渲染器时快速查看性能问题。 找到故障点后,捕获一帧并使用Xcode的OpenGL ES Frame Debugger界面来精确定位渲染问题并解决性能问题。

有效地使用Xcode OpenGL ES功能需要熟悉Xcode的调试界面。 有关背景信息,请阅读Xcode User Guide


Using the FPS Debug Gauge and GPU Report - 使用 the FPS Debug Gauge and GPU 报告

如图B-1所示,FPS调试指示器和随附的GPU报告提供了应用程序运行时的OpenGL ES性能的高级摘要。 通过在开发应用程序时监控这些显示,您可以发现性能问题,并考虑在哪里集中调整工作。

Figure B-1 FPS Debug Gauge and GPU Report

注意:FPS测量仪和GPU报告的某些功能依赖于display link定时器。 如果您不使用CADisplayLinkGLKViewController类来动画化OpenGL ES显示,则仪表和报告将无法显示相对于目标帧速率的性能或提供准确的CPU帧时间信息。

调试计和报告包含以下显示:

  • FPS Gauge。显示您的应用程序的当前动画速率(以每秒帧数(FPS))和最近的FPS读数历史记录。 单击此计量器可在Xcode的主编辑器中显示GPU报告。
  • Frames Per Second。 显示当前帧速率,相对于您的应用设置的目标帧速率(通常为30或60 FPS)。 蓝色弧表示最近的FPS读数范围。
  • Utilization。 显示三个条状图,分解您的应用程序对GPU上不同处理资源的使用情况,并指出在使用图形硬件时性能瓶颈的可能位置。
    • The Tiler bar可以测量GPU的几何处理资源的使用。 高层次利用率可以表明OpenGL ES流水线的顶点和原始处理阶段的性能瓶颈,例如使用无效的顶点着色器代码或每帧画出过多数量的顶点或图元。
    • The Renderer bar可以使用GPU的像素处理资源。 高渲染器利用率可以指示OpenGL ES管道的片段和像素处理阶段的性能瓶颈,例如使用无效的片段着色器代码或处理每个帧用于颜色混合的附加片段。
    • The Device bar显示了GPU的整体使用情况,并结合了tilerrenderer的使用。
  • Frame Time。 显示在CPU和GPU上处理每个帧的时间。 此图可以指示您的应用程序是否有效使用CPU / GPU并行性。

如果您的应用程序花费更多的CPU处理时间,您可以通过将工作转移到GPU来提高性能。 例如,如果每个帧需要许多类似的glDrawArraysglDrawElements调用,那么可以使用硬件实例来减少CPU开销。 (有关详细信息,请参阅 Use Instanced Drawing to Minimize Draw Calls

如果您的应用程序在GPU处理中花费更多时间,则可以通过将工作移到CPU来提高性能。 例如,如果着色器在特定绘制调用期间对每个顶点或片段执行与相同结果相同的计算,则可以在CPU上执行该计算一次,并将其结果传递给均匀变量中的着色器。 (请参阅Use Uniforms or Constants Instead of Computing Values in a Shader)。

  • Program Performance。捕获帧后才会出现(请参阅下面的Capturing and Analyzing an OpenGL ES Frame ),显示渲染捕获帧时花费在每个着色器程序中的时间,以毫秒为单位,占总帧渲染时间的百分比。 扩展程序的列表显示使用该程序进行的绘图调用和每个渲染时间的贡献。 选择列表中的程序以在助理编辑器中查看其着色器源代码,或单击绘图调用旁边的箭头图标,以在框架导航器中选择该调用(请参阅下面的Navigator Area)。

注意:仅在支持OpenGL ES 3.0的设备上进行调试时,才会显示“程序性能”视图(无论您的应用程序是使用OpenGL ES 3.0还是2.0上下文)。

调整应用程序时,您可以使用此图形来查找优化的机会。 例如,如果一个程序占用帧渲染时间的50%,则通过优化它可以获得更多的性能,而不是通过提高仅占帧时间的10%的程序的速度。 虽然这个视图通过着色器程序组织帧时间,但请记住,改善着色器算法不是优化应用程序性能的唯一方法 - 例如,您还可以减少使用昂贵的着色器程序的绘图调用次数,或者减少 由慢片段着色器处理的片段数。

  • Problems & Solutions。只有在Xcode分析帧捕获后才会显示(请参阅Capturing and Analyzing an OpenGL ES Frame),此区域列出了分析期间发现的可能问题以及提高性能的建议。

当您在捕获的帧中更改GLSL着色器程序(请参阅下面的Editing Shader Programs)时,帧时间和程序性能图展开,以显示原始捕获的帧的基线渲染时间和使用已编辑的渲染着色器的当前渲染时间。


Capturing and Analyzing an OpenGL ES Frame - 采集和分析OpenGL ES帧

要详细了解您的应用程序的OpenGL ES使用情况,请捕获用于渲染单帧动画的OpenGL ES命令的顺序。 Xcode提供了几种开始帧捕获的方法:

  • Manual capture。在Xcode中运行应用程序时,单击调试栏中的相机图标(如图B-2所示),或者从Debug菜单中选择Capture OpenGL ES Frame
Figure B-2 Debug Bar with Capture OpenGL ES Frame button

注意:只有当您的项目与OpenGL ES或Sprite Kit框架相连时,Capture Open ES ES Frame按钮才会自动出现。 您可以通过编辑活动方案来选择是否显示给其他项目。 (请参阅About the Scheme Editing Dialog)。

  • Breakpoint action。断点动作。 选择Capture OpenGL ES Frame作为任何断点的操作。 当调试器通过此操作到达断点时,Xcode会自动捕获一个帧。 (请参阅Setting Breakpoint Actions and Options),如果在开发应用程序时使用此操作与OpenGL ES错误断点(请参阅 Adding an OpenGL ES Error Breakpoint),每当发生错误的时候,可以使用OpenGL ES Frame Debugger调查OpenGL ES错误的原因 。

  • OpenGL ES event marker。通过在OpenGL ES命令流中插入事件标记以编程方式触发帧捕获。 以下命令插入如下标记:

glInsertEventMarkerEXT(0, "com.apple.GPUTools.event.debug-frame")

当OpenGL ES客户端到达此标记时,它完成渲染帧,然后Xcode自动捕获用于渲染该帧的整个命令序列。

Xcode捕获帧后,会显示OpenGL ES Frame Debugger界面。 使用此界面来检查渲染帧的OpenGL ES命令的顺序,并检查OpenGL ES资源,参见Touring the OpenGL ES Frame Debugger

此外,Xcode可以对应用程序的OpenGL ES使用情况进行自动分析,以确定渲染器和着色器架构的哪些部分可以从性能优化中获益最多。 要使用此选项,请单击GPU报告顶部的分析按钮(如Figure B-1右上方所示)。

当您单击“分析”按钮时,Xcode将捕获一个框架(如果尚未被捕获),则通过使用附加的iOS设备进行一系列实验来运行渲染代码。 例如,要查看渲染速度是否受到纹理大小的限制,Xcode将运行OpenGL ES命令的捕获序列,同时将您的应用程序提交到GPU的纹理数据和大小减小的纹理集合。 在Xcode完成分析之后,GPU报告的Problems & Solutions领域列出了所发现的任何问题,并提出可能的性能改进建议。


Touring the OpenGL ES Frame Debugger - 浏览OpenGL ES帧调试器

Xcode捕获帧后,会自动重新配置OpenGL ES调试界面。 OpenGL ES Frame Debugger界面修改了Xcode工作区窗口的几个区域,以提供有关OpenGL ES渲染过程的信息,如图B-3和图B-4所示,并在下面进行了总结。 (框架调试器不使用检查器或库工作板,因此您可能希望在OpenGL ES调试期间隐藏Xcode的实用程序区域。)

Figure B-3 Frame debugger examining draw calls and resources
Figure B-4 Frame debugger examining shader program performance and analysis results

1. Navigator Area - 导航区域

在OpenGL ES帧调试器界面中,调试导航器由OpenGL ES帧导航器替代。 该导航仪显示OpenGL ES命令,可以渲染捕获的帧,按顺序或根据其相关的着色器程序进行组织。 使用框架导航器顶部的Frame View Options弹出菜单在视图样式之间切换。

Figure B-5 View Frame By popup menu in navigator

View Frame By Call - 按调用查看帧

当您要依次研究OpenGL ES命令以查明错误,诊断呈现问题或识别常见性能问题时,通过调用查看捕获的帧。 在此模式下,框架导航器按照您的应用程序所称的顺序列出命令。 导致OpenGL ES错误或可能指示性能问题的命令旁边出现错误或警告图标。

您可以通过使用glPushGroupMarkerEXTglPopGroupMarkerEXT函数为OpenGL ES命令组添加结构来添加结构,这些组显示为可以展开或折叠以显示更多或更少细节的文件夹。 (有关详细信息,请参阅 Annotate Your OpenGL ES Code for Informative Debugging and Profiling),您还可以展开OpenGL ES命令,以显示堆栈跟踪,指示应用程序代码中发出命令的位置。

使用上下文菜单来选择是否缩写命令名称以及要显示的命令,组和警告。 使用导航器底部的标志图标在显示所有OpenGL ES命令之间切换,并仅显示绘制到帧缓冲区中的那些。

单击OpenGL ES命令列表将导航到OpenGL ES命令序列中的那一点,影响帧调试器接口其他区域的内容,如下所述,并显示OpenGL ES调用的效果并附加设备的显示。

View Frame By Program - 按程序查看帧

当您要分析在每个着色器程序上花费的GPU时间和绘制命令时,可以通过程序查看捕获的帧。

展开程序的列表,以查看每个着色器在程序和每个绘图调用中的时间贡献。 展开一个绘图调用的列表,以显示一个堆栈跟踪,指示您的应用程序代码中发出该命令的位置。

使用上下文菜单来优化显示 - 您可以选择程序是按照其时间贡献进行排序的,以及时间信息是否以总渲染时间的百分比显示。

单击程序或着色器将在主编辑器中显示相应的GLSL源代码。 单击OpenGL ES命令将导航到帧捕获序列中的那一点。

注意:按程序查看帧选项仅在支持OpenGL ES 3.0的设备上进行调试时可用(无论您的应用程序是否使用OpenGL ES 3.0或2.0上下文)。 在其他设备上,框架视图选项弹出菜单被禁用。

2. Editor Area - 编辑区

使用帧捕获时,您可以使用主编辑器预览要渲染的帧缓冲区,还可以使用助手编辑器来检查OpenGL ES资源并编辑GLSL着色器程序。 默认情况下,助理编辑器显示OpenGL ES上下文所有资源的图形概述,如图Figure B-3.所示。 使用助理编辑器的跳转栏仅显示为框架导航器中选择的调用使用的资源,或者选择一个单独的资源进行进一步检查。 您也可以双击概述中的资源进行检查。 当您选择资源时,助理编辑器将更改为适合该资源类型的任务的格式。

Previewing Framebuffer Contents - 预览Framebuffer内容

主编辑器显示由帧导航器中当前选择的绘图调用渲染的帧缓冲区的内容。 (如果帧导航器中所选的OpenGL ES命令不是绘图命令,例如,设置诸如glUseProgram之类的状态的命令,则framebuffer会反映在选择之前由最近的绘图调用完成的渲染。)您也可以 使用主编辑器顶部的跳转条导航OpenGL ES命令的序列。

Figure B-6 Framebuffer info popover

编辑器显示当前为绘图绑定的每个帧缓冲附件的预览。 例如,3D渲染的大多数方法都使用具有颜色和深度附件的帧缓冲区,如图所示。 使用编辑器左下角的控件选择当前显示的帧缓冲附件。 单击每个帧缓冲附件名称左侧的信息按钮,显示一个弹出窗口,详细说明附件的属性,如图B-6所示。 单击framebuffer附件名称右侧的设置按钮,以显示具有调整预览图像的控件的弹出窗口。 例如,您可以使用这些控件在深度缓冲区中在其灰阶预览中使一定范围的Z值更可见,如图B-7所示。

Figure B-7 Framebuffer settings popover

每个帧缓冲附件预览还显示一个绿色线框,突出显示当前绘图调用的效果(如图 Figure B-3所示)。 使用预览图像中的上下文菜单来选择是否突出显示在预览中或显示连接的设备上。

Editing Shader Programs - 编辑着色器程序

当您在助手编辑器的跳转栏或资源概述中选择着色程序时,助手编辑器将显示该程序片段着色器的GLSL源代码(如图B-8所示)。 当您在框架导航器中选择一个程序(请参阅View Frame By Program)时,主编辑器显示程序的片段着色器,助手编辑器显示其顶点着色器。 在显示片段着色器的任何编辑器中,您可以使用跳转条切换到其对应的顶点着色器,反之亦然。

Figure B-8 GLSL shader source editor with update button

着色器源代码的每一行在右边距中突出显示,表示其对渲染时间的相对贡献。 使用这些来集中您的着色器优化工作 - 如果几行占用更多的渲染时间,可以查看更快的替代方案。 (有关着色器性能提示,请参阅Best Practices for Shaders。)

您可以在编辑器中更改着色器源代码。 然后,单击编辑器下方的更新按钮(如图Figure B-8所示)重新编译着色器程序,并查看其对捕获帧的影响。 如果编译着色器会导致GLSL编译器发生错误或警告消息,则Xcode会为每个问题注释着色器源代码。 重新编译的着色器程序在设备上仍然使用,因此您可以恢复运行应用程序。 单击调试栏中的继续按钮以查看您的着色器更改的操作。

Inspecting Vertex Data - 检查顶点数据

当您检查数组缓冲区时,助理编辑器显示缓冲区的内容(参见图B-9)。 因为OpenGL ES内存中的缓冲区没有定义的格式,您可以使用编辑器底部的弹出菜单来选择其内容的显示方式(例如,32位整数或浮点值,或两倍于 许多16位整数或半浮点值)以及Xcode用于显示数据的列数。

Figure B-9 Assistant editor previewing array buffer contents

顶点数组对象(VAO)将一个或多个数据缓冲区封装在OpenGL ES存储器中,以及用于将顶点数据从缓冲区提供给着色器程序的属性绑定。 (有关使用VAO的详细信息,请参阅Consolidate Vertex Array State Changes Using Vertex Array Objects)由于VAO绑定包含有关缓冲区内容格式的信息,因此检查VAO会显示OpenGL ES解释的内容(参见图B-10)。

Figure B-10 Assistant editor previewing vertex array object

Viewing Textures or Renderbuffers - 查看纹理或帧缓冲区

当您检查纹理或渲染缓冲区时,助理编辑器将显示其内容的图像预览。 您可以使用主编辑器中找到的相同控件来获取有关纹理对象或渲染缓冲区的更多信息,并调整图像预览。 对于纹理,您可以使用助手编辑器左下角的附加控件预览多维数据集地图纹理的每个面的纹理和(如果适用)的每个mipmap级别(如图B-11所示)。

Figure B-11 Assistant editor previewing cube map texture

3. Debug Area - 调试区

调试栏提供多个控件,用于浏览捕获的OpenGL ES命令序列(如图B-12所示)。 您可以使用其菜单来跟踪帧导航器中显示的层次结构,并选择一个命令,也可以使用箭头和滑块按顺序前后移动。 按继续按钮结束框架调试并返回运行应用程序。

Figure B-12 OpenGL ES debug bar

框架调试器没有调试控制台。 相反,Xcode提供了多个变量视图,每个视图都提供了OpenGL ES渲染过程当前状态的不同摘要。 使用弹出菜单在可用变量视图之间进行选择,在以下部分中讨论。

The All GL Objects View - 所有GL对象视图

所有GL对象视图与图B-13右侧所示的“绑定GL对象”视图类似,列出了与辅助编辑器中图形概述相同的OpenGL ES资源。 然而,与图形概述不同,当您扩展其显示三角形时,此视图可以提供有关资源的更详细信息。 例如,扩展帧缓冲区或缓冲区对象的列表显示仅通过OpenGL ES查询功能(如glGetBufferParameterglGetFramebufferAttachmentParameter)可用的信息。 扩展着色器程序的列表显示其状态,属性绑定和每个统一变量的当前绑定值。

The Bound GL Objects View - 绑定GL对象视图

B-13右侧所示的“绑定GL对象”视图的行为与All GL Objects view视图相同,但仅列出当前要绑定的资源,用于框架导航器中所选的OpenGL ES命令。

Figure B-13 Debug area with GL Context and Bound GL Objects views

The GL Context View - GL上下文视图

B-13左侧的GL上下文视图列出了OpenGL ES渲染器的整个状态向量,并将其组织成功能组。 当您在更改OpenGL ES状态的框架导航器中选择一个调用时,更改的值将突出显示。 例如,调用glCullFaceglFrontFace函数会更改并突出显示状态列表的“剔除”部分中的值。 使用glEnable(GL_BLEND)调用或使用glBlendFunc函数更改混合参数来启用混合,可以在状态列表的“混合”部分中更改和突出显示值。

The Context Info View - 上下文信息视图

B-14右侧所示的The Context Info View列出了有关正在使用的OpenGL ES渲染器的静态信息:名称,版本,功能,扩展名和类似数据。 您可以查看此数据,而不是编写自己的代码来查询渲染器属性,如GL_MAX_TEXTURE_IMAGE_UNITSGL_EXTENSIONS

Figure B-14 Debug area with Auto and Context Info views

The Auto View - 自动视图

B-14左侧所示的自动视图会自动列出在其他变量视图中通常找到的项目的子集以及适用于框架导航器中所选调用的其他信息。 例如:

  • 如果所选的调用导致OpenGL ES错误,或者Xcode已经确定了所选调用的可能的性能问题,则该视图列出了每个的错误或警告和建议的修复。
  • 如果所选调用更改OpenGL ES上下文状态的一部分,或者其行为取决于上下文状态,则视图会自动从GL Context view中列出相关项。
  • 如果所选择的调用绑定资源或使用诸如顶点数组对象,程序或纹理的绑定资源,则视图会自动列出“绑定GL对象”视图中的相关项目。
  • 如果选择了绘图调用,则视图列出了程序性能信息,包括在绘制调用期间在每个着色器中花费的总时间,如果你自捕获帧以来已更改并重新编译着色器,则在每一个着色器中花费的基线时间都是不同的。 (仅在支持OpenGL ES 3.0的设备上进行调试时,程序性能信息才可用)。

此外,此视图列出了有关帧渲染性能的汇总统计信息,包括绘制数量和帧速率。

后记

有点小困,睡了,未完,待续~~~

推荐阅读更多精彩内容