带你读《2022技术人的百宝黑皮书》——Flutter 新一代图形渲染器 Impeller(5)https://developer.aliyun.com/article/1340787?groupCode=taobaotech
接下来进入impeller的渲染流程,使用DisplayListDispatcher执行DisplayList中所有Ops,在Op的dispatch()函数中调用DisplayListDispatcher的相应函数,把绘图信息转换为EntityPass结构。如果有saveLayer操作,则创建子EntityPass,形成EntityPass树形结构。同时把多个相关联的Ops转换为Entity存储到EntityPass中。每个Entity会对应一种Contents,表示一种绘图操作(如drawRect/clipPath等),共有11种Contents(参见第五小节附录impeller类图)。可见,DisplayList记录了细粒度的Op信息,结构扁平,无层次关系;转换为EntityPass后,对Ops进行了组装,根据savaLayer操作生成了有层次结构EntityPass tree,更便于后续的渲染。
随后,使用RenderPass从Root EntityPass开始遍历,把EntityPass中每个Entity转换为Command结构,即从Shader Bindings生成GPU Pipeline,把Polygon转换为顶点数据,设置片段着色器的颜色或纹理数据,再把顶点数据和颜色或纹理数据转换为GPU buffer设置到GPU Pipeline中。遍历完成所有的Entity Passes后,所有Com- mand都存储到了RenderPass中。
然后,开始渲染指令编码阶段,根据MTLCommandBuffer生成MTLRenderCommandEncoder,遍历所有的Commands,把每个Command中的PipelineState,Vertext Buffer,Fragment Buffer设置MTLRenderCom- mandEncoder中,最后。结束编码并提交command buffer。
如下为Entity Passes的结构图:
- Canvas#saveLayer()操作会创建子EntityPass,用于离屏渲染;常见的需要离屏渲染的操作有:alpha blending,gradient,gaussian blur和expensive clips
- EntityPass包含一系列Entity,每个Entity是一个绘图操作,对应于Canvas#drawXXX()
- 每个Entity对应一个Contents,表示一种绘图类型,共11种Contents
- 每种Contents在渲染时生成对应的Command,包含了顶点数据、片段着色器数据和GPU rendering pipeline 信息
GPU绘图过程顶点数据至关重要,需要根据绘制的形状生成顶点数据,再生成vertext buffer object(VBO)关联到渲染管线上,如下为impeller中对顶点的处理过程:
以Rect类型为例,在生成EntityPass阶段会把Rect转换为Path结构,然后在创建Command阶段利用Tessellator
(曲面细分器)根据Path生成顶点数据,存储到主存HostBuffer上,并把offset和length保存为BufferView关联到顶点或片段着色器的PSO上。在Encode Commands阶段把整个HostBuffer上传到GPU buffer,把该次绘制的Vertext/Fragment Buffer、offset和length信息设置到对应的GPU pipeline上。
Impeller渲染流程
带你读《2022技术人的百宝黑皮书》——Flutter 新一代图形渲染器 Impeller(7)https://developer.aliyun.com/article/1340784?groupCode=taobaotech