ghw icon indicating copy to clipboard operation
ghw copied to clipboard

Unable to fetch GPU information in WSL windows

Open Chetan177 opened this issue 10 months ago • 2 comments

I have an application which heavily really on hardware, The piece of code perfectly run fine on windows and macos, but when I try to run the application on WSL Windows the GPU information is empty.

Example:

package main

import (
	"fmt"

	"github.com/jaypipes/ghw"
)

func main() {
	gpu, err := ghw.GPU()
	if err != nil {
		fmt.Printf("Error getting GPU info: %v", err)
	}

	fmt.Printf("%v\n", gpu)

	for _, card := range gpu.GraphicsCards {
		fmt.Printf(" %v\n", card)
	}
}

Output when I run it inside wsl:

Image

Output in normal windows:

Image

Chetan177 avatar Feb 11 '25 13:02 Chetan177

Hi @Chetan177 hope you are doing well! You have run into the classic "Windows Subsystem for Linux isn't actually Linux and isn't Windows" problem. :)

This is why I often refer to WSL as "World's Shoddiest Linux" (though I often use a different spelling of "Shoddiest" ;)

I'm not sure there's much I will be able to do to "fix" this problem, since it really has to do with various expected Linux sysfs mounts not existing in WSL, and there's really not much I can do about that. I'm all open to any ideas you might have, though!

jaypipes avatar Feb 11 '25 13:02 jaypipes

@Chetan177 @jaypipes thx. I made some attempts. Although they failed, I still hope that the GPU-PV technology can be successfully applied. This might require the joint efforts of developers from all sectors. This is also one of the few functions that can be virtualized at a very low cost on consumer-level NVIDIA graphics cards.

mian.go

package main

import (
    "fmt"
    "github.com/jaypipes/ghw"
)

func main() {
    gpu, err: = ghw.GPU()
    if err != nil {
        fmt.Printf("Error getting GPU info: %v", err)
    }
    fmt.Printf("%v\n", gpu)
    for _, card: = range gpu.GraphicsCards {
        fmt.Printf(" %v\n", card)
    }

    fmt.Printf("=====\n")
    accel, err: = ghw.Accelerator()
    if err != nil {
        fmt.Printf("Error getting processing accelerator info: %v", err)
    }

    fmt.Printf("%v\n", accel)
    for _, device: = range accel.Devices {
        fmt.Printf(" %v\n", device)
    }

}

output:

root@fnasfnas1:/tmp/test# go run main.go 
gpu (0 graphics cards)
=====
processing accelerators (1 device)
 device @d8f8:00:00.0 -> driver: 'dxgkrnl' class: 'Display controller' vendor: 'Microsoft Corporation' product: 'Basic Render Driver'

system info:

root@fnasfnas1:/tmp/test# lspci -v
d8f8:00:00.0 3D controller: Microsoft Corporation Basic Render Driver
        Physical Slot: 1349682479
        Flags: bus master, fast devsel, latency 0, NUMA node 0
        Capabilities: [40] Null
        Kernel driver in use: dxgkrnl
        Kernel modules: dxgkrnl

root@fnasfnas1:/tmp/test# lspci -vn
d8f8:00:00.0 0302: 1414:008e
        Physical Slot: 1349682479
        Flags: bus master, fast devsel, latency 0, NUMA node 0
        Capabilities: [40] Null
        Kernel driver in use: dxgkrnl
        Kernel modules: dxgkrnl

root@fnasfnas1:/tmp/test# lsmod | grep dxg
dxgkrnl               225280  0
hv_vmbus              176128  9 hv_balloon,hv_utils,hv_netvsc,hid_hyperv,dxgkrnl,hv_storvsc,hyperv_keyboard,pci_hyperv,hyperv_fb

root@fnasfnas1:/tmp/test# lsmod | grep vgem
vgem                   12288  0
drm_shmem_helper       36864  1 vgem
drm                   757760  4 drm_kms_helper,drm_shmem_helper,vgem

root@fnasfnas1:/tmp/test# ll /dev/dri/
by-path/    card0       renderD128  

root@fnasfnas1:/tmp/test# ll /dev/dri/
total 0
drwxr-xr-x  3 root root        100 Aug 12 00:00 .
drwxr-xr-x 20 root root       3480 Aug 12 00:00 ..
drwxr-xr-x  2 root root         80 Aug 12 00:00 by-path
crw-rw----  1 root video  226,   0 Aug 12 00:00 card0
crw-rw----  1 root render 226, 128 Aug 12 00:00 renderD128

root@fnasfnas1:/tmp/test# ll /dev/dri/card0 
crw-rw---- 1 root video 226, 0 Aug 12 00:00 /dev/dri/card0

root@fnasfnas1:/tmp/test# ll /sys/class/drm/
total 0
drwxr-xr-x  2 root root    0 Aug 12 00:00 .
drwxr-xr-x 53 root root    0 Aug 12 00:00 ..
lrwxrwxrwx  1 root root    0 Aug 12 00:00 card0 -> ../../devices/platform/vgem/drm/card0
lrwxrwxrwx  1 root root    0 Aug 12 00:00 renderD128 -> ../../devices/platform/vgem/drm/renderD128
-r--r--r--  1 root root 4096 Aug 12 00:01 version

root@fnasfnas1:~# glxinfo -B
name of display: localhost:10.0
display: localhost:10  screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
    Vendor: Microsoft Corporation (0xffffffff)
    Device: D3D12 (NVIDIA GeForce RTX 3060) (0xffffffff)
    Version: 22.3.6
    Accelerated: yes
    Video memory: 44776MB
    Unified memory: no
    Preferred profile: core (0x1)
    Max core profile version: 4.2
    Max compat profile version: 4.2
    Max GLES1 profile version: 1.1
    Max GLES[23] profile version: 3.1
OpenGL vendor string: Microsoft Corporation
OpenGL renderer string: D3D12 (NVIDIA GeForce RTX 3060)
OpenGL core profile version string: 4.2 (Core Profile) Mesa 22.3.6
OpenGL core profile shading language version string: 4.20
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile

OpenGL version string: 4.2 (Compatibility Profile) Mesa 22.3.6
OpenGL shading language version string: 4.20
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile

OpenGL ES profile version string: OpenGL ES 3.1 Mesa 22.3.6
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10

root@fnasfnas1:~# nvi
nvidia-ngx-updater  nvidia-smi
root@fnasfnas1:~# nvidia-smi
Tue Aug 12 01:12:25 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 575.64.04              Driver Version: 577.00         CUDA Version: 12.9     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 3060        On  |   00000000:01:00.0  On |                  N/A |
|  0%   51C    P0             35W /  170W |    5243MiB /  12288MiB |      7%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+

Obviously, in Debian 12, hyper-v integrated GPU-PV can access the graphics card. However, this is merely a bridging operation. There are no NVIDIA PCIe devices linked to Debian.

And in WSL, the GPU device registered using /vgem - Virtual GPU Graphics Memory Manager is being used, so we may not be able to obtain pciAddress.

The actual address corresponding to the vgem card0 is /sys/devices/platform/vgem/drm/card0.

regex101: https://regex101.com/r/zgfOA8/1

https://github.com/jaypipes/ghw/blob/d0f46e2c7af550135bdbcc33fc40aa9d70628094/pkg/gpu/gpu_linux.go#L98

Architecture:

https://devblogs.microsoft.com/directx/directx-heart-linux/

Image

So I'm wondering if we have the capability to integrate the virtual graphics card created by the vgem driver. A possible structure for a Graphics Card might look like this

type GraphicsCard struct {
	Address string `json:"address"` // d8f8:00:00.0
	Index int `json:"index"` // 0
	DeviceInfo *pci.Device `json:"pci"` // from pci.New(context.WithContext(i.ctx))
	Node *topology.Node `json:"node,omitempty"` // nil
}

eric-gitta-moore avatar Aug 11 '25 17:08 eric-gitta-moore