渲染管线优化:CPU渲染与GPU渲染的区别

做嵌入式GUI优化,绕不开一个核心问题:谁在干活。CPU还是GPU?我见过不少团队,一上来就堆GPU加速,结果功耗爆炸,帧率反而没上去。说白了,你得先搞清楚这两兄弟的分工。

CPU渲染 vs GPU渲染

CPU是"全能工兵",什么都能干,但一次只能干一件事。GPU是"画图流水线",擅长并行处理大量简单计算。在GUI渲染里,CPU负责构建绘制命令,GPU负责执行绘制命令。

对比项CPU渲染GPU渲染
核心优势灵活,适合复杂逻辑并行,适合大量像素填充
瓶颈单线程串行,容易卡顿带宽受限,纹理上传慢
典型场景矢量图形、文字渲染图片缩放、动画过渡
功耗低(但占用高时发热)高(尤其频繁切换状态)

我在一个智能手表项目里遇到过:用CPU渲染圆形表盘指针,每帧要计算几十个三角函数,CPU占用直接飙到80%。后来改成GPU渲染,把指针预渲染成纹理,帧率从25fps跳到60fps。嗯,这里要注意:不是所有场景都适合GPU。如果你的UI大部分是静态文字,CPU反而更省电。

核心原则:CPU做"少而精"的绘制命令组装,GPU做"多而快"的像素填充。两者配合,才能流畅。

减少绘制调用(Draw Call)

Draw Call是什么?说白了,就是CPU告诉GPU"你该画这个了"的一次通信。每次通信都有开销——CPU要打包数据,GPU要解析命令。你想想看,一帧里如果有几百次Draw Call,光通信开销就把帧率吃掉了。

我习惯用合并绘制的思路。举个例子:一个按钮有背景、边框、文字、阴影,如果分开画就是4次Draw Call。合并成一张纹理,一次搞定。

实战技巧:在LVGL或TouchGFX里,开启"脏矩形"(Dirty Rect)机制。只重绘变化区域,而不是全屏刷新。我见过有人把全屏刷新从60fps降到30fps,就是因为没开这个。

我曾经在一个车载仪表盘项目里,把Draw Call从200+降到30以下。怎么做的?

  1. 合并静态元素:背景、刻度、固定图标,预渲染成一张大纹理。
  2. 分层更新:只有指针和数字是动态的,单独一层。
  3. 避免透明叠加:透明混合会打断批处理,能用不透明就用不透明。

批处理(Batching)技术

批处理,就是把多个相似的绘制命令打包,一次发给GPU。就像你去快递站寄包裹,一个一个寄很慢,攒一箱一起寄就快多了。

批处理的关键是状态一致性。GPU切换状态(纹理、着色器、混合模式)很费时。如果你画10个按钮,每个按钮纹理不同,那就没法批处理。反过来,10个按钮用同一张纹理,一次搞定。

注意:批处理不是万能的。如果UI元素层级复杂,强行批处理反而会增加CPU的排序开销。我建议:批处理只用于同一层级的同类元素。

我常用的批处理策略:

  • 纹理图集(Texture Atlas):把所有小图标拼成一张大图。这样切换图标时不用换纹理。
  • 顶点缓冲(Vertex Buffer):把顶点数据一次性上传到GPU,避免每帧重复上传。
  • 实例化绘制(Instancing):适合大量重复元素,比如列表项、网格。

纹理压缩与格式选择

纹理是GUI的"内存大户"。一张1080p的RGBA8888纹理,占8MB。嵌入式设备内存本来就紧,你想想看,放几张图就爆了。

纹理压缩,说白了就是用更少的比特存更多的像素。但压缩有代价:质量下降、解码开销。怎么选?

格式压缩比质量适用场景
RGBA8888无压缩最高照片、渐变背景
RGB5652:1中图标、纯色块
ETC24:1高Android设备通用
PVRTC4:1中PowerVR GPU专用
ASTC可变可调高端嵌入式GPU

我在一个智能家居面板项目里,把所有图标从RGBA8888转成RGB565,内存占用降了一半,肉眼几乎看不出区别。但注意:带透明通道的图标,别用RGB565,否则边缘会有锯齿。用RGBA4444或者ETC2带Alpha。

我的习惯:纹理格式选型三步走——1. 看GPU支持什么(查手册);2. 看UI元素类型(照片/图标/文字);3. 看内存预算。别盲目追求高质量,够用就行。

知识体系总览

下面这张图,把本章的核心逻辑串起来了。你可以把它当作优化时的检查清单。

渲染管线优化知识体系 渲染管线优化核心逻辑 渲染管线优化 CPU vs GPU 分工 减少 Draw Call 批处理 Batching CPU:命令组装 GPU:像素填充 合并绘制命令 脏矩形机制 纹理图集 实例化绘制 纹理压缩与格式选择 RGBA8888 / RGB565 ETC2 / PVRTC ASTC 核心目标:减少CPU-GPU通信开销 + 降低纹理内存占用

这张图把本章的四个知识点串成了一条优化链路。从CPU/GPU分工开始,到减少Draw Call,再到批处理,最后用纹理压缩收尾。每一步都指向同一个目标:让每一帧的渲染开销最小化。

总结一句话:渲染管线优化的本质,就是减少CPU和GPU之间的无效通信,让它们各司其职、高效协作。别让CPU等GPU,也别让GPU等CPU。