一文读懂高通GPU驱动渲染流程

news2024/11/14 14:53:33

1. gpu command分析

1.1 gpu command概述

SM8650平台上,GLES发送给KMD(GPU驱动)的GPU命令有两种类型:同步命令和绘制命令。

绘制命令,一般都是一个个的drawcall组成的,是真正GPU程序指令,KMD会给GPU硬件进行处理。

同步命令,在KMD就能处理,无需GPU硬件参与。该指令主要是往KMD的任务队列塞同步点,用来阻塞绘制指令的处理。比如dequeueBuffer带的release fence,会被打包成一个同步命令,发送到KMD,KMD将其放到任务队列,UMD后续提给KMD的命令,就会排在该同步命令后面,就会被阻塞无法被处理,直到该同步命令的同步点被signal,同步命令从任务队列清除,排在该同步命令后面的命令才能继续被处理。

GLES给KMD发送命令时,会创建一个struct kgsl_gpu_command实例,然后把命令打包好,保存到该实例里,然后通过IOCTL_KGSL_GPU_COMMAND发送给KMD处理。

KMD把GPU命令抽象成struct kgsl_drawobj数据结构的子类。比如绘制命令抽象成struct kgsl_drawobj_cmd,同步命令抽象成struct kgsl_drawobj_sync,它们都继承于struct kgsl_drawobj。

故IOCTL_KGSL_GPU_COMMAND的实现函数kgsl_ioctl_gpu_command函数接收GLES发送的消息后,会把struct kgsl_gpu_command实例内保存的GPU命令转成struct kgsl_drawobj实例(这里的转成是指创建struct kgsl_drawobj实例,解析把struct kgsl_gpu_command内容并填充到struct kgsl_drawobj实例,而不是简单的类型强转)。绘制命令转成struct kgsl_drawobj_cmd实例, 同步命令转成struct kgsl_drawobj_sync类型的实例,然后再把这些drawobj实例,保存到context的drawqueue里面。如图:    

c202cf0b94860d2358e59e5c47cc844c.jpeg

KMD初始化时,会为每个GPU设备创建一个struct adreno_device实例,每个struct adreno_device实例会有一个struct adreno_hwsched实例,每个struct adreno_hwsched实例会有16条struct adreno_dispatch_job类型的链表,每个struct adreno_dispatch_job会关联一个context,如图:

8a3156e9f175dd0797d87fe9234e14f2.jpeg

kgsl_ioctl_gpu_command函数将struct kgsl_gpu_command实例保存的GPU命令转成struct kgsl_drawobj实例,并保存到context的drawqueue里面;同时还会创建一个struct adreno_dispatch_job实例,然后根据context的priority,将创建的struct adreno_dispatch_job实例加入到struct adreno_hwsched实例对应链表的尾部(如priority为0,则加入第0条链表尾部)。

KMD初始化时,会创建一个名为kgsl_hwsched内核线程。该线程专门负责处理struct adreno_dispatch_job实例关联的context的drawqueue里面的drawobj。

kgsl_ioctl_gpu_command函数末尾,或者GPU HW处理完任务后,或者同步命令的同步点signal后,都会唤醒kgsl_hwsched线程,kgsl_hwsched线程依次遍历struct adreno_hwsched实例的16条链接,取出struct adreno_dispatch_job实例关联的context的drawqueue里面的drawobj进行处理。如果是同步命令drawobj,就直接从drawqueue里面移除。如果是绘制命令drawobj就发送GPU HW处理。

KMD初始化时,还会创建一个名为kgsl-events的内核线程。该线程专门负责GPU同步点signal,如acquire fence signal,EGLSync/GLSync的signal。

每个context都间接拥有一个struct kgsl_event类型的链表。该链表是用来保存GPU同步点的,如acquire fence,EGLSync/GLSync等。struct kgsl_event实例有两个很关键成员变量:timestamp和func。timestamp用来判断一个该event是否signal,func是事件处理函数。

08f6896bd9abbd341767651a53ea58fd.jpeg

GPU HW硬件有个retire timestamp寄存器,专门用来记录GPU HW完成任务时的时间,GPU HW每完成一次计算任务就会更新这个retire timestamp寄存器。

每次GPU HW处理完任务后,KMD就会遍历比较context的events链表的event的timestamp和retire timestamp寄存器的时间戳,如果timestamp小于hw的retire timestamp时,KMD就会在kgsl_events线程执行event的func函数,func函数就会signal同步点。    

1.2 同步命令处理分析

1.2.1 同步命令类型

KMD根据同步点的实现差异,将同步命令分为三种类型:

(1)fence syncpoint command:主要是fence类型的同步点,如release fence。对应的数据结构struct kgsl_cmd_syncpoint_fence

(2)timestamp syncpoint command:未知(没能通过gles api分析出什么情况下会下发该种同步点命令,应该是在不支持android fence机制的系统使用的)。对应的数据结构struct kgsl_cmd_syncpoint_timestamp

(3)timeline syncpoint command:未知(没能通过gles api分析出什么情况下会下发该种同步点命令)。对应的数据结构struct kgsl_cmd_syncpoint_timeline

但是这三种同步点最终都会换转成struct kgls_drawobj_sync_event实例,然后保存到struc kgsl_drawobj_sync实例的synclist变量内。看下图:    

877f5d592433055633d17b2f323ece1c.jpeg

1.2.2 fence syncpoint command处理分析

根据第一章节的概述,我们可以把GPU命令处理一般分为二个步骤:

(1)预处理,该步骤主要解析用户空间传进来的GPU命令,然后转化成对应的drawobj实例并保存到context的drawqueque里面,同时创建一个struct adreno_dispatch_job实例加入到struct adreno_hwsched实例的链表内。

(2)ready后,kgsl_hwsched内核线程取出drawobj处理。

故对于fence syncpoint command处理分析。我们也分成这两个步骤:

(1)首先分析同步命令如何转成struc kgsl_drawobj_sync实例。上面小节的UML图已经很直观的展示这一个转化过程。这里我们再补一张这一流程的时序图:    

cdd86bb5c30b723a4a2fc48f6e3de372.png

(2)当fence signal后,触发drawobj_sync_expire执行,drawobj_sync_expire函数会再次创建一个struct adreno_dispatch_job实例,并根据context的priority,将创建的struct adreno_dispatch_job实例加入到struct adreno_hwsched实例对应链表的尾部(个人认为这个步骤是多余的,因为上面已经做了这个动作),然后唤醒kgsl_hwsched线程进行处理。时序如下:

e5b1a96ca09fc45aa069b0b3237f3215.png

kgsl_hwsched线程取出drawobj处理,对于fence sync drawobj而言,kgsl_hwsched线程不做任何特殊处理,仅仅移出drawqueue,避免阻塞后面的drawobj:    

f1dfa7d9a89cbbc83d5490d43b12b53a.png    

下图是一次处理过程中的ftrace打印:

bcf56684d247c8e1ed5be73b861fd82e.png

1.2.3 timestamp syncpoint command处理分析

timestamp syncpoint的处理流程和fence syncpoint处理流程类似,同样分为两个步骤。区别一个使用的是kgsl events框架,一个使用的dma fence框架。

(1)首先解析用户空间传进来的同步命令,转成struct kgsl_drawobj_sync实例,然后把实例保存到context的drawqueque里面,同时也会创建一个struc kgsl_event实例,并保存到context的events链表里。时序图如下:

29ce43cb362f1f5ca39a4aa75e7e75ee.png

(2)当event的timestamp小于hw的retire timestamp时,唤醒ksgl_events线程执行event的事件处理函数

_kgsl_event_worker。_kgsl_event_worker执行drawobj_sync_func,drawobj_sync_func执行drawobj_sync_expire:

ce2bba9612ff93055ecdaf21a2cffa35.png

drawobj_sync_expire函数唤醒kgsl_hwsched线程进行处理。流程和fence syncpoint command处理流程一样,这里就不赘述了。

1.3 绘制命令处理分析

和上面一样,绘制命令处理,我们同样分为两个步骤进行分析。

(1)解析用户空间传进来的绘制命令,然后转化成struct kgsl_drawobj_cmd实例并保存到context的drawqueque里面,同时创建一个struct adreno_dispatch_job实例加入到struct adreno_hwsched实例的链表内。

同样,在讲解struct kgsl_drawobj_cmd生成过程前,先梳理出其相关的数据结构关系:

e9380cfd65518566bd71a80d4cd178ca.jpeg

struct kgsl_drawobj_cmd里面保存了两种类型的数据:    

(i)一个是指令数据,保存在cmlist变量里。由struct kgsl_gpu_command的cmdlist解析获得。

(ii)一个是对象数据,是输入给指令处理的,保存在memlist变量里和profiling_buf_entry变量里。由struct kgsl_gpu_command的objlist解析获得。SM8650基本上都是profiling_buf_entry。

生成struct kgsl_drawobj_cmd实例的时序图如下:

5eddf3f4e3a8b312cc3d0979f67acefc.png

(2)struct kgsl_drawobj_cmd实例处理的关键从gen7_hwsched_submit_drawobj函数开始。gen7_hwsched_submit_drawobj函数先把struct kgsl_drawobj_cmd转成struct hfi_submit_cmd实例和struct hfi_submit_cmd实例,struct hfi_submit_cmd实例和struct hfi_submit_cmd实例都是在一块内存里面。然后在调用gen7_gmu_context_queue_write函数将该内存的数据写到显存里面,GPU FW就会取出送给GPU HW处理。    

60a7a3139f6524372427207ede9a5422.jpeg

代码时序和详细如下图:    

9b01441e9189b70381f72b8a636e2d55.png    

0f39957a84632eef6cfb8025a836cabf.png

3fbd0c50c3ab62b174806ab6a382d23a.png    

89abd924cb242881c9f5e524c853a11f.png

2. gpu fence分析

gpu fence,即gpu创建的fence,由gpu进行signal。queuebuffer代入的fence就是gpu fence,EGLSync/GLsync等也是一个gpu fence。

gpu fence在KMD的数据结构为struct kgsl_sync_fence,每个struct kgsl_sync_fence实例会间接关联一个struct kgsl_event实例。

每个context都有个struct kgsl_sync_timeline实例,struct kgsl_sync_timeline实例有一个struct kgsl_sync_fence链表。context创建的gpu fence都保存在这个链表内。

gpu fence都是通过IOCTL_KGSL_TIMESTAMP_EVENT命令通知KMD创建的,该命令的实现函数为kgsl_ioctl_timestamp_event。kgsl_ioctl_timestamp_event创建gpu fence时,会生成一个fence fd,然后把这个fd保存到参数priv变量里带到用户空间。如图:    

4b2c075a1eb946978af713d9b6f53c47.jpeg

创建gpu fence的时序图:

36e506b552aad4a8fd4210dde15de0f7.png

gpu fence借助kgsl events模块signal的,根据上面的分析,我们知道每个gpu fence会关联一个struct kgsl_event实例,该实例timestamp和gpu fence是同一个。该实例signal就是gpu fence signal。struct kgsl_event实例signal流程就不分析了,上面分析过。

struct kgsl_event实例signal,kgsl-events线程被唤醒,执行_kgsl_event_worker函数

执行kgsl_sync_fence_event_cb函数,kgsl_sync_fence_event_cb执行kgsl_sync_timeline_signal函数,kgsl_sync_timeline_signal函数在执行dma fence的回调函数,完成signal操作。时序图如下:    

7238aa324f43fe556fd69175fa32e7d9.png

我们可以通过ftrace的kgsl_fire_event进行判断:

d6f521649863cc034df9537a67e78b07.png    

3. 一次完整渲染流程分析

在kgsl_ioctl函数加trace,一次eglSwapBuffers,会发起三次ioctl:

c98937ed5443a8b777aee63233c547b3.png

59bf2a3c6adaaeb5fbbfa1d854cdc8d0.png

第一次ioctl,fence syncpoint command

第二次ioctl,绘制命令

第三次ioctl,创建gpu fence

我们可以通过ftrace进行分析整个渲染流程:    

e89505db8b99de0a308443127ce73f4e.png

syncpoint_fence:表示解析fence syncpoint command完成

第一个adreno_cmdbatch_queued:表示fence syncpoint command进入待处理队列

第二个adreno_cmdbatch_queued:表示绘制命令进入待处理队列

kgsl_register_event: 表示在创建gpu fence

syncpoint_fence_expire:表示release fence signal

adreno_cmdbatch_submitted:表示指令提交到了GPU HW

kgsl_fire_event:表示gpu fence signal

4. 总结

本文是基于SM8650, Android系统,GLES API进行分析的,并不能适用所有高通平台,系统,图形接口,有一定的局限性。如有疏漏,在所难免,还请读者朋友海涵。         

以上所有的代码,都来自开源网站:

https://git.codelinaro.org/clo/la/platform/vendor/qcom/opensource/graphics-kernel/-/tree/gfx-kernel.lnx.14.0.r6-rel?ref_type=heads

df7ceb876a1d0ee061666309492b4102.jpeg

Linux内存管理中锁使用分析及典型优化案例总结

Binder驱动中的流程详解

2024年Arm最新处理器架构分析——X925和A725

cd3907258efc384917e0348e990563e2.gif

长按关注内核工匠微信

Linux内核黑科技| 技术文章| 精选教程  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动分班实用工具

开学前夕,老师们的日程表上又添上了一笔笔的工作任务。分班,作为开学前的一项重要工作,不仅关系到学生的学习环境,也是家长们关注的焦点。 易查分,让分班变得简单 易查分小程序的出现,为老师们提供了一种全…

Vercel 的 AI 工具 V0.dev:如何使用它?

几个月前,Vercel 宣布推出了 V0.dev,这是一款专为开发人员和设计师设计的工具,能够使用 AI 生成 React 代码。最初,V0.dev 对外开放时采用了邀请制,但如今拥有 Vercel 帐户的任何人都可以访问并使用它。 这些工具填补…

计算机专业的 “铁饭碗” 终于被发现啦

计算机专业毕业后只能当码农吗?大错特错❌!其实计算机专业考公真的非常有优势呢!张雪峰就曾说过:“计算机在考公的时候,有那种 yyds 的感觉,是所有单位都要。”😃 🌻计算机类专业包…

音频播放+音频采样(绘制音波)

引言 在 iOS 平台中,实现音频播放有多种方式。AVAudioPlayer 是一个专门用于播放音频数据的类,易于使用,适合处理简单的音频播放需求。而 AVPlayer 则是一种更通用的播放器,既能播放视频资源,也能处理音频内容&#x…

Linux:Linux线程池

目录 线程池的概念 线程池的优点 线程池的应用场景 线程池的实现 线程池演示 线程池的概念 线程池是一种线程使用模式。 线程过多会带来调度开销,进而影响缓存局部和整体性能,而线程池维护着多个线程,等待着监督管理者分配可并发执行的…

长视频生成研究的挑战、方法与前景

人工智能咨询培训老师叶梓 转载标明出处 长视频生成面临的主要挑战包括如何在有限的计算资源下生成长时间、高一致性、内容丰富且多样化的视频序列。另外现有研究中对于“长视频”的定义并不统一,这给研究的标准化和比较带来了困难。来自西安电子科技大学、上海交通…

Window 安装Gogs教程

1、下载 下载地址:https://gogs.io/docs/installation/install_from_binary.html(请自行科学上网 选择Windows amd64(64位)或者386(32位) 2、安装 2.1 将压缩文件放到目标文件夹 2.2 创建数据库 在本地数据库或者其他目标数据库新建查询执行下列SQL语句 找到go…

taskBus的设计局限和吞吐能力测试

在前文中,我们介绍了EPDR技术的起源,以及使用该技术驱动的业余软件无线电平台专栏。已有玩家通过踩坑证明,进程管道交换数据时间延迟大(10ms),构造时间敏感系统难。除非采用传统的紧耦合设计及更大的颗粒度…

尚品汇-选中状态缓存变更、删除缓存购物车(三十八)

目录: (1)选中状态的变更 (2)删除购物车 (3)流程总结 (1)选中状态的变更 用户每次勾选购物车的多选框,都要把当前状态保存起来。由于可能会涉及更频繁的操…

基于AT89C51单片机的可手动定时控制的智能窗帘设计

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/89469560?spm=1001.2014.3001.5503 C 源码+仿真图+毕业设计+实物制作步骤+11 摘要 I abstract II 第1章 绪论 1 1.1 背景及意义 1 1.2 国内外发展现状 1 1.3 设计思想及基…

ChatGPT等大模型高效调参大法——PEFT库的算法简介

随着ChatGPT等大模型(Large Language Model)的爆火,而且目前业界已经发现只有当模型的参数量达到100亿规模以上时,才能出现一些在小模型无法得到的涌现能力,比如 in_context learing 和 chain of thougt。深度学习似乎…

Excel如何快速的定位到某一列和快速知道当前列

Excel如何快速的定位到某一列和快速知道当前列 背景快速找到某一列---660列快速知道当前列 背景 由于某一次做excel数据太大需要快速知道某一列是多少列和快速定位到某一列对此写了这个 快速找到某一列—660列 SUBSTITUTE(ADDRESS(1, 660, 4), "1", ""…

实现MySQL的主从复制基础

目录 1 MySQL实现主从复制的原理 1.1 实现主从复制的规则 1.2 如何实现主从复制 2 MySQL 实现主从复制实践 2.1 实验环境 2.2 my.cnf 配置添加 2.2.1 配置MSTER 端配置文件 2.2.2 配置SLAVE 端配置文件 2.2.3 三台MySQL服务器重启服务 2.3 创建用于复制的用户 2.4 保证三台主机…

Android实战:过root检测

在启动这个app时,我们会看到一个提示,表示设备处于root环境。如下图所示: 为了过掉到这个root检测,我们可以通过直接Hook Toast.show()方法,并打印调用堆栈信息来实现定位关键代码。以下是相关的Frida脚本代码&#…

esxi 安装 精简版win10

镜像来源:[【不忘初心】Windows10 22H2 (19045.4780) X64 无更新 纯净[深度精简版]1.27G](https://www.pc528.net/22h2s.html) 提供下载地址:https://www.123pan.cn/s/lYtRVv-Wmuf3?提取码:GaD4 先把下载esd 转成iso安装 把下载的esd 重命名为install…

如何使用ssm实现学生宿舍管理

TOC ssm094学生宿舍管理jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大,随着当前时代的信息化,科学化发展,让社会各行业领域都争相使用新的信息技术,对行业内的各种相关数据进行科学化,规范化管理。这样…

YOLOv5改进 | 融合改进 | C3融合EffectiveSE-Convolutional【完整代码 + 小白必备】

秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录: 《YOLOv5入门 改…

如何用comate快速生成一个剩菜好帮手

想法 上班后不想吃饭店的饭菜,时长想自己做一些饭菜,买完菜后却经常放到冰箱中,剩下的菜有无法一下子处理,单纯扔掉有些可惜,但是基于冰箱中的剩菜如何能做出一顿像样的饭菜一致困扰着我,查市面上的程序有…

在不修改应用数据源的情况下,如何确保应用程序能够正常访问adg切换后的主库?

在不修改应用数据源的情况下,如何确保应用程序能够正常访问adg切换后的主库? oracle12c rac测试通过: 1.修改原主库的scanip为某个临时ip,新主库的scanip修改为原生产 2.修改新主库的service_names:dgorcl为原生产的…

学习2d直线拟合

直线拟合算法(续:加权最小二乘)_加权拟合直线法-CSDN博客 直线拟合算法_相位拟合直线-CSDN博客 特别感谢博主无私分享 博文中提到的参考资料《机器视觉算法与应用(双语版)》[德] 斯蒂格(Steger C&#x…