首页 > 解决方案 > libdrm 是否通过 ioctl() 与内核 DRM/显卡通信?

问题描述

这可能是一个愚蠢的问题,因为我对这个主题知之甚少......似乎用户应用程序可以直接与 GPU 对话以渲染图像,例如使用 OpenGL,通过 mesa 和 libdrm,其中 libdrm 是包装各种 ioctl() 调用,如图所示。这是否意味着对于 3D 游戏的每个新帧,游戏应用程序都需要调用 ioctl() 一次(如果需要访问 KMS,甚至可能调用两次)?这听起来像很多用户内核空间障碍(考虑 120 fps 游戏)。

标签: cgraphicslinux-kernelioctldrm

解决方案


libdrm 是一个用户空间包装器,用于执行对底层 KMS 驱动程序功能的细粒度访问,例如模式设置、检查所使用的平面是覆盖平面还是主平面等。对于各种 CPU/GPU/OS 组合,libdrm 实现通常是不同的,因为在内核中运行的硬件驱动程序倾向于支持除标准功能之外的不同功能集。使用 libdrm 的标准方法是打开/dev/node 中可用的 drm 设备,并使用从open().

通常情况下,特定操作系统(如 X11、wayland、hardware-composer)的显示合成器软件需要控制 drm 设备,这意味着非特权应用程序无法成为 DRM 主控。如果尝试使用它们的应用程序不是 DRM 主机,则大多数 libdrm 模式设置功能都不起作用。推荐的做法是使用标准图形库(如 openGL 或 VULKAN)来准备和渲染应用程序中的帧,而不是直接使用 libdrm。

与内核 DRM 模块交互所需的 ioctl 数量很可能不是您在尝试渲染高 FPS 应用程序时将面临的最大瓶颈。在与目标系统的显示合成器合作的同时运行高 fps 应用程序的首选方式是

  • 用于渲染的双缓冲或三缓冲设置,其中要渲染的下一个缓冲区在当前帧完成渲染之前准备好渲染。
  • 尽可能利用硬件加速,例如执行缩放/调整大小/图像格式转换/色彩空间转换。
  • 预计算和重用着色器元素
  • 尝试尽可能多地重用纹理元素,而不是为每一帧渲染计算大量纹理。
  • 尽可能使用 vector/SIMD/SSEv2,3,4/AVX/neon 指令来利用现代 CPU 管道

推荐阅读