Windows Hyper-V GPU虚拟化&串流全攻略
大家在日常中或多或少都会有虚拟机的需求,尤其WSL2普及之后,顺手启用Hyper-V来跑虚拟机几乎是标配,但Hyper-V默认默认并不提供GPU虚拟化支持,日用操作都会明显卡顿,更不用说跑大型应用或玩游戏了。实际上,即使是Windows家庭版搭配消费级显卡,也是有GPU虚拟化的能力的,只是不给下放,无法通过常规手段开启。
很久之前就有挂机的需求,主要是拿Better GI来自动做每日任务、刷材料,但是又不想影响到日常用电脑,于是就用Hyper-V起一个虚拟机,并配合GPU虚拟化来实现后台挂机。已经稳定跑将近一年了,很多小伙伴都比较好奇如何实现,所以就有了这一篇从0到1的教程。
创建虚拟机并安装系统
启用Hyper-V
首先确保BIOS中开启了虚拟化技术(Intel VT-x/AMD-V),目前大部分设备默认都是开启的
如果你的Windows还没有启用Hyper-V,请按照微软的官方教程启用
注意:Windows家庭版默认是不支持Hyper-V的,可以执行下面的脚本来启用:
pushd "%~dp0"
dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hv-home.txt
for /f %%i in ('findstr /i . hv-home.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"
del hv-home.txt
Dism /online /enable-feature /featurename:Microsoft-Hyper-V -All /LimitAccess /ALL
pause
Code language: JavaScript (javascript)把这段代码复制到记事本中,保存为任意名称的bat,然后在bat脚本上右键,以管理员身份运行,等待安装完毕后重启即可
下载Windows 11安装镜像
推荐前往Next I Tell you下载,切记选择和你主机的系统同一个大版本的镜像,例如我是Win11 25H2,直接下载最新的Windows 11 (consumer editions) 25H2即可

创建虚拟机
进入Hyper-V管理器主界面,新建虚拟机

输入虚拟机的名称,如果有需要,可以自定义存储位置,然后点击下一页

接下来的几页配置没有太多需要改的,直接用文字列出
- 指定代数:一般选择第二代
- 分配内存:如果要玩游戏,推荐12G以上,注意使用GPU虚拟化不要开启动态内存
- 配置网络:连接选择Default Switch
- 连接虚拟磁盘:创建虚拟硬盘,大小请根据你的需要配置
- 安装选项:以后安装操作系统
配置无误后,点击完成

配置虚拟机
虚拟机新建完成后,右键点击设置

先来添加虚拟DVD驱动器,以便加载系统安装镜像,点击SCSI控制器->DVD驱动器->添加

然后选择添加的DVD驱动器,介质切换为映像文件,浏览并选中之前下载的Windows11安装镜像,完成后保存

然后点击安全->加密支持,勾选启用受信任的平台模块(Windows11需要TPM才能安装),点击应用

切换到固件页面(必须先应用前面的配置),将网络适配器移动到最下方,然后保存,否则开机会卡1分钟网络引导

切换到检查点页面,关闭启用检查点(GPU虚拟化不支持)

安装系统
回到主界面,在虚拟机上右键,选择连接

然后会弹出连接界面,这时虚拟机是关机状态,我们点击启动

注意,启动后需要按下任意键,才可以进入安装界面。

按照常规安装步骤,一路下一步即可安装
- 产品密钥:选择我没有产品密钥
- 选择映像:Windows 11 专业版

不出意外,等待一段时间的安装,即可顺利进入系统

初始化系统
按照正常流程一直下一步,填写必要信息(设备名称要记住,后面会用),等待完成初始化

最新版本的Windows11在设置阶段,会联网下载系统更新,这个过程可能比较慢,请耐心等待

最后再登录你的微软账号,以及一些简单的设置,即可完成配置
注意,完成配置后,可能卡在如下界面,这可能是开启了Windows Hello导致的
我们先点击工具栏的查看->取消勾选增强会话

关闭增强会话后,就能正常进入桌面了,我们打开设置-账户-登录选项,取消勾选仅允许对此设备上的Microsoft账户使用Windows Hello登录

关闭此选项后,再次打开 查看-增强会话,即可恢复正常
配置GPU虚拟化
宿主机配置
先将虚拟机关机,在宿主机中搜索PowerShell,并使用管理员权限打开

在PowerShell中,直接粘贴执行下面的脚本
注意,请按需替换VmName、GpuMatch、Share的值
- VmName:你的虚拟机实例名称
- GpuMatch:你的设备上可能有多个GPU(比如核显+独显),脚本会根据厂商来自动匹配到对应GPU。英伟达为VEN_10DE,AMD为VEN_1002
- Share:要分配给虚拟机的比例,会按比例分配编解码、计算、显存资源
$VmName = "Windows11" # 请替换为你的虚拟机名称
$GpuMatch = "VEN_10DE" # 如果你是AMD显卡,请替换为VEN_1002
$Share = 0.6 # 要分配给虚拟机的比例
$LowMmio = 1GB
$HighMmio = 32GB
# 自动匹配GPU实例
$gpu = Get-VMHostPartitionableGpu | Where-Object { $_.Name -match $GpuMatch } | Select-Object -First 1
if (-not $gpu) { throw "找不到匹配 GPU:$GpuMatch。请检查 Get-VMHostPartitionableGpu 输出里的 Name。" }
# 关闭虚拟机
$vm = Get-VM -Name $VmName
if ($vm.State -ne 'Off') {
Stop-VM -Name $VmName -Force
}
# 清理之前的配置
$adapters = Get-VMGpuPartitionAdapter -VMName $VmName -ErrorAction SilentlyContinue
if ($adapters) {
foreach ($a in $adapters) {
Remove-VMGpuPartitionAdapter -VMName $VmName -AdapterId $a.Id -ErrorAction SilentlyContinue
}
}
Add-VMGpuPartitionAdapter -VMName $VmName -InstancePath $gpu.Name
function Scale([UInt64]$total, [double]$share) {
return [UInt64]([decimal]$total * [decimal]$share)
}
# 根据分配比例自动计算参数
$maxVRAM = Scale $gpu.TotalVRAM $Share
$maxCompute = Scale $gpu.TotalCompute $Share
$maxDecode = Scale $gpu.TotalDecode $Share
$params = @{
VMName = $VmName
MinPartitionVRAM = 0; MaxPartitionVRAM = $maxVRAM; OptimalPartitionVRAM = $maxVRAM
MinPartitionCompute = 0; MaxPartitionCompute = $maxCompute; OptimalPartitionCompute = $maxCompute
MinPartitionDecode = 0; MaxPartitionDecode = $maxDecode; OptimalPartitionDecode = $maxDecode
}
if ($gpu.TotalEncode -ne [UInt64]::MaxValue) {
$maxEncode = Scale $gpu.TotalEncode $Share
$params += @{
MinPartitionEncode = 0; MaxPartitionEncode = $maxEncode; OptimalPartitionEncode = $maxEncode
}
}
Set-VMGpuPartitionAdapter @params -Passthru | Out-Null
Set-VM -VMName $VmName -GuestControlledCacheTypes $true -LowMemoryMappedIoSpace $LowMmio -HighMemoryMappedIoSpace $HighMmio
# 启动虚拟机
Start-VM -Name $VmName
Get-VMGpuPartitionAdapter -VMName $VmName | Format-List InstancePath,Id,MinPartitionVRAM,MaxPartitionVRAM,OptimalPartitionVRAM
Code language: PowerShell (powershell)执行完上一步的脚本后,你的虚拟机会自动启动,并能够在虚拟机的设备管理器中看到显卡

不过,目前显卡依旧是不可用的状态,还需要从宿主机中拷贝当前的驱动
拷贝驱动
首先,我们要找到宿主机上的显卡驱动位置,还是在刚刚的PowerShell(管理员权限)中,执行下面的脚本
GpuMatch需要和前面保持一致
$GpuMatch = "VEN_10DE" # AMD: VEN_1002
$devIds = @()
try {
$devIds = Get-PnpDevice -Class Display -PresentOnly |
Where-Object { $_.InstanceId -match $GpuMatch } |
Select-Object -ExpandProperty InstanceId
} catch { }
if (-not $devIds) {
$devIds = Get-CimInstance Win32_VideoController |
Where-Object { $_.PNPDeviceID -match $GpuMatch } |
Select-Object -ExpandProperty PNPDeviceID
}
if (-not $devIds) { throw "找不到匹配 GPU:$GpuMatch(系统未识别到对应显示设备)。" }
$drivers = Get-CimInstance Win32_PnPSignedDriver |
Where-Object { $devIds -contains $_.DeviceID } |
Select-Object DeviceID, InfName, DriverName
$infNames = $drivers | Where-Object { $_.InfName } | Select-Object -ExpandProperty InfName -Unique
$sysDirs = $drivers | Where-Object { $_.DriverName } | ForEach-Object { Split-Path $_.DriverName -Parent } | Sort-Object -Unique
$dism = Join-Path $env:WINDIR "System32\dism.exe"
if (-not (Test-Path $dism)) { throw "找不到 dism.exe:$dism" }
$out = & $dism /online /get-drivers 2>$null
if (-not $out) { throw "dism /online /get-drivers 没有输出(可能权限/环境受限)。" }
$text = $out -join "`n"
$repoRoot = Join-Path $env:WINDIR "System32\DriverStore\FileRepository"
$repoDirs = @()
foreach ($pub in $infNames) {
$pubEsc = [regex]::Escape($pub)
$m = [regex]::Match(
$text,
"(?ims)^\s*(Published Name|已发布名称|已发布的名称)\s*[::]\s*$pubEsc\s*$.*?^\s*(Original File Name|原始文件名|原始文件名称)\s*[::]\s*(?<orig>.+?)\s*$"
)
if (-not $m.Success) { continue }
$orig = $m.Groups['orig'].Value.Trim()
if (-not $orig) { continue }
$repoDirs += Get-ChildItem -LiteralPath $repoRoot -Directory -Filter "$orig`_*" -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty FullName
}
@($repoDirs + $sysDirs) | Sort-Object -Unique
Code language: PowerShell (powershell)在我的设备上,执行列出了两个英伟达的驱动目录

进入C:\Windows\System32\DriverStore\FileRepository,并找到这两个驱动目录

右键复制他们,然后进入到虚拟机中,先粘贴到桌面上(需要开启增强会话,才可以直接在虚拟机中粘贴)
然后进入到虚拟机的C:\WINDOWS\System32\目录,新建一个HostDriverStore目录,进入,再新建一个FileRepository目录

将刚刚粘贴到虚拟机中的两个驱动目录,直接粘贴到当前目录(C:\WINDOWS\System32\HostDriverStore\FileRepository)中
最后,再次重启虚拟机,然后在资源管理器和设备管理器中,就能够看到你的显卡了
特别注意:如果宿主机的显卡驱动更新了,那么你需要同步更新虚拟机的显卡驱动,按相同步骤再来一遍即可

串流软件安装
Hyper-V自带的基于RDP的远程连接基本是不可用的状态,为了获得更好的体验,我们可以自行安装串流软件
UU远程
比较适合小白用户,在虚拟机中,直接前往UU远程官网(https://uuyc.163.com/),下载并安装Windows版即可
整个过程一路绿灯,最后登录自己的账号就可以使用了,需要注意的是,直接连接后,默认使用的是Hyper-V的虚拟显示器,分辨率和刷新率都很低

点击连接界面上方默认显示屏右侧的+按钮,创建一个虚拟显示器

然后在UU远程右上角的控制中心-虚拟屏1-其他分辨率,自定义分辨率;在控制中心-画质,自定义刷新率
Sunshine + Moonlight
前往Sunshine的Release页面,https://github.com/LizardByte/Sunshine/releases/latest,拉到下方,下载Windows版安装包
发布的包有很多,下载名为Sunshine-Windows-AMD64-installer.exe的即可

安装依旧一路绿灯,安装完成后,搜索Sunshine并打开,进入配置页面

默认会提示证书不安全,忽略即可,之后配置你的用户名和密码,点击Login

随后会弹出Basic Auth页面,输入你刚刚的用户名和密码,进入后点击PIN页面,先保持在此页面不动

然后在宿主机(不是虚拟机)安装Moonlight客户端,进入Release页面https://github.com/moonlight-stream/moonlight-qt/releases/latest,下载.exe后缀的安装包,安装并启动
因为我的宿主机也安装了Sunshine,所以这里有两个(以设备名而不是虚拟机名称展示)

我们选择虚拟机对应的设备进行配对,会弹出配对PIN码

在Sunshine的PIN配对界面,输入这个PIN码,以及你期望的客户端设备名,点击Send即可配对成功

配对成功后,刚刚设备上的小锁不见了,意味着我们可以发起连接

为了演示方便,我们直接选择Desktop进行连接。使用Sunshine时,可能登录时会被卡退,这是正常的,重新连接即可

注意,虽然能成功连接,但是和UU远程一样,默认只有Hyper-V的虚拟显示器,我们还需要创建分辨率和刷新率更高的虚拟显示器,来提升我们的体验
配置虚拟显示器
我们下载Parsec-VDD来创建虚拟显示器,进入Release页面,https://github.com/nomi-san/parsec-vdd/releases/latest,下载setup.exe,并在虚拟机中安装
同样的一路绿灯,安装完毕后重启虚拟机,重启后,使用Moonlight连接到虚拟机,可以看到ParsecVDisplay已经开机自启了
点击ADD DISPLAY添加一个虚拟显示器

你可以单击虚拟显示器,在弹出的菜单上修改分辨率和刷新率

在托盘图标上右键,打开Fallback display,这会在没有可用显示器时,自动添加显示器

同时,记得在Moonlight中,修改客户端的分辨率和刷新率

禁用Hyper-V虚拟显示器
对于部分串流软件,默认可能会走到Hyper-V虚拟显示器,这会导致帧率异常,又或者分辨率过低,最好的办法是直接禁用
搜索并打开虚拟机中的设备管理器,展开监视器和显示适配器两个子项,可以看到有Generic Monitor (HyperVMonitor)和Microsoft Hyper-V 视频两个设备,分别右击它们,均选择禁用设备

由于前面我们开启了ParsecVDD的Fallback display,所以虚拟机重启后,它会自动创建虚拟显示器
配置虚拟声卡
虚拟机没有声音输出,我们通过安装VBCABLE来解决,进入官网下载Windows版https://vb-audio.com/Cable/,解压并运行VBCABLE_Setup_x64.exe,点击Install Driver来安装驱动

重启虚拟机,即可正常使用虚拟声卡

一切都完成后,开始享受吧~
