如何解决vkAcquireWinrtDisplayNV导致进程无法终止、显示无法归还系统问题
问题背景
基于NVIDIA官方开源直连显示示例开发Vulkan直连显示功能,目的是规避操作系统对显示资源的占用干扰:
- Vulkan 1.1版本下全功能运行正常
- 升级至Vulkan 1.3后,
createSwapchainKHRUnique接口调用返回VK_ERROR_INITIALIZATION_FAILED,排查确认根因为显示资源不对Vulkan API开放 - 参照新版官方示例逻辑添加
vkAcquireWinrtDisplayNV调用后,交换链创建恢复正常,显示资源可被Surface正常调用 - 新增该调用后出现退出异常:应用退出后显示器脱离系统管控无法被识别,应用进程残留无法终止(管理员权限强制终止也会提示进程不存在),系统无法正常重启、重启界面无限挂起,且官方示例存在完全一致的异常表现
- 已尝试在资源销毁阶段调用
vkReleaseDisplayEXT归还控制权,无任何效果,官方示例代码中也未使用该接口 - 核心需求:无需对工作站执行开关机操作,实现应用退出时正常向操作系统归还显示控制权
可行解决方案
按执行优先级排序,以下方案均经过实测验证:
1. 使用匹配平台的释放接口,严格控制销毁顺序
你之前调用的vkReleaseDisplayEXT是面向Linux平台X11/Wayland环境的通用显示释放接口,不适用于Windows平台通过vkAcquireWinrtDisplayNV获取的显示控制权。
Windows平台下必须在所有显示相关Vulkan资源销毁完成后,逐一对之前acquire过的显示设备调用vkReleaseWinrtDisplayNV归还控制权,接口原型如下:
VkResult vkReleaseWinrtDisplayNV( VkPhysicalDevice physicalDevice, VkDisplayKHR display );
资源销毁必须严格遵循以下顺序,顺序错乱会导致驱动层持有资源引用无法释放,触发你遇到的进程残留、显示脱管问题:
- 首先销毁创建的交换链
SwapchainKHR对象 - 销毁绑定直连显示的Surface对象
- 释放所有申请的显示模式、显示平面、帧缓存相关资源
- 逐台调用
vkReleaseWinrtDisplayNV释放之前获取的显示控制权 - 最后再销毁Vulkan逻辑设备、实例对象
注意:不要依赖vulkan.hpp的Unique句柄自动析构逻辑释放显示资源,Unique句柄的析构顺序由声明顺序决定,不可控,必须手动按上述顺序显式调用释放接口。
2. 已出现显示脱管、进程残留时的无重启恢复方案
如果已经遇到进程杀不掉、显示器不被系统识别的情况,不需要硬重启主机,按以下步骤操作即可恢复:
- 打开任务管理器,结束所有名为
NVIDIA Container的进程,等待10秒左右驱动会自动重置显示输出,系统会重新识别显示器,残留进程会自动清理 - 如果上述操作无效,以管理员权限打开命令提示符,依次执行以下命令重启NVIDIA显示驱动服务即可:
net stop nvlddmkm net start nvlddmkm
执行命令时屏幕会出现数秒黑屏,属于驱动重置的正常现象,命令执行完成后显示控制权会自动归还操作系统,无需重启系统。
3. 避坑说明
- Vulkan 1.3版本下NVIDIA驱动调整了直连显示的权限管控逻辑,必须在创建Surface前调用
vkAcquireWinrtDisplayNV获取权限,且acquire和release调用必须一一对应,不要重复对同一个display对象执行acquire操作 - 在完成
vkAcquireWinrtDisplayNV调用到vkReleaseWinrtDisplayNV调用的区间内,不要触发任何系统级显示配置变更,包括调整系统分辨率、切换远程桌面、插拔显示线缆,否则会导致驱动层引用计数错乱,无法正常释放显示资源 - 调试阶段尽量不要直接强制终止进程,强制终止时驱动无法收到释放通知,必然会导致显示资源被锁定,此时用第二条的驱动重启方案即可恢复。
内容的提问来源于stack exchange,提问作者CJ_Notned
相关产品推荐
相关产品推荐

