window 显示驱动开发-用户模式显示驱动程序的线程模型

用户模式显示驱动程序不会同时加载到多个进程中,用户模式显示驱动程序 DLL 单独加载到每个进程的地址空间中。 不过,多个线程可以同时在用户模式显示驱动程序中运行。 但是,在用户模式显示驱动程序中运行的每个线程都必须访问不同的显示设备,该设备是通过调用用户模式显示驱动程序的 CreateDevice 函数创建的。 例如:

  • 创建两个 Microsoft Direct3D 设备的应用程序可以有两个单独访问这些设备的线程。
  • 应用程序可以在两个不同的线程上使用 Microsoft DirectX 9.0 Direct3D 运行时创建的 Direct3D 设备以及 DirectX 5.0 运行时创建的 Microsoft DirectDraw 设备。

注意 使用同一显示设备的两个或多个线程永远无法在用户模式显示驱动程序中同时运行。

与显示微型端口驱动程序一样,用户模式显示驱动程序不需要使用任何全局数据结构,因为 Direct3D 设备是独立的,并且每个设备的状态和资源不会影响其他设备。 如果用户模式显示驱动程序必须维护全局跨设备数据结构 (例如,对于自定义系统内存堆管理器) ,它必须使用自己的机制来仲裁访问。 强烈建议不要使用驱动程序管理的此类全局数据结构。 由于 Direct3D 运行时在必须访问资源的每个用户模式显示设备中打开共享资源的独立"视图",因此跨进程或跨设备资源的处理方式不应不同于单个进程或设备使用的资源。 生存期和其他管理由 DirectX 图形内核子系统 (Dxgkrnl.sys) 处理。

在多处理器计算机上,Direct3D 运行时可能从工作线程而不是从main应用程序线程调用用户模式显示驱动程序。 这种多处理器优化对用户模式显示驱动程序是透明的。 当运行时使用多处理器优化时,它仍然确保在任何给定时间,只有一个引用特定设备的线程在驱动程序中运行。

1. UMD 的进程隔离性

每个进程独立加载 UMD DLL

  • UMD 不会在多个进程间共享,而是 每个使用图形 API(如 Direct3D/DirectDraw)的进程都会加载自己的 UMD 副本。
  • 例如:进程 A 和进程 B 各自加载 igdumd64.dll(Intel UMD),但两者内存完全隔离。

无全局共享状态

  • 由于 UMD 是进程内加载,默认不应使用跨进程的全局数据结构(如静态变量)。
  • 如需跨设备共享资源(如纹理),应由 DirectX 图形内核(Dxgkrnl.sys) 管理。

2. 线程并发规则

(1) 线程与设备的绑定关系

一个线程只能访问一个设备

每个线程在 UMD 中运行时,必须绑定到 通过 CreateDevice 创建的特定显示设备(如 Direct3D 设备)。

✅ 允许的并发:

  • 线程 1 → 设备 A
  • 线程 2 → 设备 B

❌ 禁止的并发:

  • 线程 1 和线程 2 → 同时访问设备 A

多处理器优化

Direct3D 运行时可能从 工作线程(非主线程)调用 UMD,但运行时保证:

  • 同一设备不会被多线程同时访问(运行时内部同步)。

(2) 跨设备资源管理-------资源共享通过 Dxgkrnl.sys

即使两个进程(或同一进程的两个设备)共享同一纹理/缓冲区,UMD 无需直接处理跨进程同步。

  • Direct3D 运行时为每个设备创建独立的 "视图",内核负责实际内存管理。
  • 例如:ID3D11Device::OpenSharedResource 的底层实现由内核模式驱动处理。

3. 开发注意事项

(1) 避免全局状态

禁止使用全局变量(如 static 或跨设备共享的堆管理器)。

  • 如果必须使用(如自定义内存池),需通过 线程锁(如 CRITICAL_SECTION) 或 原子操作 保护。
  • 推荐替代方案:将状态存储在设备上下文(如 D3DDDI_DEVICECALLBACKS)中。

(2) 设备独立性

每个 CreateDevice 调用返回的设备对象应是 完全独立的。

  • 设备 A 的状态(如渲染管线)不应影响设备 B。
  • 示例错误:在设备 A 中修改全局渲染状态,导致设备 B 异常。

(3) 多线程安全

UMD 需支持重入(Reentrancy),但仅限于 不同设备的并发调用。

  • 例如:线程 1 调用设备 A 的 DrawPrimitive,同时线程 2 调用设备 B 的 Present。
  • 需确保 设备上下文无竞争条件(如使用每设备的锁)。

4. 典型场景示例

场景 1:多设备多线程

复制代码
进程 X:
- 线程 1 → Direct3D 设备 A (创建 SwapChain 并渲染)
- 线程 2 → Direct3D 设备 B (执行计算着色器)

✅ 合法:两个线程访问不同设备,UMD 需正确处理并发。

场景 2:跨进程资源共享

复制代码
进程 A:
- 创建纹理 T 并通过 HANDLE 共享给进程 B。

进程 B:
- 调用 OpenSharedResource 获取纹理 T 的视图。

合法:UMD 无需直接同步,内核(Dxgkrnl.sys)管理实际内存。

5. 总结

特性 用户模式显示驱动程序(UMD) 内核模式微型端口驱动(KMD)
加载方式 每个进程独立加载 全局唯一(系统范围)
线程并发 允许多线程,但每设备单线程 依赖 WDDM 同步级别(Level 0-3)
资源共享 通过 Dxgkrnl.sys 管理 直接管理 GPU 资源
全局状态 禁止(或自行同步) 可使用(但需同步)

UMD 的核心设计原则

  1. 设备隔离:每个设备独立运行,避免副作用。

  2. 线程安全:支持多设备并发,但单设备串行。

  3. 依赖内核:跨进程/设备资源共享由 Dxgkrnl.sys 处理。

遵循这些规则可确保 UMD 在复杂多线程环境下稳定运行。

相关推荐
嵌入式郑工4 小时前
RK3566 LubanCat 开发板 USB Gadget 配置完整复盘
linux·驱动开发·ubuntu
雾削木1 天前
树莓派 ESPHome 固件编译与烧录全攻略(解决超时与串口识别问题)
驱动开发
春日见2 天前
win11 分屏设置
java·开发语言·驱动开发·docker·单例模式·计算机外设
DarkAthena3 天前
【GaussDB】手动编译不同python版本的psycopg2驱动以适配airflow
驱动开发·python·gaussdb
松涛和鸣3 天前
DAY66 SPI Driver for ADXL345 Accelerometer
linux·网络·arm开发·数据库·驱动开发
嵌入式郑工3 天前
# RK3576 平台 RTC 时钟调试全过程
linux·驱动开发·ubuntu
GS8FG3 天前
针对Linux,RK3568平台下,I2C驱动的一点小小的领悟
linux·驱动开发
一路往蓝-Anbo3 天前
第 4 篇:策略模式 (Strategy) —— 算法的热插拔艺术
网络·驱动开发·stm32·嵌入式硬件·算法·系统架构·策略模式
A-花开堪折4 天前
RK3568 Android 11 驱动开发(五):串口驱动适配
驱动开发
bandaoyu4 天前
【RDMA】rdma指令
驱动开发