Skia深入分析10——Skia库的性能与优化潜力

Skia库性能与优化潜力

图形/渲染

算法/架构

作为图形渲染引擎,性能上是非常重要的,按通常Android手机60帧的刷新率,绘制一帧的总时间只有16ms,可谓是毫厘必争。提升性能到最后,就必然跟不同CPU的特性打交道,毕竟一个SIMD下去,好做的提升5、6倍,不那么好做的也达到2、3倍,收益极其可观。 
SIMD,在intel上是SSE,在arm上是neon,在mips上则是其dsp功能。使用SIMD,需要代码架构是满足内存连续性要求的,否则需要重构,Skia作为正常的图形渲染引擎,采用行渲染方式,易于实现SIMD。在充分优化的场景,其速度与GPU渲染不相上下。 
总体而言,Skia库的渲染架构是遵循连续性,易于优化的。目前Skia中的高频使用函数基本上都进行了优化,并且由于软件渲染使用频率的降低,进一步优化的价值不大。但从代码层面来看覆盖率并不是特别高,遇到特定场景卡顿了,还是可以挖出几个函数优化下的。 
从算法来看,Skia里面的图形绘制算法基本上都达到了最优,没有什么多余的步骤。编解码方面,存在一些多余的内存拷贝、采样缩放等。

行填充

这里面的行填充包括一行像素的透明度混合、颜色格式转换、抖动处理。在SkBlitter构建时,根据源、目标像素格式和paint属性挑选。 
neon优化的相关代码见 src/opts/SkBlitRow_opts_arm_neon.cpp 
主要通过 platformProc的转换而得。 
大部分行填充的类型是做了neon优化的,这些也是用得很频繁的函数。

图像绘制

Sprite流程

在前面有讲述,将用来绘制的图像预先旋转缩放好,使之和目标区域一样大,并且坐标没有小数位,可以走进Sprite流程。但目前有不少限制,这些不支持的情况并不是原理不允许,而是没有做,有需要的话可以补上。 
详细见 
SkSpriteBlitter::ChooseD16 
SkSpriteBlitter::ChooseD32

采样

前面已有说明图像采样的设计。 
对于Matrix proc,在SkBitmapProcState::chooseMatrixProc函数中决定函数分支。 
这些函数也是公共头文件加宏组合出来的。 
neon的详见: 
src/opts/SkBitmapProcState_matrixProcs_neon.cpp 
src/opts/SkBitmapProcState_matrixProcs_neon.h 
主要是一次计算四个坐标

对于采样的 
src/opts/SkBitmapProcState_filter_neon.h 
它与 
src/core/SkBitmapProcState_procs.h 
构成函数。 
这个功能是只是做一个像素的双线性插值计算(计算过程向量化实现)。感觉优化力度并不够。

在仅缩放的插值情况,由于一行的像素是相邻的,插值计算以行为单位处理会比较效率。

高级插值似乎是没有做优化,用得也少,这个还是靠GPU优化好些。

文本绘制

文本绘制中,Skia很关键的优化方法是建立了字形Mask缓存机制,blitMask过程和blitRect的过程相似,也是用的加速过的行渲染函数。这样在绘制文字固定时只是第一次解析字体构建缓存慢。 
不过在生成字体Mask缓存的流程中,generateImage函数并没有充分优化。 
Mask需要占用一定量的内存,Skia中可以设置其上限(默认8M),这个是每个应用都占这么多,整个系统加起来其实就很大了。应用如果经常变字形,改效果,这个内存很快就会到上限,然后就经常找不到cache从而性能下降。 
在一些情况下无法建Mask缓存,只能存路径SkPath,这时的性能也会差一些。

路径绘制

路径绘制里计算边界的过程基本上没有什么好方法优化,填充时也是利用行渲染函数和采样算法。

图像/算法

编解码

解码速度在系统中还是比较重要的,关系到应用开启的速度。 
Google对其优化主要在对应的编解码库中实现,Skia里面只是配置参数。 
而Skia本身的一些处理如颜色转换、下采样等可能被认为相对解码本身而言较短,并没有做优化。但做一下估计还可以提升5%左右。 
制作SOC的厂商可能会修改这一部分代码,使之用特定DSP等硬件实现。不过考虑到硬件编解码的一些限制,还是会有不少场景不得不回归软件编解码。 
区域解码基本上是用硬件优化不了或优化不好的,如果内存足够,使用硬解码后原理上也不需要区域解码这种方式提高速度。

特效

特效主要是SkMask,里面有高斯模糊、光照效果等的实现。 
其优化的代码也在 src/opts/目录下。 
在CPU上做这种代码的优化,需要把浮点转成近似整数,会有一定的精度误差。还是走GPU加速的方案好些。

GPU

Skia-GPU在当前的方式下,需要将绘制结果拷贝出来,因而不好用做渲染。 
但如果修改一下,允许外界输入 EGL-Image来创建SkSurface,映射为输出的纹理和FBO,便可以将这次拷贝避免。不过,不走窗口系统,仅仅只是输出到一个纹理是否会对GPU性能有影响,很难说。 
Skia-GPU流程的缓存的管理感觉不如硬件加速引擎hwui那一套好。

BenchMark

Skia目录下面有个 bench文件夹,里面是测试各项性能的代码。

你可能感兴趣的:(Android图形显示)