减少过度绘制

应用可能会在单个帧内多次绘制同一个像素,这种情况称为“过度绘制”。过度绘制通常是不必要的,最好避免。它会浪费 GPU 时间来渲染与用户在屏幕上所见内容无关的像素,进而导致性能问题。

本文档将向您介绍过度绘制的定义、诊断方式,以及您可以采取哪些措施来消除或减少过度绘制。

关于过度绘制

过度绘制是指系统在渲染单个帧的过程中多次在屏幕上绘制某一个像素。例如,如果我们有若干界面卡片堆叠在一起,每张卡片都会遮盖其下面一张卡片的部分内容。

但是,系统仍然需要绘制堆叠中的卡片被遮盖的部分。这是因为堆叠的卡片是根据 Painter 算法(也就是按从后到前的顺序)来渲染的。按照这种渲染顺序,系统可以将适当的透明度混合应用于阴影之类的半透明对象。

找出过度绘制问题

平台提供了以下工具来帮助您确定过度绘制是否会影响应用的性能。

GPU 过度绘制调试工具

GPU 过度绘制调试工具使用颜色编码来显示应用在屏幕上绘制每个像素的次数。此计数越高,过度绘制影响应用性能的可能性越大。

如需了解详情,请参阅如何直观呈现 GPU 过度绘制

GPU 渲染模式分析工具

GPU 渲染模式分析工具以滚动直方图的形式显示渲染流水线的每个阶段显示一帧所用的时间。每个竖条的“处理”部分都以橙色表示,它显示系统何时交换缓冲区;该指标可提供有关过度绘制的重要线索。

在性能较低的 GPU 上,可达到的填充率(GPU 填充帧缓冲区的速度)可能相当低。随着绘制一帧所需的像素数的增加,GPU 可能需要更长的时间来处理新命令,并要求系统的其余任务等待,直到它跟上进度。“处理”条显示,当 GPU 因尝试尽可能快地绘制像素而超负荷运转时,就会出现这种峰值。除了原始像素数,其他问题也可能导致该指标出现峰值。例如,如果 GPU 过度绘制调试工具显示存在严重的过度绘制和“处理”峰值,则可能存在过度绘制的问题。

如需了解详情,请参阅如何分析 GPU 渲染速度

解决过度绘制问题

您可以采取以下几种策略来减少甚至消除过度绘制:

  • 移除布局中不需要的背景。
  • 使视图层次结构扁平化。
  • 降低透明度。

本节将分别介绍这几种方法。

移除布局中不需要的背景

默认情况下,布局没有背景,这表示布局本身不会直接渲染任何内容。但是,当布局具有背景时,其有可能会导致过度绘制。

移除不必要的背景可以快速提高渲染性能。不必要的背景可能永远不可见,因为它会被应用在该视图上绘制的任何其他内容完全覆盖。例如,当系统在父视图上绘制子视图时,可能会完全覆盖父视图的背景。

如需查找过度绘制的原因,请在布局检查器工具中浏览层次结构。在浏览过程中,请留意您可以移除的背景,因为它们对用户不可见。在许多容器采用同一种背景颜色的情况下,您也有机会移除不需要的背景:您可以将窗口背景设置为应用的主背景颜色,并且不为其上面的任何容器定义背景值。

使视图层次结构扁平化

借助先进的布局设计方法,您可以轻松对视图进行堆叠和分层,从而打造出精美的设计。但是,这样做会导致过度绘制,从而降低性能,特别是在每个堆叠视图对象都是不透明的情况下,这需要将可见和不可见的像素都绘制到屏幕上。

如果遇到这类问题,您可以通过优化视图层次结构来减少重叠界面对象的数量,从而提高性能。如需详细了解如何实现此操作,请参阅优化视图层次结构

降低透明度

在屏幕上渲染透明像素,即所谓的透明度渲染,是导致过度绘制的重要因素。在普通的过度绘制中,系统会在已绘制的现有像素上绘制不透明的像素,从而将其完全遮盖,与此不同的是,透明对象需要先绘制现有的像素,以便达到正确的混合效果。诸如透明动画、淡出和阴影之类的视觉效果都会涉及某种透明度,因此有可能导致严重的过度绘制。您可以通过减少要渲染的透明对象的数量,来改善这些情况下的过度绘制。例如,如需获得灰色文本,您可以在 TextView 中绘制黑色文本,再为其设置半透明的透明度值。但是,您可以简单地通过用灰色绘制文本来获得同样的效果,而且能够大幅提升性能。

如需详细了解透明度在整个绘制流水线中造成的性能成本,请观看视频透明度的隐形成本