DRM中render-node编号的分配

DRM系统

DRM是direct rendering manager的简称。DRM是linux kernel中与负责video cards功能的GPU打交道的子系统。DRM给出了一组API,可以供用户程序来发送命令和数据给GPU设备从而来控制比如display、render等功能。

render-node由来

在以前,DRM子系统中给每个DRM device注册的device-node就是:/dev/dri/cardX ,通过该节点来作mode-setting和rendering的控制。后来发现这么做有问题:

  • mode-setting和rendering是通过同一个文件节点node来控制的

  • 单卡的mode-setting资源不能在多个graphics-servers之间切分使用

  • 在多cards之间共享display-controller实现过于复杂

然后就有了一些改进来解决这些问题。最终是mode-setting 和 render节点分家

render node

render-node架构大概是2009年左右提出来的。站在用户程序角度来看,render node的作用是用来加速computing和rendering,render node可以通过 /dev/dri/renderDX 被访问,并且提供了基本的DRM rendering interface。与 /dev/dri/cardX 节点相比,/dev/dri/renderDX 少了一些特性:

  • 没有mode-setting(KMS)ioctls功能

  • 用dma-buf替换掉gem-flink(非安全的)

  • 不再需要DRM-auth认证

  • 不再支持pre-KMS DRM-API

这样一来,当应用程序需要hardware-acclerated rendering、访问GPGPU、offscreen rendering等时,就不需要通过DRI或者wl_drm来访问graphics-server,而是直接打开某个render node就开始使用即可。对于render node的访问权限控制则通过标注的file-system modes来控制了。

render-node并没有提供新的API,它们只是将原有的DRM-API分出了一部分到一个新的device-node,原来的node也保留了下来用于如mode-setting等控制。

render-node也没有和任何一个card进行绑定,它是由原有node的同一个driver创建的,所以尝试在原有node和render-node之间进行connect连接通信没有意义。当应用程序需要和graphics-server进行通信时,可以通过dma-buf

mode-setting node

虽然从原有的node中分离出一个render-node,简化了应用程序的访问,但对于mode-setting程序的访问没有简化。当一个graphics-server想要编程一个display-controller时,它需要是给定card的DRM-Master,可以通过drmSetMaster()接口来获得身份,但同时只能有一个DRM-Master,而且必须是由CAP_SYS_ADMIN特权的程序才能成为DRM-Master,这会带来问题:

  • 不能以非root权限运行XServer

  • 不能在同一个card上使用两个不同的XServer来控制两个不同的独立的显示器

首先想到的解决办法就是分离出mode-setting node,类似render-node的方式,/dev/dri/modesetD1 和 /dev/dri/modesetD2 节点,来分割KMS CRTC和Connector资源。

另一种方法是将所有的mode-setting资源绑定到一个DRM-Master对象,然后谁要访问mode-setting资源就可以通过访问该DRM-Master对象来实现。

DRM infrastructure

不管是render-node还是mode-setting-node,在kernel角度是如何体现的?

如果hardware没有display-controller,则可以不设置DRIVER_MODESET flag只设置DRIVER_RENDER flag,这样内核DRM只会创建render-node。如果一个hardware只有display-controller而没有rendering hardware,可以设置DRIVER_MODESET而不设置DRIVER_RENDER

大概回顾了下render node的由来。那么render node由kernel来负责创建,其编号为何从128开始,答案估计还要到kernel中寻找。

drm_dev_init

linux kernel中 drivers/gpu/drm/drm_drv.c中定义了drm_dev_init()函数,其中创建drm设备编号的代码如下

	if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) {ret = drm_minor_alloc(dev, DRM_MINOR_ACCEL);if (ret)goto err;} else {if (drm_core_check_feature(dev, DRIVER_RENDER)) {ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);if (ret)goto err;}ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);if (ret)goto err;}

涉及到两个枚举类型结构体

enum drm_driver_feature {DRIVER_GEM			= BIT(0),DRIVER_MODESET			= BIT(1),DRIVER_RENDER			= BIT(3),DRIVER_ATOMIC			= BIT(4),DRIVER_SYNCOBJ                  = BIT(5),DRIVER_SYNCOBJ_TIMELINE         = BIT(6),DRIVER_COMPUTE_ACCEL            = BIT(7),DRIVER_USE_AGP			= BIT(25),DRIVER_LEGACY			= BIT(26),DRIVER_PCI_DMA			= BIT(27),DRIVER_SG			= BIT(28),DRIVER_HAVE_DMA			= BIT(29),DRIVER_HAVE_IRQ			= BIT(30),
};enum drm_minor_type {DRM_MINOR_PRIMARY,DRM_MINOR_CONTROL,DRM_MINOR_RENDER,DRM_MINOR_ACCEL = 32,
};

当drm core检查到device设置了DRIVER_RENDER标签时,就通过drm_minor_alloc(dev, DRM_MINOR_RENDER)来分配ID,而drm_minor_alloc()函数中最终分配ID是通过idr_alloc()函数来实现,这里的type传入的就是DRM_MINOR_RENDER,也就是2。

r = idr_alloc(&drm_minors_idr,NULL,64 * type,64 * (type + 1),GFP_NOWAIT);//idr_alloc又是调用idr_alloc_u32来实现		
int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp)
{u32 id = start;int ret;if (WARN_ON_ONCE(start < 0))return -EINVAL;ret = idr_alloc_u32(idr, ptr, &id, end > 0 ? end - 1 : INT_MAX, gfp);if (ret)return ret;return id;
}
EXPORT_SYMBOL_GPL(idr_alloc);
 * idr_alloc() - Allocate an ID.* @idr: IDR handle.* @ptr: Pointer to be associated with the new ID.* @start: The minimum ID (inclusive).* @end: The maximum ID (exclusive).* @gfp: Memory allocation flags.

idr_alloc()的底3个参数就是ID的start,第4个参数是ID范围的end。所以,对于DRIVER_RENDER属性的device来说,其ID范围是

DRM_MINOR_RENDER * 64 = 128 至 (DRM_MINOR_RENDER + 1) * 64 = 192 之间。

所以才有renderD128、renderD129。

内核如何管理render-node的编号

问题:DRM中如何做到一个已经分配了的ID比如128,下一个device来分配时就不使用128而是129呢?换句话说kernel中如何记忆ID的分配结果的?

int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid,unsigned long max, gfp_t gfp)
{struct radix_tree_iter iter;void __rcu **slot;unsigned int base = idr->idr_base;unsigned int id = *nextid;if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR)))idr->idr_rt.xa_flags |= IDR_RT_MARKER;id = (id < base) ? 0 : id - base;radix_tree_iter_init(&iter, id);slot = idr_get_free(&idr->idr_rt, &iter, gfp, max - base);if (IS_ERR(slot))return PTR_ERR(slot);*nextid = iter.index + base;/* there is a memory barrier inside radix_tree_iter_replace() */radix_tree_iter_replace(&idr->idr_rt, &iter, slot, ptr);radix_tree_iter_tag_clear(&idr->idr_rt, &iter, IDR_FREE);return 0;
}
EXPORT_SYMBOL_GPL(idr_alloc_u32);

这里使用了基数树(radix-tree)。

两个显卡其分配render-node的顺序

比如我这个pc上有两个显卡intel UHD Graphics 630和Nvidia GTX 1050 Ti,然后/dev/dri/下也有两个render-node,renderD128和renderD129,内核分配它们的顺序是如何确定的?

应该是扫描PCI设备的时候就确定顺序了。

ubuntu上查看哪个card和哪个GPU绑定:

drm_info    #该命令可以查看/dev/dri/card0对应的GPU驱动

比如我这里两个显卡,card0对应intel 630, card1对应nvidia GTX 1050Ti。

那么如何确定render node和GPU对应关系?

ls /sys/class/drm/card0/device/drm/
#可以看到card0中有card0, controlD64, renderD128
ls /sys/class/drm/card1/device/drm/
#可以看到card1中有card1, controlD65, renderD129

参考:
DRM render node number

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

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

相关文章

Java数字处理类-- Math类--数学运算

在Java中提供了一个执行数学基本运算的Math类,该类包括了常用的数学运算方法和常量&#xff0c;包括【三角函数方法】&#xff0c;【指数函数方法】&#xff0c;【取整函数方法】、【取最大值函数方法】、【取最小值函数方法】、【取平均值函数方法】、【对数函数方法】&#x…

MSF入门

漏洞数据库、利用工具集MSF MSF: The Metasploit Framework 简称美少妇 MSF安装 安装平台 Kali Linux: 自带Linux: 阿里云CentOS7安装msfWindows.msi 使用方式 msfconsole 交互终端 msfcli . msfconsole -x"command:..."图形界面: artimate、viper 下面我会用…

ES6 Class和Class继承

1.class的基本语法 class可以理解为是一个语法糖&#xff0c;将js只能通过构造函数创建实例的方法进行了补充 构造函数&#xff1a; function Person ({ name, age18 }) {this.name namethis.age age } new Person({name: 张三}) Class类&#xff1a; class Person {con…

SLAM从入门到精通(构建自己的slam包)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 我们学习了很多的开源包&#xff0c;比如hector、gmapping。但其实我们也可以自己编写一个slam包。这么做最大的好处&#xff0c;主要还是可以帮助…

抽象轻松的java

先看问题代码和运行结果 public static void main(String[] args) {Scanner scanner new Scanner(System.in);System.out.println("输入一串数字");int i scanner.nextInt();System.out.println("i&#xff1a;" i);int z scanner.nextInt();System.ou…

宏(预编译)详解

目录 一、程序的编译环境 二、运行环境 三、预编译详解 3.1预定义符号 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 3.2.3#define替换规则 3.2.4 #和## 2)##的作用&#xff1a; 3.2.5宏和函数的对比 3.2.6宏的命名约定和#undef指令 一、命名约定&#xff1a; …

学信息系统项目管理师第4版系列32_信息技术发展

1. 大型信息系统 1.1. 大型信息系统是指以信息技术和通信技术为支撑&#xff0c;规模庞大&#xff0c;分布广阔&#xff0c;采用多级 网络结构&#xff0c;跨越多个安全域&#xff1b;处理海量的&#xff0c;复杂且形式多样的数据&#xff0c;提供多种类型应用 的大系统 1.1.…

【常用图像增强技术,Python-opencv】

文章目录 常用图像增强技术调整大小灰度变换标准化随机旋转中心剪切随机裁剪高斯模糊亮度、对比度和饱和度调节水平翻转垂直翻转高斯噪声随机块中心区域 常用图像增强技术 图像增强技术是常用于数据增强的方法&#xff0c;可以帮助增加数据集中图像的多样性&#xff0c;提高深…

webpack 项目升级成vite项目

将webpack升级成vite得步骤&#xff1a; 1.把 public/index.html 移动到项目根目录&#xff0c;把文件中的 %PUBLIC_URL% 去掉 // %PUBLIC_URL%就是指向对应的public文件夹的绝对路径2.把 src/index.js 入口文件 &#xff0c;改成 src/main.ts &#xff0c;并在 index.html 文…

论文阅读:Point-to-Voxel Knowledge Distillation for LiDAR Semantic Segmentation

来源&#xff1a;CVPR 2022 链接&#xff1a;https://arxiv.org/pdf/2206.02099.pdf 0、Abstract 本文解决了将知识从大型教师模型提取到小型学生网络以进行 LiDAR 语义分割的问题。由于点云的固有挑战&#xff0c;即稀疏性、随机性和密度变化&#xff0c;直接采用以前的蒸馏…

Mapping 设计指南

Mapping 设计指南 目录概述需求&#xff1a; 设计思路实现思路分析1、properties2.fields 3.search_analyzer4.2、format1、enabled2、doc_values 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0…

ROS自学笔记十二:Command ‘git‘ not found, but can be installed with:

这个错误提示表明在你的系统上未安装Git命令行工具。你可以按照以下步骤在不同的操作系统上安装Git&#xff1a; 在Linux上安装Git Ubuntu/Debian&#xff1a; sudo apt update sudo apt install git Fedora&#xff1a; sudo dnf install git CentOS&#xff1a; sudo yu…

Vue3 + Nodejs 实战 ,文件上传项目--大文件分片上传+断点续传

目录 1.大文件上传的场景 2.前端实现 2.1 对文件进行分片 2.2 生成hash值&#xff08;唯一标识&#xff09; 2.3 发送上传文件请求 3.后端实现 3.1 接收分片数据临时存储 3.2 合并分片 4.完成段点续传 4.1修改后端 4.2 修改前端 5.测试 博客主页&#xff1a;専心_前端…

【Python】文件操作

一、文件的编码 思考:计算机只能识别:0和1&#xff0c;那么我们丰富的文本文件是如何被计算机识别&#xff0c;并存储在硬盘中呢? 答案:使用编码技术( 密码本)将内容翻译成0和1存入 编码技术即:翻译的规则&#xff0c;记录了如何将内容翻译成二进制&#xff0c;以及如何将二…

人人开源前后端分离开源项目启动流程(超详细)

renren-security是一个轻量级的&#xff0c;前后端分离的Java快速开发平台&#xff0c;能快速开发项目并交付【接私活利器】采用SpringBoot、Shiro、MyBatis-Plus、Vue3、TypeScript、Element Plus、Vue Router、Pinia、Axios、Vite框架&#xff0c;开发的一套权限系统&#xf…

【计算机网络笔记】OSI参考模型基本概念

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

2023-9-12 阿里健康2024秋招后端开发-体检及泛医疗二面

1 自我介绍 2 快手实习 2.1 说说你在实习期间遇到的挑战、收获 &#xff08;1&#xff09;在设计模式的应用能力上&#xff0c;有了很大的提高&#xff0c;使用模板设计模式&#xff0c;架构实例反向同步到架构定义&#xff0c;使用了策略模式 &#xff08;2&#xff09; …

(H5轮播)vue一个轮播里显示多个内容/一屏展示两个半内容

效果图 : html: <div class"content"><van-swipeclass"my-swipe com-long-swipe-indicator":autoplay"2500"indicator-color"#00C4FF"><van-swipe-itemclass"flex-row-wrap"v-for"(items, index) in M…

【Git】升级MacOS系统,git命令无法使用

终端执行git命令报错 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun安装这个东东&#xff0c;&#xff1f;需要42小时 最终解决&#xff1a; 下载安装 https…

【WPF】对Image元素进行缩放平移等操作

元素布局 <Border Grid.Row"1" Name"border" ClipToBounds"True" Margin"10,10,10,10"><Image Name"image" Visibility"Visible" Margin"3,3,3,3" Grid.Column"1" Source"{Bin…