当前位置: 首页 > news >正文

Chromium Graphics: GPUclient的原理和实现分析之间的同步机制-Part I

摘要:Chromium于GPU多个流程架构的同意GPUclient这将是这次访问的同时GPU维修,和GPUclient这之间可能存在数据依赖性。因此必须提供一个同步机制,以确保GPU订购业务。本文讨论了下一个多进程架构GPUclient之间的同步,而同步点(SyncPoint)。

GPU进程架构等基本概念

我们知道,Chromium是一个多进程架构的软件系统。出于安全和稳定性方面的考虑,Chromium有个专门的进程(或者线程)和GPU设备进行交互,运行GL操作,也就是说,不论什么一条GL命令都必须经由这个进程处理后才提交给GPU驱动,这个进程就是GPU进程。Renderer进程或者Browser进程必须通过IPC才干与GPU进程交互,告诉GPU进程须要运行哪些GL命令。在这个过程中,Renderer进程或Browser进程是GPUclient,而GPU进程本身就是GPU服务端

GPUclient和服务端之间GL命令传输是通过命令缓冲区(CommandBuffer)完毕的。

CommandBuffer是Chromium为解决多进程架构下高效在client和服务端传输GL命令而设计的,缓冲区使用共享内存存储GL命令,每条GL命令的命令名和參数都会被序列化为字符串存储在命令行缓冲区中。当client须要将命令缓冲区中的全部GL命令提交给GPU服务端时。client会向服务端发送一条GpuCommandBufferMsg_AsyncFlush消息。服务端收到这条消息后会依据指定的偏移从CommandBuffer中读取GL命令并将其反序列化后再提交给GPU驱动。

Chromium中。页面的渲染和合成过程都启用了GPU硬件加速,不论什么一个要求GPU硬件加速的进程都是GPU进程的client,比如Renderer进程是GPUclient,由于它须要请求GPU进程绘制和合成页面的内容,Browser进程也是GPUclient,由于它须要将页面的内容与地址栏等元素进行终于的合成,并显示在屏幕上。

下图给出了GPUclient、GPU服务端以及命令缓冲区的基本关系。


GPUclient之间能够通过mailbox机制进行texture共享的,简单的说。mailbox机制就是给每一个texture生成唯一标识。并由GPU进程统一管理名标识和texture之间的映射关系。同一时候这些GPUclient属于同一上下文共享组。因此全部texture资源也是能够共享的。

GPUclient之间的同步问题

从上述描写叙述不难看出,GPU进程须要处理来自多个GPUclient的请求,而且这些GPUclient可能存在纹理(Texture)数据依赖关系。

以下以Android平台上渲染WebGL页面http://get.webgl.org 为例,说明为什么不同GPUclient会存在数据依赖关系。

首先,Browser进程是一个GPUclient,它创建了一个Browser端的合成器(Compositor)请求GPU进程将页面的内容和地址栏等UI元素(假设有)进行终于的合成。并将其渲染到SurfaceView上。Renderer进程也是GPUclient,它也会创建一个Renderer端的合成器用于页面内容的合成。并且这个client中还包括了两个独立的3D上下文,一个用于页面中渲染层的合成,还有一个作为WebGL的渲染上下文。

其次,在Android平台上,默认启用了托付模式(DelegatedRenderer)的渲染器,因此,Renderer端合成器管理的全部GPU资源(包含WebGL)都会通过IPC转交给Browser端的合成器,再由Browser端合成器对全部的texture进行统一的合成,当终于的合成操作完毕之后。Browser端合成器则会通知Renderer端,此时Renderer端的合成器能够安全删除不再使用的GPU资源。

最后,再来看看WebGL的渲染过程。在硬件加速的页面渲染机制中,页面的内容是由多个渲染层(RenderLayer)叠加构成的。普通情况下,渲染层都会使用Texture作为存储后端,Chromium中WebGL是一个独立的渲染层,在渲染每一帧内容时。Renderer进程会请求GPU进程创建一个新的Texture来存放WebGL的渲染结果。并通过Framebuffer对象将WebGL渲染到这个Texture中。

待 WebGL命令完毕后,Renderer端的合成器会将这个Texture以资源形式发送给Browser端的合成器。当Browser端合成器完毕WebGL内容的合成之后。会通知Renderer端将这个Texture删除。

从上面的描写叙述中能够判断出整个过程存在哪些问题呢?

第一。Renderer端的合成器和Browser端合成器存在数据依赖关系,是生产者-消费者的关系,即Renderer端的WebGL上下文生成Texture内容,Browser端合成器使用该内容;

第二,WebGL上下文和Browser端合成器存在同步问题。因为全部的GL命令都是在同一线程中执行。包含Browser端合成器和WebGL,而3D上下文是GPU线程的调度基本单位,也就是仅仅有同一个3D上下文中GL命令才干依照顺序逐条执行的。

一方面,不同GPUclient可能执行在不同的进程或者线程中,还有一方面。同一GPUclient的不同3D上下文可能执行在不同的线程中,比如Renderer进程的合成器执行在一个单独的线程中,而WebGL执行在Renderer进程的主线程中。显然。不同3D上下文中GL命令执行次序是不分先后的,这里就引申出一个问题,对于WebGL页面渲染而言,必须保证下面这两个要求:

  • 当WebGL上下文的GL命令运行完成后,Browser端合成器才干使用。
  • 当Browser端合成器使用完WebGL的Texture后,WebGL上下文才干安全删除;

否则Browser合成器使用的texture将会是不完整的。这就是GPUclient之间的同步问题。接下来将重点讨论Chromium是怎样解决问题的。

同步点机制的基本原理

Chromium通过GL扩展接口设计了一套同步机制解决不同GPUclient之间的同步问题,它必须满足两个条件:

第一,上下文A能够等待上下文B运行完一组GL命令后再运行上下文A中兴许的GL命令。

第二,上下文A中的这样的等待必须是非堵塞的,也就是说GPUclient代码的运行不能被堵塞。

依据gpu/gles2/extensions/GL_CHROMIUM_sync_point.txt文件所述,同步点机制定义了两个特定于Chromium的GL扩展接口:

        uint InsertSyncPointCHROMIUM()
        void WaitSyncPointCHROMIUM(uint sync_point)

InsertSyncPointCHROMIUM在当前上下文中创建一个同步点并将其插入到命令流中,这个同步点起到一个防护墙的作用,当这个同步点之前的命令都已经提交到server。或者上下文被销毁时。会向该同步点发个信号。返回同步点的标识符。收到信号后。这个同步点会被删除点。在同一个server上同步点标识符在全部上下文中是唯一的,包含同一共享组的上下文。

WaitSyncPointCHROMIUM导致当前上下文暂停提交GL命令,直到指定同步点收到信号,被实现为服务端的等待。參数sync_point为InsertSyncPointCHROMIUM返回的同步点标识符。

假设sync_point參数无效。这个命令相当于no-op操作而且不会报错。

以上文档化的描写叙述读起来有些晦涩难懂。以下通过一个简化的样例更直观地说明SyncPoint在Chromium中的执行原理:

 

如果有两个上下文A和B。它们可能在不同的GPUclient中,但属于同一个共享组(ShareGroup),GPUclient代码中通过调用InsertSyncPointCHROMIUM在上下文A的命令流中插入一个同步点sp。而在上下文B中,调用WaitSyncPointCHROMIUM等待同步点sp,终于在GPU服务端运行GL命令的顺序为,仅仅有当上下文A中同步点sp之前的GL命令A1,A2和A3运行完成后,才会运行上下文B中的GL命令B3。

更进一步地说,上下文B中调用WaitSyncPointCHROMIUM(sp),实际上是指示GPU服务端停止向GPU设备提交上下文B兴许的GL命令,取而代之的是:

  • 假设此时上下文A的同步点sp之前的GL命令都已经运行完成,即同步点sp收到信号,已经从被删除了,那么能够忽略WaitSyncPointCHROMIUM了,继续运行上下文B中兴许的GL命令。
  • 假设此时上下文A的同步点sp之前的GL命令尚未运行,那么取而代之的是将等待上下文A中sp点之前的GL命令运行完成。这个等待发生在GPU服务端的,不会堵塞GPUclient兴许代码的运行(如Renderer进行的运行)。

综上所述,同步点机制同意client设定不同上下文之间GL命令运行的次序。上下文B等待上下文A的同步点实际上是保证A中同步点之前的命令在B中兴许命令之前运行。



未完待续...下节将从Chromium阅读源代码同步点是如何实现的机制


版权声明:本文博主原创文章,博客,未经同意不得转载。

相关文章:

  • 关联引用
  • 数据库的四种隔离级别
  • 跟马哥学linux (lesson 6)linux包管理程序rpm yum
  • 第八章:java常用类(一)
  • GCD介绍
  • Python 脚本学习(三),日志分析脚本,文件差异对比,HTTP状态检测
  • 几种.NET平台数据持久化框架介绍
  • php中Maximum execution time of 120 seconds exceeded时间超时错误解决方案
  • 矩阵键盘 数码管
  • 使用U盘代替光盘来刻录ISO镜像文件的方法
  • linux 函数
  • MyBatis笔记——Mapper动态代理
  • python教程
  • C语言 实现 给定两个整形变量的值,将两个值的内容进行交换
  • 更为适合并发的极简易队列
  • [译] React v16.8: 含有Hooks的版本
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • canvas 绘制双线技巧
  • Django 博客开发教程 16 - 统计文章阅读量
  • Javascript Math对象和Date对象常用方法详解
  • Netty源码解析1-Buffer
  • Sass 快速入门教程
  • ViewService——一种保证客户端与服务端同步的方法
  • Vim 折腾记
  • Vue2.x学习三:事件处理生命周期钩子
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 后端_MYSQL
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 前嗅ForeSpider中数据浏览界面介绍
  • 前言-如何学习区块链
  • 线性表及其算法(java实现)
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • # include “ “ 和 # include < >两者的区别
  • #AngularJS#$sce.trustAsResourceUrl
  • #etcd#安装时出错
  • #单片机(TB6600驱动42步进电机)
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (13):Silverlight 2 数据与通信之WebRequest
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (function(){})()的分步解析
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (三)终结任务
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (转)Scala的“=”符号简介
  • (转)大型网站架构演变和知识体系
  • .net 设置默认首页
  • .NET 中 GetProcess 相关方法的性能
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .NET的数据绑定
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .Net中的设计模式——Factory Method模式
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [2019/05/17]解决springboot测试List接口时JSON传参异常