window 显示驱动开发-线程和同步级别一级(二)
一、重排范围类
WDDM 不允许以可重入的方式调用某个重排范围类函数。 也就是说,在给定的时间,最多可以在以下函数之一中运行一个线程:
- DxgkDdiAcquireSwizzlingRange
- DxgkDdiReleaseSwizzlingRange
1、一级同步级别的共性:
- 类内不可重入:同一类别的函数在同一时间只能由一个线程执行(跨类别允许并发)。
- 跨进程允许并发:不同进程的线程可以同时调用不同类别的函数(同一进程的多线程仍受限制)。
2、新增类别详解:
1. 重排范围类(Swizzling Range Class)
功能:管理内存的 Swizzling Range(一种优化内存访问的机制,常见于纹理或图形数据布局)。
不可重入函数:
- DxgkDdiAcquireSwizzlingRange(获取Swizzling范围)
- DxgkDdiReleaseSwizzlingRange(释放Swizzling范围)
规则:同一时间只能有一个线程执行此类函数(全局互斥)。
二、覆盖类
WDDM 不允许以可重入的方式调用覆盖类函数之一。 也就是说,在给定的时间,最多可以在以下函数之一中运行一个线程:
- DxgkDdiCreateOverlay
- DxgkDdiDestroyOverlay
- DxgkDdiFlipOverlay
- DxgkDdiUpdateOverlay
功能:处理硬件覆盖层(Overlay),用于高效显示视频或动态内容(如视频播放器)。
不可重入函数:
- DxgkDdiCreateOverlay(创建覆盖层)
- DxgkDdiDestroyOverlay(销毁覆盖层)
- DxgkDdiFlipOverlay(切换覆盖层内容)
- DxgkDdiUpdateOverlay(更新覆盖层属性)
规则:同一时间只能有一个线程执行覆盖类的任一函数。
三、子 I/O 类
WDDM 不允许以可重入的方式调用某个子 I/O 类函数。 也就是说,在给定的时间,每个子设备最多可以在以下函数之一内运行一个线程。
每个子设备同步子 I/O 类函数 (也就是说,允许) 同时调用多个子设备。 但是,如果子设备之间存在内部依赖关系,则显示微型端口驱动程序必须根据需要阻止调用。
- DxgkDdiQueryChildStatus
- DxgkDdiQueryConnectionChange
- DxgkDdiQueryDeviceDescriptor
- DxgkDdiDisplayDetectControl
- DxgkDdiI2CReceiveDataFromDisplay
- DxgkDdiI2CTransmitDataToDisplay
- DxgkDdiOPMConfigureProtectedOutput
- DxgkDdiOPMCreateProtectedOutput
- DxgkDdiOPMDestroyProtectedOutput
- DxgkDdiOPMGetCertificate
- DxgkDdiOPMGetCertificateSize
- DxgkDdiOPMGetCOPPCompatibleInformation
- DxgkDdiOPMGetInformation
- DxgkDdiOPMGetRandomNumber
- DxgkDdiOPMSetSigningKeyAndSequenceNumbers
功能:管理子设备的 I/O 操作(如多显示器环境下的单个显示设备)。
不可重入范围:
- 基于子设备隔离:每个子设备(Child Device)允许一个线程执行子 I/O 类函数,不同子设备可并发。
- 函数示例(未明确列出,但通常包括子设备的资源分配、状态查询等)。
特殊规则:
- 若子设备间存在依赖(如共享硬件资源),驱动程序需自行实现同步机制(如内部锁)来避免冲突。
四、显示类
WDDM 不允许以可重入的方式调用其中一个显示类函数。 也就是说,在给定的时间,最多可以在以下函数之一中运行一个线程:
- DxgkDdiSetTargetGamma
- DxgkDdiSetTargetContentType
- DxgkDdiSetTargetAnalogCopyProtection
- DxgkDdiSetTargetAdjustedColorimetry
五、并发场景示例
允许的并发:
- 线程A调用 DxgkDdiAcquireSwizzlingRange(重排范围类),同时线程B调用 DxgkDdiFlipOverlay(覆盖类)。
- 子设备1的线程C调用子I/O类函数,子设备2的线程D同时调用另一子I/O类函数。
禁止的并发:
- 两个线程同时调用 DxgkDdiUpdateOverlay(同属覆盖类)。
- 同一子设备的两个线程同时进入子I/O类函数。
六、开发者注意事项
同步实现:
- 全局锁:重排范围类和覆盖类需全局锁(如自旋锁或互斥体)保证类内互斥。
- 子设备锁:子I/O类需为每个子设备维护独立的锁,并在存在依赖时扩展锁范围。
依赖处理:
- 若子设备共享资源(如GPU引擎),需在驱动中显式同步(例如:子设备1和子设备2的I/O操作需串行化)。
错误处理:
- 违反规则可能导致 STATUS_GRAPHICS_RESOURCE_IN_USE 或 STATUS_GRAPHICS_TOO_MANY_REFERENCES。
七、设计意图
- 性能优化:通过细粒度类别划分(如子设备级并发)最大化硬件利用率。
- 资源隔离:防止覆盖层操作与内存重排操作相互干扰,确保视频播放流畅性。
- 扩展性:支持多显示器环境(子设备)的独立管理。
八、典型应用场景
- 视频播放:DxgkDdiFlipOverlay 快速切换视频帧,同时另一线程通过 DxgkDdiAcquireSwizzlingRange 优化纹理内存。
- 多显示器系统:子设备1的分辨率调整(子I/O类)与子设备2的覆盖层更新(覆盖类)并行执行。
通过遵循这些规则,驱动程序可以在复杂多线程环境下保持稳定性和高性能。