Last active
November 4, 2025 20:46
-
-
Save neggles/e35793da476095beac716c16ffba1d23 to your computer and use it in GitHub Desktop.
Revisions
-
neggles revised this gist
Jul 5, 2022 . 1 changed file with 5 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -178,9 +178,12 @@ process { Write-Verbose -Message ('Device SystemDriver:') ($SystemDriver | Format-Table -AutoSize | Out-String).Trim().Split("`n") | ForEach-Object -Process { Write-Verbose -Message (' {0}' -f $_) } Write-Verbose -Message ('SystemDriver main/anchor file: {0}' -f $SystemDriver.PathName) $DriverStoreFolder = Get-Item -Path (Split-Path -Path $SystemDriver.PathName -Parent) while ((Get-Item (Split-Path $DriverStoreFolder)).Name -notlike 'FileRepository') { $DriverStoreFolder = Get-Item -Path (Split-Path -Path $DriverStoreFolder -Parent) } Write-Verbose -Message ('Device DriverStoreFolder: {0}' -f $DriverStoreFolder.FullName) Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) $TempDriverStore = ('{0}/System32/HostDriverStore/FileRepository/{1}' -f $fTempFolder, $DriverStoreFolder.Name) -
neggles revised this gist
Jun 28, 2022 . 1 changed file with 181 additions and 164 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -20,184 +20,201 @@ .FUNCTIONALITY Creates a guest driver package. #> [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, DefaultParameterSetName = 'NoPathProvided', HelpUri = 'http://www.microsoft.com/', ConfirmImpact = 'Low')] [Alias()] [OutputType([String])] Param ( # Path to output directory. # If no file name is specified the filename will be GPUPDriverPackage-YYYYMMMDD.zip [Parameter( Mandatory = $false, ParameterSetName = 'PathProvided', HelpMessage = "Path to one or more locations.")] [Alias("PSPath", "Path")] [ValidateNotNullOrEmpty()] [string] $DestinationPath, # Device friendly name filter. # Only devices whose friendly names contain the supplied string will be processed [Parameter( Mandatory = $false, HelpMessage = "Only add drivers for devices whose friendly names contain the supplied string.")] [ValidateNotNullOrEmpty] [String] $Filter ) process { try { # make me a temporary folder, and assemble the structure $fTempFolder = Join-Path -Path $Env:TEMP -ChildPath "GPUPDriverPackage" (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Set default archive name $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) # Check if DestinationPath has been provided if ($PSCmdlet.ParameterSetName -eq "PathProvided") { switch ($DestinationPath) { { (Split-Path -Path $_ -Leaf) -match '(\.zip)' } { # Path we've been provided is a full file path, so we'll just use it $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break } { Test-Path -Path $_ -PathType Container } { # Path exists and is a directory, so we place our file in it with the default name. $ArchiveFolder = $DestinationPath break } Default { # Path doesn't end in .zip and doesn't exist, so we're going to assume it's a directory and place the file in it with the default name. $ArchiveFolder = $DestinationPath (New-Item -ItemType Directory -Path $ArchiveFolder -Force -ErrorAction SilentlyContinue | Out-Null) break } } } else { # if DestinationPath not supplied, use current directory and default name $ArchiveFolder = (Get-Location).Path } # just double check that one if (-not $ArchiveFolder) { $ArchiveFolder = (Get-Location).Path } Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) <# Determine which cmdlet we should use to gather the list of GPU-P capable GPUs. On Windows builds before Server 2022/21H2, the cmdlet is 'Get-VMPartitionableGpu' On later builds, it's 'Get-VMHostPartitionableGpu', and the old cmdlet just prints an error. So, we check if Get-VMHostPartitionableGpu is a valid cmdlet to determine whether we should use it. #> Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." if (Get-Command -Name 'Get-VMHostPartitionableGpu' -ErrorAction SilentlyContinue) { Write-Verbose -Message 'Using new Get-VMHostPartitionableGpu cmdlet' $PVCapableGPUs = Get-VMHostPartitionableGpu } else { Write-Verbose -Message 'Using old Get-VMPartitionableGpu cmdlet' $PVCapableGPUs = Get-VMPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception if ($PVCapableGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects...') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this dirty regex trick, but it works. Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # OK, now that we have some actual device names, we can filter them if we've been asked to if ($null -ne $Filter) { Write-Output -InputObject ('Applying filter "{0}" to device list...' -f $Filter) $TargetGPUs = $TargetGPUs | Where-Object { $_.FriendlyName -like ('*{0}*' -f $Filter) } } Write-Output -InputObject ('Will create driver package for {0} GPUs:' -f $TargetGPUs.Count) $TargetGPUs.FriendlyName | ForEach-Object { Write-Output -InputObject (' - {0}' -f $_) } } catch { throw $PSItem } # Last chance to turn back, traveler. Are you sure? if ($pscmdlet.ShouldProcess("Driver Package", "Create")) { try { Write-Output -InputObject ('The next few steps may take some time, depending on how many devices & driver packages are installed.') Write-Output -InputObject ('If the script appears hung, please give it a few minutes to complete before terminating.') # Get display class devices Write-Output -InputObject ('Gathering display device CIM objects...') $PnPEntities = Get-CimInstance -ClassName 'Win32_PnPEntity' | Where-Object { $_.Class -like 'Display' } Write-Verbose -Message ('Found {0} display devices' -f $PnPEntities.Count) ($PnPEntities | Format-Table -AutoSize | Out-String).Trim().Split("`n") | ForEach-Object -Process { Write-Verbose -Message (' {0}' -f $_) } # Get display class drivers Write-Output -InputObject ('Gathering display device driver CIM objects...') $PnPSignedDrivers = Get-CimInstance -ClassName 'Win32_PnPSignedDriver' -Filter "DeviceClass = 'DISPLAY'" Write-Verbose -Message ('Found {0} display device drivers' -f $PnPSignedDrivers.Count) $PnPSignedInfo = ($PnPSignedDrivers | Select-Object -Property DeviceName,DriverProviderName,InfName,DriverVersion,Description | Format-Table -AutoSize | Out-String).Trim().Split("`n") $PnPSignedInfo | ForEach-Object -Process { Write-Verbose -Message (' {0}' -f $_) } # next we have to get every PnPSignedDriverCIMDataFile, because Get-CimAssociatedInstance doesn't wanna play ball Write-Output -InputObject ('Gathering all driver file objects... (this is the slow one. Blame Microsoft.)') # or me not understanding CIM i guess? $SignedDriverFiles = Get-CimInstance -ClassName 'Win32_PNPSignedDriverCIMDataFile' Write-Output -InputObject ('Found {0} files across all system drivers.' -f $SignedDriverFiles.Count) foreach ($GPU in $TargetGPUs) { Write-Output -InputObject ('Getting driver package for {0}' -f $GPU.FriendlyName) $PnPEntity = $PnPEntities | Where-Object { $_.InstanceId -eq $GPU.InstanceId }[0] Write-Verbose -Message ('Device PnP Entity:') ($PnPEntity | Format-Table -AutoSize | Out-String).Trim().Split("`n") | ForEach-Object -Process { Write-Verbose -Message (' {0}' -f $_) } $PnPSignedDriver = $PnPSignedDrivers | Where-Object { $_.DeviceId -eq $GPU.InstanceId } Write-Verbose -Message ('Device PnPSignedDriver:') ($PnPSignedDriver | Format-Table -AutoSize | Out-String).Trim().Split("`n") | ForEach-Object -Process { Write-Verbose -Message (' {0}' -f $_) } $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity Write-Verbose -Message ('Device SystemDriver:') ($SystemDriver | Format-Table -AutoSize | Out-String).Trim().Split("`n") | ForEach-Object -Process { Write-Verbose -Message (' {0}' -f $_) } $DriverStoreFolder = Get-Item -Path (Split-Path -Path $SystemDriver.PathName -Parent) Write-Verbose -Message ('Device DriverStoreFolder:') Write-Verbose -Message (' - Driver store folder: {0}' -f $DriverStoreFolder.FullName) Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) $TempDriverStore = ('{0}/System32/HostDriverStore/FileRepository/{1}' -f $fTempFolder, $DriverStoreFolder.Name) $DriverStoreFolder | Copy-Item -Destination $TempDriverStore -Recurse -Force Write-Output -InputObject ('Copied {0} of {1} files to temporary directory' -f (Get-ChildItem -Path $TempDriverStore -Recurse).Count, (Get-ChildItem -Path $DriverStoreFolder -Recurse).Count) # Get driver files from system32 etc and copy Write-Output -InputObject ('Gathering files from System32 and SysWOW64') $DriverFiles = ($SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }).Dependent.Name | Sort-Object $NonDriverStoreFiles = $DriverFiles.Where{$_ -notlike '*DriverStore*'} Write-Output -InputObject ('Found {0} files, copying to temporary directory...' -f $NonDriverStoreFiles.Count) $NonDriverStoreFiles | ForEach-Object -Process { $TargetPath = Join-Path -Path $fTempFolder -ChildPath $_.ToLower().Replace(('{0}\' -f $Env:SYSTEMROOT.ToLower()),'') # make sure the parent folder exists (New-Item -ItemType directory -Path (Split-Path -Path $TargetPath -Parent) -Force -ErrorAction SilentlyContinue | Out-Null) Write-Output -InputObject (' - {0} -> {1}' -f $_, $TargetPath) Copy-Item -Path $_ -Destination $TargetPath -Force -Recurse } Write-Output -InputObject ('Finished gathering files for {0}' -f $GPU.FriendlyName) } Write-Output -InputObject ('All driver files have been collected, creating archive file') $Location = (Get-Location).Path Set-Location -Path (Split-Path -Path $fTempFolder -Parent) Compress-Archive -Path $fTempFolder -DestinationPath (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName) -CompressionLevel Fastest -Confirm:$false Set-Location -Path $Location Write-Output -InputObject ('GPU driver package has been created at path {0}\{1}' -f $ArchiveFolder, $ArchiveName) } catch { throw $PSItem } finally { Write-Output -InputObject ('Cleaning up temporary directory {0}' -f $fTempFolder) Remove-Item -Recurse -Force -Path $fTempFolder } } Write-Output -InputObject ('Driver package generation complete.') Write-Output -InputObject ('Please copy it to your guest and extract the archive into C:\Windows\') } -
neggles revised this gist
Dec 31, 2021 . 1 changed file with 24 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,20 +1,30 @@ $Config = @{ VMName = 'GPU-VM' # Edit this to match your existing VM. If you don't have a VM with this name, it will be created. VMMemory = 8192MB # Set appropriately VMCores = 4 # likewise MinRsrc = 80000000 # We don't really know what these values do - my GPU reports 100,000,000 available units... MaxRsrc = 100000000 # I suspect in the current implementation they do nothing, but this is known to work - play around if you like! OptimalRsrc = 100000000 } ### actual execution try { # Get VM host capabilities $VMHost = Get-VMHost # Get highest VM config version available $VMVersion = $VMHost.SupportedVmVersions[$VMHost.SupportedVmVersions.Count - 1] # Get existing VM if it exists $VMObject = (Get-VM -Name $Config.VMName -ErrorAction SilentlyContinue) # Create VM if it doesn't already exist if (-not $VMObject) { $NewVM = @{ Name = $Config.VMName MemoryStartupBytes = $Config.VMMemory Generation = 2 Version = $VMVersion } New-VM @NewVM } @@ -48,12 +58,19 @@ try { MaxPartitionCompute = $Config.MaxRsrc OptimalPartitionCompute = $Config.OptimalRsrc } # Get adapter if it exists $VMAdapter = (Get-VMGpuPartitionAdapter -VMName $Config.VMName -ErrorAction SilentlyContinue) # Add adapter if not present, update if present if ($VMAdapter) { Set-VMGpuPartitionAdapter @GPUParams } else { Add-VMGpuPartitionAdapter @GPUParams } } catch { Write-Error "Something went wrong with creation. Error details below:" Write-Error $PSItem.ErrorDetails throw $PSItem } -
neggles revised this gist
Sep 25, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -85,7 +85,7 @@ } } else { # if DestinationPath not supplied, use current directory and default name $ArchiveFolder = (Get-Location).Path } # just double check that one -
neggles revised this gist
Sep 5, 2021 . 1 changed file with 31 additions and 22 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,17 +22,20 @@ #> # commented out so this functions as a script instead of a function #function New-GPUPDriverPackage { [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, DefaultParameterSetName = 'NoPathProvided', HelpUri = 'http://www.microsoft.com/', ConfirmImpact = 'Low')] [Alias()] [OutputType([String])] Param ( # Path to output directory. # If no file name is specified the filename will be GPUPDriverPackage-YYYYMMMDD.zip [Parameter( Mandatory = $false, ParameterSetName = 'PathProvided', HelpMessage = "Path to one or more locations.")] [Alias("PSPath", "Path")] [ValidateNotNullOrEmpty()] @@ -41,7 +44,8 @@ # Device friendly name filter. # Only devices whose friendly names contain the supplied string will be processed [Parameter( Mandatory = $false, HelpMessage = "Only add drivers for devices whose friendly names contain the supplied string.")] [ValidateNotNullOrEmpty] [String] @@ -55,27 +59,32 @@ (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Set default archive name $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) # Check if DestinationPath has been provided if ($PSCmdlet.ParameterSetName -eq "PathProvided") { switch ($DestinationPath) { { (Split-Path -Path $_ -Leaf) -match '(\.zip)' } { # Path we've been provided is a full file path, so we'll just use it $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break } { Test-Path -Path $_ -PathType Container } { # Path exists and is a directory, so we place our file in it with the default name. $ArchiveFolder = $DestinationPath break } Default { # Path doesn't end in .zip and doesn't exist, so we're going to assume it's a directory and place the file in it with the default name. $ArchiveFolder = $DestinationPath (New-Item -ItemType Directory -Path $ArchiveFolder -Force -ErrorAction SilentlyContinue | Out-Null) break } } } else { # if DestinationPath not supplied, use current directory and default name Default { $ArchiveFolder = (Get-Location).Path } } -
neggles revised this gist
Sep 5, 2021 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -20,7 +20,8 @@ .FUNCTIONALITY Creates a guest driver package. #> # commented out so this functions as a script instead of a function #function New-GPUPDriverPackage { [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, @@ -190,4 +191,4 @@ function New-GPUPDriverPackage { Write-Output -InputObject ('Driver package generation complete.') Write-Output -InputObject ('Please copy it to your guest and extract the archive into C:\Windows\') } #} # see top -
neggles revised this gist
Sep 5, 2021 . 1 changed file with 128 additions and 114 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -48,132 +48,146 @@ function New-GPUPDriverPackage { ) process { try { # make me a temporary folder, and assemble the structure $fTempFolder = Join-Path -Path $Env:TEMP -ChildPath "GPUPDriverPackage" (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Do some processing on the DestinationPath $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) switch ($DestinationPath) { # if path is a folder that exists, use the default name and just put it there { Test-Path -Path $_ -PathType Container -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath break } # if path is a folder that does NOT exist, create it and put archive in it { Test-Path -Path $_ -PathType Container -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath (New-Item -ItemType Directory -Path $ArchiveFolder -Force -ErrorAction SilentlyContinue | Out-Null) break } # if path is a valid path with a file name ending in .zip, use that { Test-Path -Path $_ -PathType Leaf -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break } # if param not supplied, use current directory and default name Default { $ArchiveFolder = (Get-Location).Path } } # just double check that one if (-not $ArchiveFolder) { $ArchiveFolder = (Get-Location).Path } Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) <# Determine which cmdlet we should use to gather the list of GPU-P capable GPUs. On Windows builds before Server 2022/21H2, the cmdlet is 'Get-VMPartitionableGpu' On later builds, it's 'Get-VMHostPartitionableGpu', and the old cmdlet just prints an error. So, we check if Get-VMHostPartitionableGpu is a valid cmdlet to determine whether we should use it. #> Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." if (Get-Command -Name 'Get-VMHostPartitionableGpu' -ErrorAction SilentlyContinue) { Write-Verbose -Message 'Using new Get-VMHostPartitionableGpu cmdlet' $PVCapableGPUs = Get-VMHostPartitionableGpu } else { Write-Verbose -Message 'Using old Get-VMPartitionableGpu cmdlet' $PVCapableGPUs = Get-VMPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception if ($PVCapableGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects...') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this dirty regex trick, but it works. Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # OK, now that we have some actual device names, we can filter them if we've been asked to if ($null -ne $Filter) { Write-Output -InputObject ('Applying filter "{0}" to device list...' -f $Filter) $TargetGPUs = $TargetGPUs | Where-Object { $_.FriendlyName -like ('*{0}*' -f $Filter) } } Write-Output -InputObject ('Will create driver package for {0} GPUs:' -f $TargetGPUs.Count) $TargetGPUs.FriendlyName | ForEach-Object { Write-Output -InputObject (' - {0}' -f $_) } } catch { throw $PSItem } # Last chance to turn back, traveler. Are you sure? if ($pscmdlet.ShouldProcess("Driver Package", "Create")) { try { Write-Output -InputObject ('The next few steps may take some time, depending on how many devices & driver packages are installed.') Write-Output -InputObject ('If the script appears hung, please give it a few minutes to complete before terminating.') # Get display class devices Write-Output -InputObject ('Gathering display device CIM objects...') $PnPEntities = Get-CimInstance -ClassName 'Win32_PnPEntity' | Where-Object { $_.Class -like 'Display' } # Get display class drivers Write-Output -InputObject ('Gathering display driver CIM objects...') $PnPSignedDrivers = Get-CimInstance -ClassName 'Win32_PnPSignedDriver' -Filter "DeviceClass = 'DISPLAY'" # next we have to get every PnPSignedDriverCIMDataFile, because Get-CimAssociatedInstance doesn't wanna play ball Write-Output -InputObject ('Gathering all driver file CIM objects... (this is the slow one. Blame Microsoft.)') # or me not understanding CIM i guess? $SignedDriverFiles = Get-CimInstance -ClassName 'Win32_PNPSignedDriverCIMDataFile' # -Verbose Write-Output -InputObject ('CIM objects gathered.') foreach ($GPU in $TargetGPUs) { Write-Output -InputObject ('Getting driver package for {0}' -f $GPU.FriendlyName) $PnPEntity = $PnPEntities | Where-Object { $_.InstanceId -eq $GPU.InstanceId }[0] $PnPSignedDriver = $PnPSignedDrivers | Where-Object { $_.DeviceId -eq $GPU.InstanceId } $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity $DriverStoreFolder = Split-Path -Path $SystemDriver.PathName -Parent Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) Copy-Item -Path $DriverStoreFolder -Destination "$fTempFolder/System32/HostDriverStore/FileRepository/" -Recurse -Force # Get driver files from system32 etc and copy Write-Output -InputObject ('DriverStore folder copied, gathering files from System32 and SysWOW64') $DriverFiles = ($SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }).Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } Write-Output -InputObject ('Found {0} files:' -f ($System32Files.Count + $SysWOW64Files.Count)) $System32Files | ForEach-Object { Write-Output -InputObject (' - System32\{0}' -f (Split-Path -Path $_ -Leaf)) } $SysWOW64Files | ForEach-Object { Write-Output -InputObject (' - SysWOW64\{0}' -f (Split-Path -Path $_ -Leaf)) } Write-Output -InputObject ('Copying to temporary directory...') Copy-Item -Path $System32Files -Destination "$fTempFolder/System32/" Copy-Item -Path $SysWOW64Files -Destination "$fTempFolder/SysWOW64/" Write-Output -InputObject ('Finished gathering files for {0}' -f $GPU.FriendlyName) } Write-Output -InputObject ('All driver files have been collected, creating archive file') $Location = (Get-Location).Path Set-Location -Path (Split-Path -Path $fTempFolder -Parent) Compress-Archive -Path $fTempFolder -DestinationPath (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName) -CompressionLevel Fastest -Confirm:$false Set-Location -Path $Location Write-Output -InputObject ('GPU driver package has been created at path {0}\{1}' -f $ArchiveFolder, $ArchiveName) } catch { throw $PSItem } finally { Write-Output -InputObject ('Cleaning up temporary directory {0}' -f $fTempFolder) Remove-Item -Recurse -Force -Path $fTempFolder } } Write-Output -InputObject ('Driver package generation complete.') Write-Output -InputObject ('Please copy it to your guest and extract the archive into C:\Windows\') } } -
neggles revised this gist
Aug 18, 2021 . 1 changed file with 114 additions and 128 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -48,146 +48,132 @@ function New-GPUPDriverPackage { ) process { # make me a temporary folder, and assemble the structure $fTempFolder = Join-Path -Path $Env:TEMP -ChildPath "GPUPDriverPackage" (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Do some processing on the DestinationPath $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) switch ($DestinationPath) { # if path is a folder that exists, use the default name and just put it there { Test-Path -Path $PSItem -PathType Container -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath break } # if path is a folder that does NOT exist, create it and put archive in it { Test-Path -Path $PSItem -PathType Container -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath (New-Item -ItemType Directory -Path $ArchiveFolder -Force -ErrorAction SilentlyContinue | Out-Null) break } # if path is a valid path with a file name ending in .zip, use that { Test-Path -Path $PSItem -PathType Leaf -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break } # if param not supplied, use current directory and default name Default { $ArchiveFolder = (Get-Location).Path } } # just double check that one if (-not $ArchiveFolder) { $ArchiveFolder = (Get-Location).Path } Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." # requires some care as the command name changed in Server 2022/W10 21H2 try { $PVCapableGPUs = Get-VMPartitionableGpu } catch { $PVCapableGPUs = Get-VMHostPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception if ($PVCapableGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this, no sir Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # OK, now that we have some actual device names, we can filter them if we've been asked to if ($null -ne $Filter) { Write-Output -InputObject ('Applying filter "{0}" to device list...' -f $Filter) $TargetGPUs = $TargetGPUs | Where-Object { $_.FriendlyName -like ('*{0}*' -f $Filter) } } Write-Output -InputObject ('Will create driver package for {0} GPUs:' -f $TargetGPUs.Count) $TargetGPUs.FriendlyName | ForEach-Object { Write-Output -InputObject (' - {0}' -f $_) } # Last chance to turn back, traveler. Are you sure? if ($pscmdlet.ShouldProcess("Driver Package", "Create")) { Write-Output -InputObject ('The next few steps may take some time, depending on how many devices & driver packages are installed.') Write-Output -InputObject ('If the script appears hung, please give it a few minutes to complete before terminating.') # Get display class devices Write-Output -InputObject ('Gathering display device CIM objects...') $PnPEntities = Get-CimInstance -ClassName 'Win32_PnPEntity' | Where-Object { $_.Class -like 'Display' } # Get display class drivers Write-Output -InputObject ('Gathering display driver CIM objects...') $PnPSignedDrivers = Get-CimInstance -ClassName 'Win32_PnPSignedDriver' -Filter "DeviceClass = 'DISPLAY'" # next we have to get every PnPSignedDriverCIMDataFile, because Get-CimAssociatedInstance doesn't wanna play ball Write-Output -InputObject ('Gathering all driver file CIM objects... (this is the slow one. Blame Microsoft.)') # or me not understanding CIM i guess? $SignedDriverFiles = Get-CimInstance -ClassName 'Win32_PNPSignedDriverCIMDataFile' # -Verbose Write-Output -InputObject ('CIM objects gathered.') foreach ($GPU in $TargetGPUs) { Write-Output -InputObject ('Getting driver package for {0}' -f $GPU.FriendlyName) $PnPEntity = $PnPEntities | Where-Object { $_.InstanceId -eq $GPU.InstanceId }[0] $PnPSignedDriver = $PnPSignedDrivers | Where-Object { $_.DeviceId -eq $GPU.InstanceId } $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity $DriverStoreFolder = Split-Path -Path $SystemDriver.PathName -Parent Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) Copy-Item -Path $DriverStoreFolder -Destination "$fTempFolder/System32/HostDriverStore/FileRepository/" -Recurse -Force # Get driver files from system32 etc and copy Write-Output -InputObject ('Done, getting files from System32 and SysWOW64') $DriverFiles = ($SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }).Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } Write-Output -InputObject ('Found {0} files:' -f ($System32Files.Count + $SysWOW64Files.Count)) $System32Files | ForEach-Object { Write-Output -InputObject (' - System32\{0}' -f (Split-Path -Path $_ -Leaf)) } $SysWOW64Files | ForEach-Object { Write-Output -InputObject (' - SysWOW64\{0}' -f (Split-Path -Path $_ -Leaf)) } Write-Output -InputObject ('Copying to temporary directory...') Copy-Item -Path $System32Files -Destination "$fTempFolder/System32/" Copy-Item -Path $SysWOW64Files -Destination "$fTempFolder/SysWOW64/" Write-Output -InputObject ('Finished gathering files for {0}' -f $GPU.FriendlyName) } Write-Output -InputObject ('All driver files have been collected, creating archive file') $Location = (Get-Location).Path Set-Location -Path (Split-Path -Path $fTempFolder -Parent) Compress-Archive -Path $fTempFolder -DestinationPath (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName) -CompressionLevel Fastest -Confirm:$false Set-Location -Path $Location Write-Output -InputObject ('GPU driver package has been created at path {0}\{1}' -f $ArchiveFolder, $ArchiveName) Write-Output -InputObject ('Cleaning up temporary directory {0}' -f $fTempFolder) Remove-Item -Recurse -Force -Path $fTempFolder } Write-Output -InputObject ('Driver package generation complete.') } } -
neggles revised this gist
Jul 9, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -160,7 +160,7 @@ function New-GPUPDriverPackage { # Get driver files from system32 etc and copy Write-Output -InputObject ('DriverStore folder copied, gathering files from System32 and SysWOW64') $DriverFiles = ($SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }).Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } -
neggles revised this gist
Jul 7, 2021 . 1 changed file with 25 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,34 +8,40 @@ I am not in any way responsible for working this out, that credit goes to [Nimoa 1. Create a new VM using `New-GPUPVirtualMachine.ps1` below and install Windows 10 on it. 1. Gather driver files for your guest using one of the two methods below: ## Using the driver gathering script (recommended) Download the `New-GPUPDriverPackage.ps1` script from this gist, it will gather the various files for you - it must be run as admin, make sure you either specify a destination path or run it from the folder you'd like the .zip created in. 1. Run the script on your host, in an admin PowerShell session. It will create `GPUPDriverPackage-[date].zip` in the current directory, or a path specified with `-Destination <path>`. 2. Copy the .zip to your guest VM and extract it. 3. Copy the contents of the extracted `GPUPDriverPackage` folder into `C:\Windows\` on the guest VM 4. Reboot the guest, and enjoy your hardware acceleration! This has been tested on nVidia, AMD, and Intel GPU drivers. (Most Intel iGPUs have support for GPU-P, though I've not tested for Quick Sync Video support in guests yet) ## Gathering driver files manually This only covers nVidia drivers, but the process is very similar for Intel and AMD. 1. On your host system: 1. Browse to ``C:\Windows\system32\DriverStore\FileRepository`` 2. Find the ``nvdispsi.inf_amd64_<guid>`` and/or ``nvltsi.inf_amd64_<guid>`` folders, and copy them to a temporary folder 3. View driver details in device manager on your host, and copy all the files you see listed in `System32` or `SysWOW64` into matching folders inside your temporary folder. 2. On your guest system: 1. Browse to ``C:\Windows\system32\HostDriverStore\FileRepository`` (You will likely need to create the ``HostDriverStore`` and ``FileRepository`` directories) 2. Copy the two driver folders you collected from your host to this path. 3. Copy ``nvapi64.dll`` (and the other to ``C:\Windows\system32\`` on the guest as well 3. Shut down the guest VM, 4. Make sure the VM's checkpoints are disabled, and automatic stop action is set to 'Turn Off' (The VM creation script covers this, but never hurts to be sure) 5. Boot your VM, and enjoy your hardware acceleration! ---- Windows features that must be enabled: * Hyper-V * Windows Subsystem for Linux* * Virtual Machine Platform \* WSL/WSL2 is probably not necessary, but this functionality is present in Windows 10 to allow for CUDA support in WSL2, so it's probably a good idea to turn it on. -
neggles revised this gist
Jul 7, 2021 . 1 changed file with 15 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -84,12 +84,19 @@ function New-GPUPDriverPackage { Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) <# Determine which cmdlet we should use to gather the list of GPU-P capable GPUs. On Windows builds before Server 2022/21H2, the cmdlet is 'Get-VMPartitionableGpu' On later builds, it's 'Get-VMHostPartitionableGpu', and the old cmdlet just prints an error. So, we check if Get-VMHostPartitionableGpu is a valid cmdlet to determine whether we should use it. #> Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." if (Get-Command -Name 'Get-VMHostPartitionableGpu' -ErrorAction SilentlyContinue) { Write-Verbose -Message 'Using new Get-VMHostPartitionableGpu cmdlet' $PVCapableGPUs = Get-VMHostPartitionableGpu } else { Write-Verbose -Message 'Using old Get-VMPartitionableGpu cmdlet' $PVCapableGPUs = Get-VMPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception @@ -110,10 +117,10 @@ function New-GPUPDriverPackage { # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects...') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this dirty regex trick, but it works. Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } @@ -152,7 +159,7 @@ function New-GPUPDriverPackage { Copy-Item -Path $DriverStoreFolder -Destination "$fTempFolder/System32/HostDriverStore/FileRepository/" -Recurse -Force # Get driver files from system32 etc and copy Write-Output -InputObject ('DriverStore folder copied, gathering files from System32 and SysWOW64') $DriverFiles = $SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }.Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } @@ -181,5 +188,6 @@ function New-GPUPDriverPackage { } } Write-Output -InputObject ('Driver package generation complete.') Write-Output -InputObject ('Please copy it to your guest and extract the archive into C:\Windows\') } } -
neggles revised this gist
Jun 27, 2021 . 1 changed file with 118 additions and 112 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -48,131 +48,137 @@ function New-GPUPDriverPackage { ) process { try { # make me a temporary folder, and assemble the structure $fTempFolder = Join-Path -Path $Env:TEMP -ChildPath "GPUPDriverPackage" (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Do some processing on the DestinationPath $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) switch ($DestinationPath) { # if path is a folder that exists, use the default name and just put it there { Test-Path -Path $_ -PathType Container -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath break } # if path is a folder that does NOT exist, create it and put archive in it { Test-Path -Path $_ -PathType Container -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath (New-Item -ItemType Directory -Path $ArchiveFolder -Force -ErrorAction SilentlyContinue | Out-Null) break } # if path is a valid path with a file name ending in .zip, use that { Test-Path -Path $_ -PathType Leaf -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break } # if param not supplied, use current directory and default name Default { $ArchiveFolder = (Get-Location).Path } } # just double check that one if (-not $ArchiveFolder) { $ArchiveFolder = (Get-Location).Path } Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." # requires some care as the command name changed in Server 2022/W10 21H2 try { $PVCapableGPUs = Get-VMPartitionableGpu } catch { $PVCapableGPUs = Get-VMHostPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception if ($PVCapableGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this, no sir Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # OK, now that we have some actual device names, we can filter them if we've been asked to if ($null -ne $Filter) { Write-Output -InputObject ('Applying filter "{0}" to device list...' -f $Filter) $TargetGPUs = $TargetGPUs | Where-Object { $_.FriendlyName -like ('*{0}*' -f $Filter) } } Write-Output -InputObject ('Will create driver package for {0} GPUs:' -f $TargetGPUs.Count) $TargetGPUs.FriendlyName | ForEach-Object { Write-Output -InputObject (' - {0}' -f $_) } } catch { throw $PSItem } # Last chance to turn back, traveler. Are you sure? if ($pscmdlet.ShouldProcess("Driver Package", "Create")) { try { Write-Output -InputObject ('The next few steps may take some time, depending on how many devices & driver packages are installed.') Write-Output -InputObject ('If the script appears hung, please give it a few minutes to complete before terminating.') # Get display class devices Write-Output -InputObject ('Gathering display device CIM objects...') $PnPEntities = Get-CimInstance -ClassName 'Win32_PnPEntity' | Where-Object { $_.Class -like 'Display' } # Get display class drivers Write-Output -InputObject ('Gathering display driver CIM objects...') $PnPSignedDrivers = Get-CimInstance -ClassName 'Win32_PnPSignedDriver' -Filter "DeviceClass = 'DISPLAY'" # next we have to get every PnPSignedDriverCIMDataFile, because Get-CimAssociatedInstance doesn't wanna play ball Write-Output -InputObject ('Gathering all driver file CIM objects... (this is the slow one. Blame Microsoft.)') # or me not understanding CIM i guess? $SignedDriverFiles = Get-CimInstance -ClassName 'Win32_PNPSignedDriverCIMDataFile' # -Verbose Write-Output -InputObject ('CIM objects gathered.') foreach ($GPU in $TargetGPUs) { Write-Output -InputObject ('Getting driver package for {0}' -f $GPU.FriendlyName) $PnPEntity = $PnPEntities | Where-Object { $_.InstanceId -eq $GPU.InstanceId }[0] $PnPSignedDriver = $PnPSignedDrivers | Where-Object { $_.DeviceId -eq $GPU.InstanceId } $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity $DriverStoreFolder = Split-Path -Path $SystemDriver.PathName -Parent Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) Copy-Item -Path $DriverStoreFolder -Destination "$fTempFolder/System32/HostDriverStore/FileRepository/" -Recurse -Force # Get driver files from system32 etc and copy Write-Output -InputObject ('Done, getting files from System32 and SysWOW64') $DriverFiles = $SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }.Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } Write-Output -InputObject ('Found {0} files:' -f ($System32Files.Count + $SysWOW64Files.Count)) $System32Files | ForEach-Object { Write-Output -InputObject (' - System32\{0}' -f (Split-Path -Path $_ -Leaf)) } $SysWOW64Files | ForEach-Object { Write-Output -InputObject (' - SysWOW64\{0}' -f (Split-Path -Path $_ -Leaf)) } Write-Output -InputObject ('Copying to temporary directory...') Copy-Item -Path $System32Files -Destination "$fTempFolder/System32/" Copy-Item -Path $SysWOW64Files -Destination "$fTempFolder/SysWOW64/" Write-Output -InputObject ('Finished gathering files for {0}' -f $GPU.FriendlyName) } Write-Output -InputObject ('All driver files have been collected, creating archive file') $Location = (Get-Location).Path Set-Location -Path (Split-Path -Path $fTempFolder -Parent) Compress-Archive -Path $fTempFolder -DestinationPath (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName) -CompressionLevel Fastest -Confirm:$false Set-Location -Path $Location Write-Output -InputObject ('GPU driver package has been created at path {0}\{1}' -f $ArchiveFolder, $ArchiveName) } catch { throw $PSItem } finally { Write-Output -InputObject ('Cleaning up temporary directory {0}' -f $fTempFolder) Remove-Item -Recurse -Force -Path $fTempFolder } } Write-Output -InputObject ('Driver package generation complete.') } -
neggles revised this gist
Jun 26, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -150,7 +150,7 @@ function New-GPUPDriverPackage { # Get driver files from system32 etc and copy Write-Output -InputObject ('Done, getting files from System32 and SysWOW64') $DriverFiles = ($SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }).Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } -
neggles revised this gist
Jun 26, 2021 . 1 changed file with 7 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -57,17 +57,18 @@ function New-GPUPDriverPackage { $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) switch ($DestinationPath) { # if path is a folder that exists, use the default name and just put it there { Test-Path -Path $PSItem -PathType Container -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath break } # if path is a folder that does NOT exist, create it and put archive in it { Test-Path -Path $PSItem -PathType Container -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = $DestinationPath (New-Item -ItemType Directory -Path $ArchiveFolder -Force -ErrorAction SilentlyContinue | Out-Null) break } # if path is a valid path with a file name ending in .zip, use that { Test-Path -Path $PSItem -PathType Leaf -IsValid -ErrorAction SilentlyContinue } { $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break @@ -76,9 +77,8 @@ function New-GPUPDriverPackage { Default { $ArchiveFolder = (Get-Location).Path } } # just double check that one if (-not $ArchiveFolder) { $ArchiveFolder = (Get-Location).Path } Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) -
neggles revised this gist
Jun 26, 2021 . 3 changed files with 180 additions and 162 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,161 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,179 @@ <# .SYNOPSIS Create a GPU-P Guest driver package. .DESCRIPTION Gathers the necessary files for a GPU-P enabled Windows guest to run. .EXAMPLE New-GPUPDriverPackage -DestinationPath '.' .EXAMPLE New-GPUPDriverPackage -Filter 'nvidia' -DestinationPath '.' .INPUTS None. .OUTPUTS A driver package .zip .NOTES This has some mildly dodgy use of CIM cmdlets... .COMPONENT PSHyperTools .ROLE GPUP .FUNCTIONALITY Creates a guest driver package. #> function New-GPUPDriverPackage { [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, HelpUri = 'http://www.microsoft.com/', ConfirmImpact = 'Low')] [Alias()] [OutputType([String])] Param ( # Path to output directory. # If no file name is specified the filename will be GPUPDriverPackage-YYYYMMMDD.zip [Parameter(Mandatory = $false, HelpMessage = "Path to one or more locations.")] [Alias("PSPath", "Path")] [ValidateNotNullOrEmpty()] [string] $DestinationPath, # Device friendly name filter. # Only devices whose friendly names contain the supplied string will be processed [Parameter(Mandatory = $false, HelpMessage = "Only add drivers for devices whose friendly names contain the supplied string.")] [ValidateNotNullOrEmpty] [String] $Filter ) process { # make me a temporary folder, and assemble the structure $fTempFolder = Join-Path -Path $Env:TEMP -ChildPath "GPUPDriverPackage" (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Do some processing on the DestinationPath $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) switch ($DestinationPath) { # if path is a folder that exists, use the default name and just put it there { Test-Path -Path $PSItem -PathType Container } { $ArchiveFolder = $DestinationPath break } # if path is a folder that exists, use the default name and just put it there { Test-Path -Path $PSItem -PathType Container } { $ArchiveFolder = $DestinationPath break } # if path is a valid path with a file name ending in .zip, use that { Test-Path -Path $PSItem -PathType Leaf -IsValid } { $ArchiveFolder = Split-Path -Path $DestinationPath -Parent $ArchiveName = Split-Path -Path $DestinationPath -Leaf break } # if param not supplied, use current directory and default name Default { $ArchiveFolder = (Get-Location).Path } } if (-not $ArchiveFolder) { $ArchiveFolder = (Get-Location).Path } Write-Output -InputObject ('Creating GPU-P driver package for host {0}' -f $Env:COMPUTERNAME) Write-Output -InputObject ('Destination path: {0}' -f (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName)) Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." # requires some care as the command name changed in Server 2022/W10 21H2 try { $PVCapableGPUs = Get-VMPartitionableGpu } catch { $PVCapableGPUs = Get-VMHostPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception if ($PVCapableGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this, no sir Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # OK, now that we have some actual device names, we can filter them if we've been asked to if ($null -ne $Filter) { Write-Output -InputObject ('Applying filter "{0}" to device list...' -f $Filter) $TargetGPUs = $TargetGPUs | Where-Object { $_.FriendlyName -like ('*{0}*' -f $Filter) } } Write-Output -InputObject ('Will create driver package for {0} GPUs:' -f $TargetGPUs.Count) $TargetGPUs.FriendlyName | ForEach-Object { Write-Output -InputObject (' - {0}' -f $_) } # Last chance to turn back, traveler. Are you sure? if ($pscmdlet.ShouldProcess("Driver Package", "Create")) { Write-Output -InputObject ('The next few steps may take some time, depending on how many devices & driver packages are installed.') Write-Output -InputObject ('If the script appears hung, please give it a few minutes to complete before terminating.') # Get display class devices Write-Output -InputObject ('Gathering display device CIM objects...') $PnPEntities = Get-CimInstance -ClassName 'Win32_PnPEntity' | Where-Object { $_.Class -like 'Display' } # Get display class drivers Write-Output -InputObject ('Gathering display driver CIM objects...') $PnPSignedDrivers = Get-CimInstance -ClassName 'Win32_PnPSignedDriver' -Filter "DeviceClass = 'DISPLAY'" # next we have to get every PnPSignedDriverCIMDataFile, because Get-CimAssociatedInstance doesn't wanna play ball Write-Output -InputObject ('Gathering all driver file CIM objects... (this is the slow one. Blame Microsoft.)') # or me not understanding CIM i guess? $SignedDriverFiles = Get-CimInstance -ClassName 'Win32_PNPSignedDriverCIMDataFile' # -Verbose Write-Output -InputObject ('CIM objects gathered.') foreach ($GPU in $TargetGPUs) { Write-Output -InputObject ('Getting driver package for {0}' -f $GPU.FriendlyName) $PnPEntity = $PnPEntities | Where-Object { $_.InstanceId -eq $GPU.InstanceId }[0] $PnPSignedDriver = $PnPSignedDrivers | Where-Object { $_.DeviceId -eq $GPU.InstanceId } $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity $DriverStoreFolder = Split-Path -Path $SystemDriver.PathName -Parent Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) Copy-Item -Path $DriverStoreFolder -Destination "$fTempFolder/System32/HostDriverStore/FileRepository/" -Recurse -Force # Get driver files from system32 etc and copy Write-Output -InputObject ('Done, getting files from System32 and SysWOW64') $DriverFiles = $SignedDriverFiles | Where-Object { $_.Antecedent.DeviceID -like $GPU.DeviceID }.Dependent.Name $System32Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles | Where-Object { (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } Write-Output -InputObject ('Found {0} files:' -f ($System32Files.Count + $SysWOW64Files.Count)) $System32Files | ForEach-Object { Write-Output -InputObject (' - System32\{0}' -f (Split-Path -Path $_ -Leaf)) } $SysWOW64Files | ForEach-Object { Write-Output -InputObject (' - SysWOW64\{0}' -f (Split-Path -Path $_ -Leaf)) } Write-Output -InputObject ('Copying to temporary directory...') Copy-Item -Path $System32Files -Destination "$fTempFolder/System32/" Copy-Item -Path $SysWOW64Files -Destination "$fTempFolder/SysWOW64/" Write-Output -InputObject ('Finished gathering files for {0}' -f $GPU.FriendlyName) } Write-Output -InputObject ('All driver files have been collected, creating archive file') $Location = (Get-Location).Path Set-Location -Path (Split-Path -Path $fTempFolder -Parent) Compress-Archive -Path $fTempFolder -DestinationPath (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName) -CompressionLevel Fastest -Confirm:$false Set-Location -Path $Location Write-Output -InputObject ('GPU driver package has been created at path {0}\{1}' -f $ArchiveFolder, $ArchiveName) Write-Output -InputObject ('Cleaning up temporary directory {0}' -f $fTempFolder) Remove-Item -Recurse -Force -Path $fTempFolder } Write-Output -InputObject ('Driver package generation complete.') } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -25,7 +25,7 @@ I am not in any way responsible for working this out, that credit goes to [Nimoa ## Using the driver gathering script You also have the option to use `New-GPUPDriverPackage.ps1`, which will gather the various files for you. 1. Run the script on your host, in an admin PowerShell session. It will create `GPUPDriverPackage-[date].zip` in the current directory. 2. Copy the .zip to your guest VM and extract -
neggles revised this gist
Jun 24, 2021 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ # Configuring GPU-PV on Hyper-V This works on a Windows Pro 10 version 2004 or newer machine, confirmed to function with nVidia GPUs and recent AMD GPUs. Intel should work as well, but why do you want that? I am not in any way responsible for working this out, that credit goes to [Nimoa at cfx.re](https://forum.cfx.re/t/running-fivem-in-a-hyper-v-vm-with-full-gpu-performance-for-testing-gpu-partitioning/1281205) and [reddit users on r/hyperv](https://www.reddit.com/r/HyperV/comments/huy09l/gpupv_in_hyperv_with_windows_10/) -
neggles revised this gist
Jun 24, 2021 . 2 changed files with 1 addition and 1 deletion.There are no files selected for viewing
File renamed without changes.This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -5,7 +5,7 @@ This works on a Windows 10 version 2004 machine with an nVidia GPU. It should wo I am not in any way responsible for working this out, that credit goes to [Nimoa at cfx.re](https://forum.cfx.re/t/running-fivem-in-a-hyper-v-vm-with-full-gpu-performance-for-testing-gpu-partitioning/1281205) and [reddit users on r/hyperv](https://www.reddit.com/r/HyperV/comments/huy09l/gpupv_in_hyperv_with_windows_10/) 1. Make sure you have Hyper-V enabled (no way!) - there's a list of other features below that you *might* need, enable those if it doesn't work. 1. Create a new VM using `New-GPUPVirtualMachine.ps1` below and install Windows 10 on it. 1. Gather driver files for your guest using one of the two methods below: ## Gathering driver files manually -
neggles revised this gist
Jun 24, 2021 . 3 changed files with 170 additions and 122 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,161 @@ <# .SYNOPSIS Create a GPU-P Guest driver package. .DESCRIPTION Gathers the necessary files for a GPU-P enabled Windows guest to run. .EXAMPLE Compress-GPUPDriverPackage -DestinationPath '.' .EXAMPLE Compress-GPUPDriverPackage -Filter 'nvidia' -DestinationPath '.' .INPUTS None. .OUTPUTS A driver package .zip .NOTES This has some mildly dodgy use of CIM cmdlets... .COMPONENT PSHyperTools .ROLE GPUP .FUNCTIONALITY Creates a guest driver package. #> [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, HelpUri = 'http://www.microsoft.com/', ConfirmImpact = 'Low')] [Alias()] [OutputType([String])] Param ( # Path to output directory. # If no file name is specified the filename will be GPUPDriverPackage-YYYYMMMDD.zip [Parameter(Mandatory = $false, HelpMessage = "Path to one or more locations.")] [Alias("PSPath", "Path")] [ValidateNotNullOrEmpty()] [string] $DestinationPath, # Device friendly name filter. # Only devices whose friendly names contain the supplied string will be processed [Parameter(Mandatory = $false, HelpMessage = "Only add drivers for devices whose friendly names contain the supplied string.")] [ValidateNotNullOrEmpty] [String] $Filter ) begin { # make me a temporary folder, and assemble the structure $fTempFolder = Join-Path -Path $Env:TEMP -ChildPath "GPUPDriverPackage" (New-Item -ItemType Directory -Path "$fTempFolder/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$fTempFolder/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) # Do some processing on the DestinationPath if ($null -eq $DestinationPath) { $ArchiveName = ('GPUPDriverPackage-{0}.zip' -f $(Get-Date -UFormat '+%Y%b%d')) $ArchiveFolder = (Get-Location).Path } elseif ($DestinationPath -like '*.zip') { $ArchiveName = Split-Path -Path $DestinationPath -Leaf $ArchiveFolder = Split-Path -Path $DestinationPath -Parent } Write-Output -InputObject ('Driver package will be created:') Write-Output -InputObject (' Name: {0}' -f $ArchiveName) Write-Output -InputObject (' Path: {0}\{1}' -f $ArchiveFolder, $ArchiveName) } process { Write-Output -InputObject "Getting all GPU-P capable GPUs in the current system..." # requires some care as the command name changed in Server 2022/W10 21H2 try { $PVCapableGPUs = Get-VMPartitionableGpu } catch { $PVCapableGPUs = Get-VMHostPartitionableGpu } # if we found no GPU-P capable GPUs, throw an exception if ($PVCapableGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } # Map each PVCapableGPU to the corresponding PnPDevice. Regex (mostly) extracts the InstanceId from the VMPartitionableGpu 'name' property. Write-Output -InputObject ('Mapping GPU-P capable GPUs to their corresponding PnPDevice objects') $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') $TargetGPUs = $PVCapableGPUs.Name | ForEach-Object -Process { # I'm not proud of this, no sir Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # OK, now that we have some actual device names, we can filter them if we've been asked to if ($null -ne $Filter) { Write-Output -InputObject ('Applying filter "{0}" to device list...' -f $Filter) $TargetGPUs = $TargetGPUs | Where-Object { $_.FriendlyName -like ('*{0}*' -f $Filter) } } Write-Output -InputObject ('Will create driver package for {0} GPUs:' -f $TargetGPUs.Count) $TargetGPUs.FriendlyName | ForEach-Object { Write-Output -InputObject (' - {0}' -f $_) } # Last chance to turn back, traveler. Are you sure? if ($pscmdlet.ShouldProcess("Driver Package", "Create")) { Write-Output -InputObject ('The next few steps may take some time, depending on how many devices & driver packages are installed.') Write-Output -InputObject ('If the script appears hung, please give it a few minutes to complete before terminating.') # Get display class devices Write-Output -InputObject ('Gathering display device CIM objects...') $PnPEntities = Get-CimInstance -ClassName 'Win32_PnPEntity' | Where-Object { $_.Class -like 'Display' } # Get display class drivers Write-Output -InputObject ('Gathering display driver CIM objects...') $PnPSignedDrivers = Get-CimInstance -ClassName 'Win32_PnPSignedDriver' -Filter "DeviceClass = 'DISPLAY'" # next we have to get every PnPSignedDriverCIMDataFile, because Get-CimAssociatedInstance doesn't wanna play ball Write-Output -InputObject ('Gathering all driver file CIM objects... (this is the slow one. Blame Microsoft.)') # or me not understanding CIM i guess? $SignedDriverFiles = Get-CimInstance -ClassName 'Win32_PNPSignedDriverCIMDataFile' # -Verbose Write-Output -InputObject ('CIM objects gathered.') foreach ($GPU in $TargetGPUs) { Write-Output -InputObject ('Getting driver package for {0}' -f $GPU.FriendlyName) $PnPEntity = $PnPEntities.Where{ $_.InstanceId -eq $GPU.InstanceId }[0] $PnPSignedDriver = $PnPSignedDrivers.Where{ $_.DeviceId -eq $GPU.InstanceId } $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity $DriverStoreFolder = Split-Path -Path $SystemDriver.PathName -Parent Write-Output -InputObject ('Found package {0}, copying DriverStore folder {1} to temporary directory' -f $PnPSignedDriver.InfName, (Split-Path $DriverStoreFolder -Leaf)) Copy-Item -Path $DriverStoreFolder -Destination "$fTempFolder/System32/HostDriverStore/FileRepository/" -Recurse -Force # Get driver files from system32 etc and copy Write-Output -InputObject ('Done, getting files from System32 and SysWOW64') $DriverFiles = $SignedDriverFiles.Where{ $_.Antecedent.DeviceID -like $GPU.DeviceID }.Dependent.Name $System32Files = $DriverFiles.Where{ (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\System32" } $SysWOW64Files = $DriverFiles.Where{ (Split-Path -Path $_ -Parent) -like "$Env:SYSTEMROOT\SysWOW64" } Write-Output -InputObject ('Found {0} files:' -f ($System32Files.Count + $SysWOW64Files.Count)) $System32Files | ForEach-Object { Write-Output -InputObject (' - System32\{0}' -f (Split-Path -Path $_ -Leaf)) } $SysWOW64Files | ForEach-Object { Write-Output -InputObject (' - SysWOW64\{0}' -f (Split-Path -Path $_ -Leaf)) } Write-Output -InputObject ('Copying to temporary directory...') Copy-Item -Path $System32Files -Destination "$fTempFolder/System32/" Copy-Item -Path $SysWOW64Files -Destination "$fTempFolder/SysWOW64/" Write-Output -InputObject ('Finished gathering files for {0}' -f $GPU.FriendlyName) } Write-Output -InputObject ('All driver files have been collected, creating archive file') $Location = (Get-Location).Path Set-Location -Path (Split-Path -Path $fTempFolder -Parent) Compress-Archive -Path $fTempFolder -DestinationPath (Join-Path -Path $ArchiveFolder -ChildPath $ArchiveName) -CompressionLevel Fastest -Confirm:$false Set-Location -Path $Location Write-Output -InputObject ('GPU driver package has been created at path {0}\{1}' -f $ArchiveFolder, $ArchiveName) Write-Output -InputObject ('Cleaning up temporary directory {0}' -f $fTempFolder) Remove-Item -Recurse -Force -Path $fTempFolder } Write-Output -InputObject ('Driver package generation complete.') } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,118 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -18,16 +18,21 @@ I am not in any way responsible for working this out, that credit goes to [Nimoa (You will likely need to create the ``HostDriverStore`` and ``FileRepository`` directories) 2. Copy the two driver folders you collected from your host to this path. 3. Copy ``nvapi64.dll`` to ``C:\Windows\system32\`` on the guest as well, and a few others - look at 'driver details' for your GPU in device manager to work out which ones 5. Shut down the guest VM, 6. Make sure the VM's checkpoints are disabled, and automatic stop action is set to 'Turn Off' (The VM creation script covers this, but never hurts to be sure) 6. Boot your VM, and enjoy your hardware acceleration! ## Using the driver gathering script You also have the option to use `Compress-GPUPDriverPackage.ps1`, which will gather the various files for you. 1. Run the script on your host, in an admin PowerShell session. It will create `GPUPDriverPackage-[date].zip` in the current directory. 2. Copy the .zip to your guest VM and extract 3. Copy the contents of the extracted `GPUPDriverPackage` folder into `C:\Windows\` 4. Reboot the guest. This will work for nVidia GPUs, at least, and should also work for Intel/AMD ones. ---- Windows features that must be enabled: -
neggles revised this gist
Jun 23, 2021 . 1 changed file with 5 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,11 +4,12 @@ This works on a Windows 10 version 2004 machine with an nVidia GPU. It should wo I am not in any way responsible for working this out, that credit goes to [Nimoa at cfx.re](https://forum.cfx.re/t/running-fivem-in-a-hyper-v-vm-with-full-gpu-performance-for-testing-gpu-partitioning/1281205) and [reddit users on r/hyperv](https://www.reddit.com/r/HyperV/comments/huy09l/gpupv_in_hyperv_with_windows_10/) 1. Make sure you have Hyper-V enabled (no way!) - there's a list of other features below that you *might* need, enable those if it doesn't work. 1. Create a new VM using `New-VMWithPartitionGpu.ps1` below and install Windows 10 on it. 1. Gather driver files for your guest using one of the two methods below: ## Gathering driver files manually 1. On your host system: 1. Browse to ``C:\Windows\system32\DriverStore\FileRepository`` 2. Find the ``nvdispsi.inf_amd64_<guid>`` and/or ``nvltsi.inf_amd64_<guid>`` folders, and copy them to a temporary folder 3. Grab ``nvapi64.dll`` from ``C:\Windows\system32`` as well -
neggles revised this gist
Jun 23, 2021 . 1 changed file with 14 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,29 +1,35 @@ # Configuring GPU-PV on Hyper-V This works on a Windows 10 version 2004 machine with an nVidia GPU. It should work on AMD and Intel GPUs too, but they need slightly different driver files copied and I haven't had time to work out which yet. I am not in any way responsible for working this out, that credit goes to [Nimoa at cfx.re](https://forum.cfx.re/t/running-fivem-in-a-hyper-v-vm-with-full-gpu-performance-for-testing-gpu-partitioning/1281205) and [reddit users on r/hyperv](https://www.reddit.com/r/HyperV/comments/huy09l/gpupv_in_hyperv_with_windows_10/) ## Gathering driver files for the guest manually. 1. Make sure you have Hyper-V enabled (no way!) - there's a list of other features below that you *might* need, enable those if it doesn't work. 2. Create a new VM using `New-VMWithPartitionGpu.ps1` below and install Windows 10 on it. 3. On your host system: 1. Browse to ``C:\Windows\system32\DriverStore\FileRepository`` 2. Find the ``nvdispsi.inf_amd64_<guid>`` and/or ``nvltsi.inf_amd64_<guid>`` folders, and copy them to a temporary folder 3. Grab ``nvapi64.dll`` from ``C:\Windows\system32`` as well 4. On your guest system: 1. Browse to ``C:\Windows\system32\HostDriverStore\FileRepository`` (You will likely need to create the ``HostDriverStore`` and ``FileRepository`` directories) 2. Copy the two driver folders you collected from your host to this path. 3. Copy ``nvapi64.dll`` to ``C:\Windows\system32\`` on the guest as well, and a few others - look at 'driver details' for your GPU in device manager to work out which ones 5. Shut down the guest VM, make sure checkpoints are disabled and automatic stop action is set to 'Turn Off' (The VM creation script covers this, but never hurts to be sure) 6. Boot your VM, and enjoy your hardware acceleration! ## Using the driver gathering script You also have the option to use `Make-PvGpuDriverZip.ps1` which will gather the various files for you, if you have an nVidia GPU. I've not yet worked out how to get the filename list device manager presents without abuse of devcon.exe or similar. Just run the script and it'll make you a GPUPDrivers.zip, extract it and dump the contents of the GPUPDrivers folder into C:\Windows\ then reboot. ---- Windows features that must be enabled: * Hyper-V and all associated subfeatures * Windows Subsystem for Linux * Virtual Machine Platform -
neggles revised this gist
Jun 23, 2021 . 2 changed files with 120 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,118 @@ # set work dir $sScriptRoot = if ($PSScriptRoot) { $PSScriptRoot } else { $PWD } $WorkDir = Join-Path -Path $sScriptRoot -ChildPath 'temp/GPUPDrivers' # Get all GPU-P capable GPUs in this system. $PvGPUs = (Get-VMPartitionableGpu).Name # warn user if there's more than one GPU if ($PvGPUs.Count -lt 1) { throw [System.Management.Automation.ItemNotFoundException]::new('Did not find any GPU-P capable GPUs in this system.') } elseif ($PvGPUs.Count -gt 1) { Write-Warning -Message ( ("You have {0} GPU-P capable GPUs in this system. `n" -f $PvGPUs.Count) + " At present, there is no way to control which one is assigned to a given VM.`n" + " Unless one of the available GPUs is an intel IGP, it is highly recommended`n" + " that you disable the GPU(s) you do not wish to use.`n") $choices = '&Yes', '&No' $question = 'Do you wish to proceed without disabling the extra GPU(s)?' if ($Host.UI.PromptForChoice('', $question, $choices, 1) -eq 1) { throw [System.Management.Automation.ActionPreferenceStopException]::new('User requested to cancel.') } } Write-Output -InputObject "Getting device information for each GPU-P capable GPU..." # this expr strips the device instance ID out of the VMPartitionableGpu 'name' param $InstanceExpr = [regex]::New('^\\\\\?\\(.+)#.*$') # get all partitionable GPUs, and find their actual devices $PvCapableGPUs = $PvGPUs | ForEach-Object -Process { Get-PnpDevice -InstanceId $InstanceExpr.Replace($_, '$1').Replace('#', '\') } # Get CIM instances for all video controllers and PnP Entities $VideoControllers = Get-CimInstance -ClassName Win32_VideoController $PnPEntities = Get-CimInstance -ClassName Win32_PnPEntity # lets make a driver zip! #$DriverFiles = Import-PowerShellDataFile -Path "$sScriptRoot\DriverFiles.psd1" $DriverFiles = @{ nVidia = @{ System32 = @( 'nvapi64.dll' 'nvcuda.dll' 'nvcuvid.dll' 'nvdispco*.dll' 'nvdispgenco*.dll' 'nvEncodeAPI64.dll' 'NvFBC64.dll' 'NvIFR64.dll' 'NvIFROpenGL.dll' 'nvofapi64.dll' 'OpenCL.dll' 'vulkan-1.dll' 'vulkan-1-*.dll' ) SysWOW64 = @( 'nvapi.dll' 'nvcuda.dll' 'nvcuvid.dll' 'nvEncodeAPI.dll' 'NvFBC.dll' 'NvIFR.dll' 'NvIFROpenGL.dll' 'nvofapi.dll' 'OpenCL.dll' 'vulkan-1.dll' 'vulkan-1-*.dll' ) } } # make work dirs if not exist (New-Item -ItemType Directory -Path "$WorkDir/System32/HostDriverStore/FileRepository" -Force -ErrorAction SilentlyContinue | Out-Null) (New-Item -ItemType Directory -Path "$WorkDir/SysWOW64" -Force -ErrorAction SilentlyContinue | Out-Null) foreach ($PvCapableGPU in $PvCapableGPUs) { # Get the CIM instance for this GPU $VideoController = $VideoControllers.Where{ $_.PNPDeviceID -eq $PvCapableGPU.InstanceId }[0] $PnPEntity = $PnPEntities.Where{ $_.InstanceId -eq $PvCapableGPU.InstanceId }[0] $SystemDriver = Get-CimAssociatedInstance -InputObject $PnPEntity -Association Win32_SystemDriverPNPEntity Write-Output -InputObject ('Gathering driver files for GPU "{0}"...' -f $PnPEntity.FriendlyName) # am it nvidia or AMD? $GPUVendor = switch -wildcard ($PnPEntity.FriendlyName) { '*nvidia*' { "nVidia" } '*intel*' { "Intel" } '*AMD*' { "AMD" } '*ATI*' { "AMD" } Default { throw } } # now we're going to be very dirty. lets get the driverstore path $DriverFolder = Split-Path -Path $SystemDriver.PathName -Parent # copy all the files from the driver into the HostDriverStore we're building Copy-Item -Path $DriverFolder -Destination "$WorkDir/System32/HostDriverStore/FileRepository" -Recurse -Force # this is the tricky part... tbh i am cheating here $DriverFiles.$GPUVendor.System32 | ForEach-Object -Process { Copy-Item -Path ('{0}\System32\{1}' -f $Env:SystemRoot, $_) -Destination "$WorkDir/System32/" -Force } $DriverFiles.$GPUVendor.SysWOW64 | ForEach-Object -Process { Copy-Item -Path ('{0}\SysWOW64\{1}' -f $Env:SystemRoot, $_) -Destination "$WorkDir/SysWOW64/" -Force } Write-Output -InputObject "Files gathered for GPU." } Write-Output -InputObject "Creating .zip..." Set-Location -Path (Split-Path -Path $WorkDir -Parent) Compress-Archive -Path GPUPDrivers -DestinationPath "$sScriptRoot/GPUPDrivers.zip" -CompressionLevel Fastest -Confirm:$false -Force Set-Location -Path $sScriptRoot Write-Output -InputObject "Cleaning up..." Remove-Item -Recurse -Force -Path "$sScriptRoot/temp" Write-Output -InputObject "Driver zip created, extract it and copy the contents into C:\Windows\ on the guest VM." This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,7 @@ $Config = @{ VMName = 'GPU-VM' # pick a NAME BRO VMMemory = 8192MB # Set appropriately VMCores = 4 # likewise MinRsrc = 80000000 # We don't really know what these values do - my GPU reports 100,000,000 available units... MaxRsrc = 100000000 # I suspect in the current implementation they do nothing, but this is known to work - play around if you like! OptimalRsrc = 100000000 -
neggles revised this gist
Aug 11, 2020 . 1 changed file with 4 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,23 +10,25 @@ $Config = @{ try { # Create VM if needed if (-not (Get-VM -Name $Config.VMName)) { $NewVM = @{ Name = $Config.VMName MemoryStartupBytes = $Config.VMMemory Generation = 2 Version = 9.2 # Latest available virtual hardware version } New-VM @NewVM } # Enable VM features required for this to work $SetParams = @{ VMName = $Config.VMName GuestControlledCacheTypes = $true LowMemoryMappedIoSpace = 1Gb HighMemoryMappedIoSpace = 32GB AutomaticStopAction = 'TurnOff' CheckpointType = 'Disabled' } Set-VM @SetParams # Disable secure boot Set-VMFirmware -VMName $Config.VMName -EnableSecureBoot 'Off' -
neggles revised this gist
Aug 5, 2020 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,6 +2,8 @@ This works on a Windows 10 version 2004 machine with an nVidia GPU. It should work on AMD and Intel GPUs too, but they need slightly different driver files copied and I haven't had time to work out which yet. I am not in any way responsible for working this out, that credit goes to [Nimoa at cfx.re](https://forum.cfx.re/t/running-fivem-in-a-hyper-v-vm-with-full-gpu-performance-for-testing-gpu-partitioning/1281205) and [reddit users on r/hyperv](https://www.reddit.com/r/HyperV/comments/huy09l/gpupv_in_hyperv_with_windows_10/) Steps: 1. Make sure you have Hyper-V enabled (no way!) - there's a list of other features below that you *might* need, enable those if it doesn't work. 2. Create a new VM using 'New-GPUPartitionVM.ps1' below and install Windows 10 on it. -
neggles revised this gist
Aug 5, 2020 . 3 changed files with 84 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,57 @@ $Config = @{ VMName = 'GPU-VM' VMMemory = 8192MB # Set appropriately VMCores = 4 MinRsrc = 80000000 # We don't really know what these values do - my GPU reports 100,000,000 available units... MaxRsrc = 100000000 # I suspect in the current implementation they do nothing, but this is known to work - play around if you like! OptimalRsrc = 100000000 } try { # Create VM if needed if (-not (Get-VM -Name $Config.VMName)) { New-VM @{ Name = $Config.VMName MemoryStartupBytes = $Config.VMMemory Generation = 2 Version = 9.2 # Latest available virtual hardware version } } # Enable VM features required for this to work Set-VM @{ VMName = $Config.VMName GuestControlledCacheTypes = $true LowMemoryMappedIoSpace = 1Gb HighMemoryMappedIoSpace = 32GB AutomaticStopAction = 'TurnOff' CheckpointType = 'Disabled' } # Disable secure boot Set-VMFirmware -VMName $Config.VMName -EnableSecureBoot 'Off' # Parameters for vAdapter $GPUParams = @{ VMName = $Config.VMName MinPartitionVRAM = $Config.MinRsrc MaxPartitionVRAM = $Config.MaxRsrc OptimalPartitionVRAM = $Config.OptimalRsrc MinPartitionEncode = $Config.MinRsrc MaxPartitionEncode = $Config.MaxRsrc OptimalPartitionEncode = $Config.OptimalRsrc MinPartitionDecode = $Config.MinRsrc MaxPartitionDecode = $Config.MaxRsrc OptimalPartitionDecode = $Config.OptimalRsrc MinPartitionCompute = $Config.MinRsrc MaxPartitionCompute = $Config.MaxRsrc OptimalPartitionCompute = $Config.OptimalRsrc } # Add adapter if not present, update if present if (-not (Get-VMGpuPartitionAdapter -VMName $Config.VMName)) { Add-VMGpuPartitionAdapter @GPUParams } else { Set-VMGpuPartitionAdapter @GPUParams } } catch { throw $PSItem } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,20 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,27 @@ ## Configuring GPU Partitioning / GPU-PV on Hyper-V This works on a Windows 10 version 2004 machine with an nVidia GPU. It should work on AMD and Intel GPUs too, but they need slightly different driver files copied and I haven't had time to work out which yet. Steps: 1. Make sure you have Hyper-V enabled (no way!) - there's a list of other features below that you *might* need, enable those if it doesn't work. 2. Create a new VM using 'New-GPUPartitionVM.ps1' below and install Windows 10 on it. 3. On your host system: 1. Browse to ``C:\Windows\system32\DriverStore\FileRepository`` 2. Find the ``nvdispsi.inf_amd64_<guid>`` and ``nvltsi.inf_amd64_<guid>`` folders, and copy them to a temporary folder 3. Grab ``nvapi64.dll`` from ``C:\Windows\system32`` as well 4. On your guest system: 1. Browse to ``C:\Windows\system32\HostDriverStore\FileRepository`` (You will likely need to create the ``HostDriverStore`` and ``FileRepository`` directories) 2. Copy the two driver folders you collected from your host to this path. 3. Copy ``nvapi64.dll`` to ``C:\Windows\system32\`` on the guest as well 5. Shut down the guest VM, make sure checkpoints are disabled and automatic stop action is set to 'Turn Off' (The VM creation script covers this, but never hurts to be sure) 6. Boot your VM, and enjoy your hardware acceleration! ---- Windows features I had enabled: * Hyper-V and all associated subfeatures * Windows Containers - don't know if you actually need this one * Windows Sandbox * Windows Subsystem for Linux * Virtual Machine Platform -
neggles created this gist
Aug 4, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,20 @@ $Min = 80000000 $Max = 100000000 $Optimal = 100000000 $Params = @{ VMName = 'NameOfTheVM' MinPartitionVRAM = $Min MaxPartitionVRAM = $Max OptimalPartitionVRAM = $Optimal MinPartitionEncode = $Min MaxPartitionEncode = $Max OptimalPartitionEncode = $Optimal MinPartitionDecode = $Min MaxPartitionDecode = $Max OptimalPartitionDecode = $Optimal MinPartitionCompute = $Min MaxPartitionCompute = $Max OptimalPartitionCompute = $Optimal } Add-VMGpuPartitionAdapter @Params Set-VM –VMName $Params.VMName -GuestControlledCacheTypes $true -LowMemoryMappedIoSpace 1Gb –HighMemoryMappedIoSpace 32GB