3. 常见渲染故障现象:屏幕撕裂、卡顿、黑屏/花屏与渲染延迟

在 DRM 驱动开发与调试中,渲染故障是用户最直观感知到的异常。本章聚焦四种核心故障现象:屏幕撕裂(Tearing)、画面卡顿(Jank)、黑屏/花屏以及渲染延迟过高。理解这些现象背后的 DRM 机制(如 VBlank、Buffer Flip、Fence 同步)是精准定位问题的前提。

3.1 屏幕撕裂(Tearing)

现象描述:画面在水平方向出现错位或断裂,通常发生在快速移动的场景中。根本原因是 GPU 在显示器刷新(VBlank)期间更新了帧缓冲区(Front Buffer),导致显示器在一帧内同时显示了新旧两帧的内容。

核心机制:DRM 的 Page Flip 操作若未与 VBlank 同步(即未使用 VBlank 等待或 Atomic Commit 的垂直同步标志),则会产生 Tearing。

3.1.1 撕裂产生的时序图

下图展示了未同步的 Buffer Flip 如何导致撕裂:

屏幕撕裂产生时序 时间 VBlank 区间 VBlank 区间 扫描线(显示中) Flip 撕裂:上半部分旧帧 + 下半部分新帧 (Flip 发生在扫描线到达中间时)

3.1.2 排查清单

排查项检查方法典型根因
VBlank 等待检查 DRM_IOCTL_MODE_PAGE_FLIP 是否设置 DRM_MODE_PAGE_FLIP_EVENT用户态未等待 VBlank 事件
Atomic Commit 标志检查 CRTC 属性 "vrr_enabled" 或 "VRR" 是否误开启可变刷新率(VRR)范围配置错误
双缓冲 vs 三缓冲查看 /sys/kernel/debug/dri/0/state 中的 fb_id 切换频率单缓冲模式或 Buffer 数量不足
驱动层面dmesg 搜索 "tearing" 或 "page flip timeout"GPU 调度器延迟导致 Flip 错过 VBlank
快速验证:在 weston 或 kmscube 中启用 --fullscreen --vsync 参数,若撕裂消失,则确认是用户态同步缺失。

3.2 画面卡顿(Jank)

现象描述:画面出现不连续的停顿或跳跃,帧率不稳定。Jank 通常由渲染管线中的某个环节超时导致,例如 GPU 提交延迟、Fence 等待超时或 DRM 的 Atomic Commit 被阻塞。

3.2.1 Jank 的典型流程

画面卡顿产生流程 用户态提交 DRM Atomic GPU 渲染 Fence 等待 VBlank 翻转 卡顿点:Fence 等待超时 或 VBlank 翻转错过窗口 导致上一帧重复显示或下一帧延迟提交

3.2.2 Jank 分类与定位

Jank 类型特征DRM 相关工具
提交延迟 Jankdrm_atomic_commit 返回 -EBUSY 或 -ETIMEDOUTperf trace -e drm:*
渲染超时 JankGPU 作业在调度器中等待超过 2 个 VBlank 周期drm_info + /sys/kernel/debug/dri/*/gpu_busy
Fence 饥饿 Jankdma_fence_wait_timeout 返回 0ftrace filter: dma_fence_signaled
VBlank 错过 JankCRTC 的 vblank_count 出现跳变或停滞cat /sys/kernel/debug/dri/*/vblank_count
注意:Jank 与 Tearing 有时同时出现。若 VBlank 同步开启但仍卡顿,优先检查 GPU 频率是否被限制(如 devfreq 策略导致降频)。

3.3 黑屏/花屏

现象描述:显示器无信号(黑屏)或显示随机像素/色块(花屏)。黑屏通常意味着 CRTC 或 Encoder 未正确使能;花屏则多与帧缓冲区数据损坏或格式不匹配有关。

3.3.1 黑屏/花屏根因对比

现象可能根因DRM 状态检查
黑屏(无背光)Backlight 属性未设置或 PWM 驱动异常cat /sys/class/backlight/*/brightness
黑屏(有背光)CRTC 未使能或 Connector 状态为 disconnecteddrmModeGetConnector 返回的连接状态
花屏(水平条纹)Fence 未等待,GPU 写入未完成即翻转检查 Atomic Commit 中 in_fence_fd 是否有效
花屏(随机色块)帧缓冲区 stride 或 pixel_format 不匹配drmModeAddFB2 的 pitch 与硬件要求对齐
花屏(全屏绿色/紫色)色彩空间转换错误(如 YUV 误传为 RGB)检查 plane 的 color_encoding 属性

3.3.2 花屏排查流程图

花屏排查决策树 花屏出现 检查 fb 格式与 stride 检查 Fence 同步 格式匹配? Fence 已 signaled? 修正 stride/format 添加 in_fence 等待 验证:重新 Atomic Commit
调试命令:使用 modetest -M -p 查看当前 plane 的 fb_id 和 format,对比硬件支持的格式列表(通常位于 /sys/kernel/debug/dri/*/framebuffer)。

3.4 渲染延迟过高

现象描述:从用户输入到画面更新之间的延迟明显增加(如触控笔延迟 > 50ms)。渲染延迟通常由管线中的排队、等待或缓冲区复制引起。

3.4.1 延迟构成分析

延迟阶段典型耗时DRM 相关因素
用户态提交0.5 – 2 msdrmModeAtomicCommit 的 ioctl 开销
内核排队1 – 8 ms调度器等待 GPU 空闲;drm_sched 队列深度
GPU 渲染2 – 16 ms着色器复杂度;显存带宽瓶颈
Fence 等待0 – 16 ms等待前一帧完成;out_fence 未及时 signaled
VBlank 翻转0 – 16.7 ms等待下一个 VBlank 窗口(60Hz 显示器)

3.4.2 延迟优化方向

  • 减少排队深度:通过 drm_sched 的 num_jobs 参数控制 GPU 队列中的最大作业数,避免过度缓冲。
  • 使用 Direct Flip:在 Atomic Commit 中设置 DRM_MODE_ATOMIC_NONBLOCK 并结合 in_fence_fd,减少内核态阻塞。
  • 启用 VRR(可变刷新率):在支持 FreeSync 或 HDMI-VRR 的显示器上,允许显示器在帧就绪后立即刷新,而非等待固定 VBlank。
  • 避免隐式同步:使用 dma-buf 的显式同步(Explicit Sync)替代隐式 dma_fence 等待,减少不必要的同步点。
延迟测量方法:在用户态记录 clock_gettime(CLOCK_MONOTONIC) 在 Atomic Commit 前后,结合 drm_wait_vblank 的返回时间,可精确计算端到端延迟。使用 perf record -e drm:drm_vblank_event 可捕获内核态 VBlank 事件时间戳。

3.5 故障现象总结表

故障现象主要根因首要排查方向典型 DRM 调试接口
屏幕撕裂Page Flip 未同步 VBlank检查 DRM_MODE_PAGE_FLIP_EVENT 标志drm_wait_vblank
画面卡顿Fence 等待超时 / 提交阻塞检查 Atomic Commit 返回码与 Fence 状态drm_atomic_state_dump
黑屏CRTC/Encoder 未使能检查 Connector 状态与 CRTC 激活属性modetest -c
花屏帧缓冲区格式/stride 不匹配验证 fb 的 pixel_format 与硬件兼容性drmModeGetFB
渲染延迟高管线排队深 / VBlank 等待测量各阶段耗时,优化队列深度perf trace + drm:* 事件