Skip to content

Instantly share code, notes, and snippets.

@nenkoru
Created May 22, 2024 08:49
Show Gist options
  • Save nenkoru/acadf3039c94525f3bc3a7329cfdfcd1 to your computer and use it in GitHub Desktop.
Save nenkoru/acadf3039c94525f3bc3a7329cfdfcd1 to your computer and use it in GitHub Desktop.
function Assign-VMGPUPartitionAdapter {
param(
[string]$VMName,
[string]$GPUName,
[decimal]$GPUResourceAllocationPercentage = 100
)
#Remove-VMGpuPartitionAdapter -VMName $VMName
Set-VM -Name $VMName -CheckpointType Disabled -LowMemoryMappedIoSpace 3GB -HighMemoryMappedIoSpace 32GB -GuestControlledCacheTypes $true -AutomaticStopAction ShutDown
$PartitionableGPUList = Get-WmiObject -Class "Msvm_PartitionableGpu" -ComputerName $env:COMPUTERNAME -Namespace "ROOT\virtualization\v2"
if ($GPUName -eq "AUTO") {
$DevicePathName = $PartitionableGPUList.Name[0]
Add-VMGpuPartitionAdapter -VMName $VMName
}
else {
$DeviceID = ((Get-WmiObject Win32_PNPSignedDriver | where {($_.Devicename -eq "$GPUNAME")}).hardwareid).split('\')[1]
$DevicePathName = ($PartitionableGPUList | Where-Object name -like "*$deviceid*").Name
Add-VMGpuPartitionAdapter -VMName $VMName -InstancePath $DevicePathName
}
[float]$devider = [math]::round($(100 / $GPUResourceAllocationPercentage),2)
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionVRAM ([math]::round($(1000000000 / $devider))) -MaxPartitionVRAM ([math]::round($(1000000000 / $devider))) -OptimalPartitionVRAM ([math]::round($(1000000000 / $devider)))
Set-VMGPUPartitionAdapter -VMName $VMName -MinPartitionEncode ([math]::round($(18446744073709551615 / $devider))) -MaxPartitionEncode ([math]::round($(18446744073709551615 / $devider))) -OptimalPartitionEncode ([math]::round($(18446744073709551615 / $devider)))
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionDecode ([math]::round($(1000000000 / $devider))) -MaxPartitionDecode ([math]::round($(1000000000 / $devider))) -OptimalPartitionDecode ([math]::round($(1000000000 / $devider)))
Set-VMGpuPartitionAdapter -VMName $VMName -MinPartitionCompute ([math]::round($(1000000000 / $devider))) -MaxPartitionCompute ([math]::round($(1000000000 / $devider))) -OptimalPartitionCompute ([math]::round($(1000000000 / $devider)))
}
Assign-VMGPUPartitionAdapter -GPUName "AUTO" -VMName "GPU-base+gpu" -GPUResourceAllocationPercentage 10
Function Add-VMGpuPartitionAdapterFiles {
param(
[string]$hostname = $ENV:COMPUTERNAME,
[string]$DriveLetter,
[string]$GPUName
)
If (!($DriveLetter -like "*:*")) {
$DriveLetter = $Driveletter + ":"
}
If ($GPUName -eq "AUTO") {
$PartitionableGPUList = Get-WmiObject -Class "Msvm_PartitionableGpu" -ComputerName $env:COMPUTERNAME -Namespace "ROOT\virtualization\v2"
$DevicePathName = $PartitionableGPUList.Name | Select-Object -First 1
$GPU = Get-PnpDevice | Where-Object {($_.DeviceID -like "*$($DevicePathName.Substring(8,16))*") -and ($_.Status -eq "OK")} | Select-Object -First 1
$GPUName = $GPU.Friendlyname
$GPUServiceName = $GPU.Service
}
Else {
$GPU = Get-PnpDevice | Where-Object {($_.Name -eq "$GPUName") -and ($_.Status -eq "OK")} | Select-Object -First 1
$GPUServiceName = $GPU.Service
}
# Get Third Party drivers used, that are not provided by Microsoft and presumably included in the OS
Write-Host "INFO : Finding and copying driver files for $GPUName to VM. This could take a while..."
$Drivers = Get-WmiObject Win32_PNPSignedDriver | where {$_.DeviceName -eq "$GPUName"}
New-Item -ItemType Directory -Path "$DriveLetter\windows\system32\HostDriverStore" -Force | Out-Null
#copy directory associated with sys file
$servicePath = (Get-WmiObject Win32_SystemDriver | Where-Object {$_.Name -eq "$GPUServiceName"}).Pathname
$ServiceDriverDir = $servicepath.split('\')[0..5] -join('\')
$ServicedriverDest = ("$driveletter" + "\" + $($servicepath.split('\')[1..5] -join('\'))).Replace("DriverStore","HostDriverStore")
if (!(Test-Path $ServicedriverDest)) {
Copy-item -path "$ServiceDriverDir" -Destination "$ServicedriverDest" -Recurse
}
# Initialize the list of detected driver packages as an array
$DriverFolders = @()
foreach ($d in $drivers) {
$DriverFiles = @()
$ModifiedDeviceID = $d.DeviceID -replace "\\", "\\"
$Antecedent = "\\" + $hostname + "\ROOT\cimv2:Win32_PNPSignedDriver.DeviceID=""$ModifiedDeviceID"""
$DriverFiles += Get-WmiObject Win32_PNPSignedDriverCIMDataFile | where {$_.Antecedent -eq $Antecedent}
$DriverName = $d.DeviceName
$DriverID = $d.DeviceID
if ($DriverName -like "NVIDIA*") {
New-Item -ItemType Directory -Path "$driveletter\Windows\System32\drivers\Nvidia Corporation\" -Force | Out-Null
}
foreach ($i in $DriverFiles) {
$path = $i.Dependent.Split("=")[1] -replace '\\\\', '\'
$path2 = $path.Substring(1,$path.Length-2)
$InfItem = Get-Item -Path $path2
$Version = $InfItem.VersionInfo.FileVersion
If ($path2 -like "c:\windows\system32\driverstore\*") {
$DriverDir = $path2.split('\')[0..5] -join('\')
$driverDest = ("$driveletter" + "\" + $($path2.split('\')[1..5] -join('\'))).Replace("driverstore","HostDriverStore")
if (!(Test-Path $driverDest)) {
Copy-item -path "$DriverDir" -Destination "$driverDest" -Recurse
}
}
Else {
$ParseDestination = $path2.Replace("c:", "$driveletter")
$Destination = $ParseDestination.Substring(0, $ParseDestination.LastIndexOf('\'))
if (!$(Test-Path -Path $Destination)) {
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
}
Copy-Item $path2 -Destination $Destination -Force
}
}
}
}
<#
If you are opening this file in Powershell ISE you should modify the params section like so...
Remember: GPU Name must match the name of the GPU you assigned when creating the VM...
#>
Param (
[string]$VMName = "GPUP-base+gpu",
[string]$GPUName = "AUTO",
[string]$Hostname = $ENV:Computername
)
<#
Param (
[string]$VMName,
[string]$GPUName,
[string]$Hostname = $ENV:Computername
)
#>
Import-Module $PSSCriptRoot\Add-VMGpuPartitionAdapterFiles.psm1
$VM = Get-VM -VMName $VMName
$VHD = Get-VHD -VMId $VM.VMId
If ($VM.state -eq "Running") {
[bool]$state_was_running = $true
}
if ($VM.state -ne "Off"){
"Attemping to shutdown VM..."
Stop-VM -Name $VMName -Force
}
While ($VM.State -ne "Off") {
Start-Sleep -s 3
"Waiting for VM to shutdown - make sure there are no unsaved documents..."
}
"Mounting Drive..."
$DriveLetter = (Mount-VHD -Path $VHD.Path -PassThru | Get-Disk | Get-Partition | Get-Volume | Where-Object {$_.DriveLetter} | ForEach-Object DriveLetter)
"Copying GPU Files - this could take a while..."
Add-VMGPUPartitionAdapterFiles -hostname $Hostname -DriveLetter $DriveLetter -GPUName $GPUName
"Dismounting Drive..."
Dismount-VHD -Path $VHD.Path
If ($state_was_running){
"Previous State was running so starting VM..."
Start-VM $VMName
}
"Done..."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment