研发实战五:如何通过RenderDoc优化Quest VR应用
(映维网 2021年11月29日)RenderDoc是一个支持Android的开源调试器,可帮助你窥视应用渲染机制幕后情况。对于商用游戏引擎,实际的渲染代码要么是隐藏,要么难以通过于各种内置子系统来解密,所以如果能够看到引擎是如何确定场景在单帧中的渲染方式,何乐而不为呢?
当你通过RenderDoc捕获一帧时,它会按照帧的发出顺序记录所有图形API命令和资源,然后再播放它们。RenderDoc同时可以帮助你大致知晓GPU执行绘制需要多少时间和绘制逻辑组。
关于RenderDoc的另一个关键要点是,它完全免费,并且开源。具体请访问官方的RenderDoc下载页面。
延伸阅读:研发实战一:如何通过RenderDoc优化Oculus Quest应用
延伸阅读:研发实战二:如何通过RenderDoc优化Oculus Quest应用
延伸阅读:研发实战三:如何通过RenderDoc优化Oculus Quest应用
延伸阅读:研发实战四:如何通过RenderDoc优化Oculus Quest应用
映维网早前已经分享过一系列通过RenderDoc优化Oculus Quest应用的博文。现在,Meta开发者团队又介绍了与之相关的主题技巧,下面是映维网的具体整理:
RenderDoc for Oculus是热门图形调试器RenderDoc的定制分支。这个特定于Quest的工具提供了对底层GPU剖析数据的访问,特别是来自Tile渲染器的信息。我们正继续改进工具,并增加了一系列德新功能,如Tile Browser和Oculus Performance Counters。深度剖析功能和各种图形调试功能令RenderDoc for Oculus成为了解决性能难题的一个重要工具。在这篇博文中,我们将回顾如何有效地利用RenderDoc for Oculus,以及你应该避免的陷阱。
1. 开始
RenderDoc for Oculus这个图形调试器允许你快速轻松地捕获单帧,并详细检查任何应用。如果是刚刚接触,你可以参阅下面的博文:
延伸阅读:研发实战一:如何通过RenderDoc优化Oculus Quest应用
延伸阅读:研发实战二:如何通过RenderDoc优化Oculus Quest应用
延伸阅读:研发实战三:如何通过RenderDoc优化Oculus Quest应用
延伸阅读:研发实战四:如何通过RenderDoc优化Oculus Quest应用
对于已经十分熟悉RenderDoc For Oculus的用户,我们现在将深入探讨如何充分利用这个工具。
2. 计时器按钮行为
计时器按钮是RenderDoc最热门的功能之一,因为它简单易用。从v23.2开始,我们改动计时器按钮行为以进行渲染通道测量,而不是绘制调用测量。这一变化的原因是性能查询:因为基于Tile的GPU架构,RenderDoc用于测量每次绘制调用持续时间的机制不适合移动平台。但如果你喜欢旧的行为,你可以将Settings > Profiling > Timer query type改回绘制调用。
3. 优化级别
当你通过RenderDoc启动应用时,它会用自己的API调用替换应用的API调用,以记录为生成帧而发出的所有命令。为了提取要在UI中显示的资源和状态,RenderDoc有时需要插入或更改命令。所以,RenderDoc的播放有时会包含phantom操作。为了在分析过程中最小化这个问题,当你选择profiling mode replay context时,我们强制将优化级别设置为最快。作为副作用,部分资源在剖析模式下会显示为黑色。如果需要同时检查所述资源和概要文件,可以使用主线RenderDoc打开capture,同时使用profiling mode replay context打开相同的capture文件。如果你的capture足够小,可以同时在内存中容纳两个副本,你将能能够同时分析和检查资源。
由于我们在使用profiling mode replay context时强制设置为Fastest,所以建议你将设置保持为Balanced,以便在使用非profiling mode replay context时方便地检查资源。
4. GLES/Vulkan API错误
在开始任何性能调查之前,你应该检查应用的API错误,因为我们所有的性能工具都需要有效的命令stream。无效的命令stream或错误的命令将导致API错误,并产生未定义的行为,如崩溃或性能差。自v29以来,我们的操作系统版本中包含了Vulkan验证层支持;你可以通过命令行或RenderDoc使用它们。
5. RenderDoc API验证
若要检查应用是否存在API错误,请在打开capture播放时启用API验证。请注意,我们已经禁用了在profiling mode replay context中启用API验证的功能。这是因为我们希望在使用RenderDoc for Oculus进行评测时尽可能减少开销。
在启用API验证打开capture后,RenderDoc检测的所有API错误将显示在错误和警告面板之下。
6. Tile Timeline和Tile Browser
若应用没有API错误,我们就可以依靠RenderDoc for Oculus的Tile Timeline功能在渲染过程中检查不必要的存储或加载。
Quest和Quest 2的Tile架构GPU通过Tile渲染优化内存带宽使用。每个Tile都可以通过GPU的快速内存临时存储和访问多次,并且只需向较慢的内存写入一次。所以,移动VR应用利用这种优化非常重要。
RenderDoc for Oculus的Tile Timeline功能显示了高通GPU在渲染场景时所经历的不同阶段。
你可能会注意到,一些bin比其他大,这是由于Tile打包,其中与周边视觉对应的Tile被合并,并以较低的分辨率渲染。另外,热图覆盖可能会过度扩展帧缓冲区的尺寸。这是由于帧缓冲区尺寸未与bin尺寸对齐。这种部分占用的边缘bin使用自定义scissor test来消除超出边界像素的工作负载。
你另外可能会注意到,从Tile Timeline报告的帧时间可能比持续时间计时器或其他帧时间测量方法报告的帧时间有着更高的成本。这是因为收集定时信息和属性的行为会带来开销,并且由于渲染阶段数量很大,开销会显著增加。然后,Quest 2的解析阶段(例如颜色写入或深度写入)可以与渲染操作重叠。这种同时执行渲染的能力会产生相当大的开销,并且会影响性能度量。
7. phantom属性
如前所述,RenderDoc有时会根据需要在播放过程中更改操作。这有时会影响计时测量,所以仔细检查播放命令并确保它们与应用正在执行的操作相匹配非常重要。
上面是来自同一UE4 Vulkan应用的两组曲面属性。左侧是Perfetto捕获的曲面属性,右侧是 RenderDoc for Oculus捕获的RenderDoc的曲面属性。左侧的颜色attachment属性显示“Tiled | UBWC”,右侧显示0。UBWC是指高通的Universal Bandwidth Compression。它不是可以为帧缓冲区设置的Vulkan/GL属性,而是在帧缓冲区配置满足UBWC的要求时的选择。UBWC帧缓冲区attachment的要求之一是,不使用VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT flag创建图像,但RenderDoc会插入它以提取MSAA内容。这是一个可以解决的问题,但需要一定的时间进行解决。
需要强调的是,你从RenderDoc for Oculus获得的测量值可能不是应用的精确重播,你应该从多个来源获取测量值。
8. Oculus Performance Counters
在确保应用充分利用Tile架构后,我们可以查看单个绘制调用性能。由于绘制调用在Tile GPU中执行的方式,我们不能依赖性能查询来比较绘制调用。相反,我们可以在Performance Counters Viewer下使用特定于Oculus的硬件计数器。
Renderdoc中目前有49个指标可用于Oculus Performance Counters。最重要的指标之一是GPU时钟指标。当 RenderDoc for Oculus为Oculus Performance Counters查询时,绘制调用将逐个执行,没有并行性。对于GPU执行操作的每个周期,GPU时钟计数器将递增一。占用更多存储bin的绘制调用自然具有更大的GPU时钟度量,因为存储bin一次处理一个。GPU时钟度量是对绘制调用延迟而不是吞吐量的度量。在正常执行环境中,设备将采用各种延迟隐藏技术,这可能导致许多操作的重叠。所以,重要的是不要过度索引GPU时钟指标,因为延迟隐藏技术对于实现应用的高性能同样至关重要。
百分比时间度量可以帮助你了解绘制调用在vertex阶段和fragment阶段之间的成本分布。对于计算shader dispatc, %Time Compute 度量应接近100%。这三个指标的总和应达到100%,表示绘制调用花费的总时间。
在知道会知道是vertex bound还是fragment bound后,我们可以检查着色器调用度量,看看是否需要优化着色器本身。vertex着色器成本高可能是由于vertex计数高或vertex着色器本身的复杂性。类似地,对于frament着色器,成本可能是由于fragment的数量或着色器本身的复杂性。
除了指令计数外,memory locality差会降低缓存的有效性并降低性能。诸如% Vertex Fetch Stall,% Texture Fetch Stall,L1 Texture Cache Miss Per Pixel,% Texture L1 Miss,% Texture L2 Miss,% Stalled on System Memory等的内存指标衡量内存操作造成的负面影响。所述指标衡量内存操作对调用的影响。要查明绘制调用中的问题,你需要下一组指标。
Per-Shader Metrics可以告诉你着色器使用了多少纹理提取、算术运算和基本函数操作。“Textures / Vertex”或“Textures / Fragment”度量值较高,加上“Vertices Shaded”或“Fragments Shaded”度量值较高,这可能会导致较高的“% Vertex Fetch Stall”或“% Texture Fetch Stall”。请注意,SSBO或R/W缓冲区操作视为纹理操作,可以增加“Textures / Vertex”或“Textures / Fragment”。“ALU/Vertex”和“ALU/Fragment”度量衡量着色器使用的算术运算量。最后,“EFU/Vertex”和“EFU/Fragment”衡量基本函数操作的数量,例如正弦/余弦。
9. 着色器编辑
标准RenderDoc包含着色器编辑功能,我们可以利用它来进行快速着色器实验,而无需重建应用。若要使用所述功能,请确保着色器处理工具路径指向有效路径。在Settings>Shader Viewer下面,选择你的路径并单击Edit:
正确设置着色器处理工具路径后,你可以导航到着色器以更改着色器,单击编辑打开编辑着色器模块面板。
完成更改后,单击“刷新”按钮编译着色器以使更改生效。在关闭“编辑着色器模块”面板之前,后续剖析测量将反映所做的更改。
10. 演示
下面这个视频演练利用了Renderdoc for Oculus中的所有剖析功能。
0:00-启动剖析模式并加载capture
0:30-Tile Timeline和Tile Browser
3:10-Oculus Performance Counters
7:10-着色器编辑和分析
11. 结语
创造引人入胜的沉浸式虚拟现实体验需要对平台有深刻的理解。我们将继续对工具集进行升级和改进,以反映平台的性能特征。