protonscr

Hybrid GPU systems: DX12 capability probing uses first Vulkan device rather than discrete GPU

protonopen NVIDIA drivers
ValveSoftware/Proton#9329 · opened 2025-12-21 by EAbuVrwV · updated 2026-04-17 · 17 comments · github
EEAbuVrwV 2025-12-21 github

Summary

On hybrid GPU systems (Intel iGPU + NVIDIA dGPU), Proton/VKD3D-Proton appears to be relying on Vulkan device enumeration order when probing DX12 capabilities. Even when Steam and games are explicitly launched on the discrete GPU (confirmed via system tools), Vulkan seems to be enumerating the iGPU first. Proton then probes that device and reports missing DX12 support, despite the discrete GPU fully supporting it.

As a result, games that require DirectX12 on hybrid GPU systems are unable to launch.

This behavior reproduces across multiple distributions and does not appear to be caused by missing drivers or ICDs, though the timing does roughly line up with recent NVIDIA driver issues that began to manifest post-580.

Question

Is Proton expected to implement additional heuristics or checks for hybrid GPU systems (e.g. preferring discrete GPUs when available), or will this be considered the responsibility of the OS / Vulkan layer?

Downstream issue for context

EEAbuVrwV 2025-12-21 github

It seems that the GPU selection issue was raised with Vulkan around 2019 - 2020, and while a fix was implemented for Windows to prefer the dGPU, a fix was not made for Linux due to technical limitations at the time.

EEAbuVrwV 2025-12-22 github

Update:

After extensive testing on a hybrid GPU system (Intel iGPU + NVIDIA dGPU), I have some new findings that help clarify why DX12 games are now failing under Proton on certain hybrid systems, even when the discrete GPU is available.

First, Vulkan correctly enumerates all devices. vulkaninfo | grep deviceName returns:

deviceName = Intel(R) UHD Graphics (CML GT2)
deviceName = NVIDIA GeForce RTX 3070 Laptop GPU
deviceName = llvmpipe (LLVM 19.1.1, 256 bits)

So all three Vulkan devices (Intel iGPU, NVIDIA dGPU, llvmpipe) are visible to the Vulkan loader. This matches what we would expect to see on a hybrid system and confirms there is no driver installation or ICD problem; Vulkan is functioning and sees every GPU.

Second, Native Vulkan apps prefer the NVIDIA GPU. vkcube returns:

Selected GPU 1: NVIDIA GeForce RTX 3070 Laptop GPU, type: DiscreteGpu

This demonstrates that native Vulkan applications like vkcube are capable of selecting the dGPU by default, even when multiple GPUs are present. The NVIDIA Vulkan Optimus layer is not used for basic selection in simple Vulkan apps like this.

Third, the NVIDIA Vulkan Optimus layer is present, but now acts as advisory only. VK_LAYER_NV_optimus=NVIDIA_only vkcube vulkaninfo | grep -A5 Optimus shows:

VK_LAYER_NV_optimus (NVIDIA Optimus layer) Vulkan version 1.4.312, layer version 1:
Devices: count = 3
GPU id = 0 (Intel(R) UHD Graphics (CML GT2))

The layer is loaded and recognizes all 3 GPUS, but its current behavior is now advisory. In other words, it tags the NVIDIA device, but leaves all 3 GPUs visible. This explains why setting VK_LAYER_NV_optimus=NVIDIA_only does not change device enumeration.

Summarizing the Data

Historically, the NVIDIA Vulkan Optimus layer (VK_LAYER_NV_optimus) hid non-NVIDIA devices when NVIDIA_only was set. This effectively forced all Vulkan apps to see only the discrete GPU. Proton and other DX12/Vulkan wrappers would then probe a single device (the NVIDIA GPU) and everything worked correctly.

However, under the new NVIDIA driver versions and observed in the above tests, the Optimus layer no longer hides non-NVIDIA devices. All devices (Intel iGPU, NVIDIA dGPU, and lvmpipe) are enumerated regardless of the environment variable, and the layer is now advisory; it marks the NVIDIA dGPU but does not filter devices. This is consistent with anecdotal reports from other users that DX12 Proton games started failing recently on hybrid systems; the timeline correlates with the newer NVIDIA driver versions.

When NVIDIA’s Optimus layer used to hide the iGPU, the first enumerated device was always the dGPU, so Proton never ran into this failure. Now that the iGPU is visible first, Proton probes the iGPU, fails DX12 capability checks, and aborts the game process instead of retrying the dGPU.

So the root cause seems to be upstream: NVIDIA changed the Optimus layer behavior, which exposed a latent issue in Proton’s device probing logic.

Combining these observations, we see that:

  • The Optimus layer is now advisory-only and is not correctly enforcing NVIDIA_only
  • Vulkan exposes all GPUs (with the iGPU being first and the NVIDIA dGPU second)
  • Proton / VKD3D-Proton probes devices in order of enumeration
  • The first device (Intel iGPU) fails DX12 capability checks
  • Proton aborts initialization and the game never launches
  • Even if Steam or the system is running on the NVIDIA GPU, the DX12 game fails because Proton never retries the discrete GPU after the first device fails
  • Native Vulkan apps that don't rely on the Optimus layer are unaffected, unlike Proton DX12 games

Possible Fixes

  • NVIDIA could provide a Vulkan layer or extension that enforces discrete-only enumeration, or restore device filtering behavior in the Optimus Vulkan layer so that VK_LAYER_NV_optimus=NVIDIA_only hides non-NVIDIA devices like before.

  • NVIDIA should also document advisory-only behavior clearly for developers so they understand that NVIDIA_only no longer guarantees device hiding as it did in prior versions.

  • Proton should allow user override via Steam launch options to explicitly select the dGPU, or to prefer dGPUs ahead of iGPUs when multiple Vulkan devices are present.

  • Proton should also retry device selection if the first enumerated GPU fails DX12 capability checks, and update the DX12 initialization logic to be aware of hybrid systems and multiple GPU scenarios.

EEAbuVrwV 2025-12-28 github

UPDATE WITH POTENTIAL FIX IDENTIFIED:

For comparison purposes: I attempted to launch World of Warcraft and World of Warcraft Classic using Crossover. Note the original tests on Steam Proton were not with World of Warcraft; this is simply to illustrate that a DX12 application can function correctly on the same system while DX12 games inside Steam Proton did not.

When I first tried in Crossover 25.1.0, both WoW programs failed with an error. I then:

  1. Launched Crossover Preview 20251106 with the NVIDIA GPU while on Pop!_OS hybrid graphics mode.
  2. Launched the Battle.net app as a child process under Crossover Preview
  3. Launched World of Warcraft and World of Warcraft Classic as child processes under Battle.net

Both games launched correctly, and the game is running on the NVIDIA GPU under DirectX 12 (see screenshot).

Image

Inspection of the working process under Crossover Preview shows that it explicitly sets:

__VK_LAYER_NV_optimus=NVIDIA_only
__NV_PRIME_RENDER_OFFLOAD=1

and maps winevulkan.dll, vulkan-1.dll, and /dev/nvidia0, indicating DX12 → Vulkan → NVIDIA is active.

This suggests that Crossover Preview applies a policy that forces Vulkan device selection to the discrete GPU, avoiding DX12 initialization on the integrated GPU. (Crossover 25.1.0 appears not to do this) Vulkan enumeration still lists Intel as GPU0, so success depends on overriding enumeration order, not on drivers or hardware.

This aligns with the Steam DX12 failure reported in pop-os/cosmic-epoch#2696 and suggests that Proton’s DX12 path should either prefer PHYSICAL_DEVICE_TYPE_DISCRETE_GPU during Vulkan selection during initial DXGI adapter enumeration, or defer DX12 capability rejection until all Vulkan physical devices are evaluated.

The key point is that DX12 failure in Steam is not due to missing support, but due to early Vulkan device selection on the wrong adapter. Crossover Preview demonstrates a working policy that Proton can mirror.

Aaliqut 2026-01-13 github

Facing the exact same issue. Native vulkan apps work, wine/proton fail to select the correct GPU. Broke almost my entire game library.

Ggilvbp 2026-01-15 github

@aliqut @EAbuVrwV
Hi, I faced a very similar issue when upgrading from a TRX40 ASUS ROG (better BIOS with PCI graphics enum mapping support) to a TRX50 ASUS Sage. I have two identical RTX 3090 GPUs, and after the upgrade I had problems with some DirectX 12 games.

Using DXVK, applying a device filter solved the issue for me. You might want to try this approach:

https://github.com/doitsujin/dxvk#device-filter

Aaliqut 2026-01-16 github

@aliqut @EAbuVrwV Hi, I faced a very similar issue when upgrading from a TRX40 ASUS ROG (better BIOS with PCI graphics enum mapping support) to a TRX50 ASUS Sage. I have two identical RTX 3090 GPUs, and after the upgrade I had problems with some DirectX 12 games.

Using DXVK, applying a device filter solved the issue for me. You might want to try this approach:

https://github.com/doitsujin/dxvk#device-filter

This doesn't work for me unfortunately.

Ggalacticaledge 2026-01-16 github

Replying to https://github.com/ValveSoftware/Proton/issues/9329#issuecomment-3761078627

Can confirm. In the interim, is there a way to do what Crossover Preview does on Proton?

Aaliqut 2026-01-19 github

This is absolutely bizarre, but for whatever reason, running nvidia-smi fixes the issue for me until next reboot. I have no idea how or why.

ZZardizz 2026-01-20 github

This is absolutely bizarre, but for whatever reason, running nvidia-smi fixes the issue for me until next reboot. I have no idea how or why.

That is crazy. It works! This is some strange bug.

EEAbuVrwV 2026-01-20 github

This is absolutely bizarre, but for whatever reason, running nvidia-smi fixes the issue for me until next reboot. I have no idea how or why.

Interesting; I did try using nvidia-smi repeatedly in the original downstream issue on on Pop!_OS and it didn't work for me.

Ggalacticaledge 2026-01-21 github

This is absolutely bizarre, but for whatever reason, running nvidia-smi fixes the issue for me until next reboot. I have no idea how or why.

Interesting; I did try using nvidia-smi repeatedly in the original downstream issue on on Pop!_OS and it didn't work for me.

Using a System76 laptop running CachyOS and it doesn't fix the issue for me either

EEAbuVrwV 2026-01-25 github

Update — test results & new root cause hypothesis:

New testing confirms that when using Steam launch options:

  • VKD3D_CONFIG=force_adapter=discrete → original DirectX 12 feature probing error still occurs
  • VKD3D_CONFIG=skip_feature_check → same DX12 error again
  • Combining VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json → silent early exit (Steam returns to the green Play button)

These results suggest:

  • Proton starts and correctly sees the discrete NVIDIA GPU via Vulkan; adapter ordering isn’t blocking startup
  • Failure occurs during Direct3D 12 feature negotiation / device capability checks
  • Modifying Vulkan ICD or adapter selection only shifts when the failure occurs (dialog vs silent exit), but does not allow the app to initialize

@kisak-valve this may not be an NVIDIA driver issue as tagged because:

  • Vulkan enumeration and ICD forcing prove the NVIDIA Vulkan driver exposes the discrete GPU correctly
  • Other native Vulkan and DXVK workloads work fine
  • The failure persists even when adapter enumeration is manually corrected, pointing at a layer above the driver

This strongly suggests the problem is VKD3D‑Proton’s DXGI/D3D12 feature negotiation or capability reporting. While the issue became noticeable with NVIDIA 580 driver update, testing confirms Proton sees the discrete GPU correctly; DX12 initialization still fails due to incomplete feature reporting. The 580 driver may have simply changed Vulkan/DXGI behavior in a way that triggers the failure more reliably.

Suggested direction for patching:

Proton’s DX12 startup logic via VKD3D currently relies on Vulkan enumeration order and does not fully validate the discrete GPU’s feature set on hybrid systems. This should be hardened so VKD3D correctly exposes all required DX12 capabilities during device probing, preventing early D3D12 initialization failures.

Ggalacticaledge 2026-03-13 github

This issue is still around as of March 2026. I just want to raise awareness of it again.

EEAbuVrwV 2026-03-30 github

Has anyone been able to test if the new 595 production driver branch has fixed this for them? I haven't yet but wondering if anyone else has looked into it. I'm still skeptical that the driver is the actual root cause of the problem.

Kkakra 2026-03-30 github

I'm not sure if I'm seeing a similar problem. I have my Intel iGPU enabled for video encoding via obs-vkcapture. But my primary GPU is my NVIDIA RTX 3080 Ti, my monitors are not connected to the iGPU. This system is not a laptop with a classical iGPU first / dGPU on demand setup.

After a fresh reboot, most DX12 games will just not launch. Usually the wine process of the game exe just segfaults, e.g.:

# coredumpctl info 11114
           PID: 11114 (NoRestForTheWic)
           UID: 1000 (kakra)
           GID: 1000 (kakra)
        Signal: 11 (SEGV)
     Timestamp: Tue 2026-03-31 00:51:54 CEST (6min ago)
  Command Line: $'Z:\\home\\kakra\\.local\\share\\Steam\\steamapps\\common\\NoRestForTheWicked\\NoRestForTheWicked.exe'
    Executable: /home/kakra/.local/share/Steam/steamapps/common/Proton - Experimental/files/bin/wine64-preloader
 Control Group: /user.slice/user-1000.slice/[email protected]/app.slice/app-steam-app1371980-10934.scope
          Unit: [email protected]
     User Unit: app-steam-app1371980-10934.scope
         Slice: user-1000.slice
     Owner UID: 1000 (kakra)
       Boot ID: 21ff45df0578447998a52df2d755b5b0
    Machine ID: 121b87ca633e8ac0016656680000001b
      Hostname: jupiter
       Storage: /var/lib/systemd/coredump/core.NoRestForTheWic.1000.21ff45df0578447998a52df2d755b5b0.11114.1774911114000000.zst (present)
  Size on Disk: 5.8M
       Message: Process 11114 (NoRestForTheWic) of user 1000 dumped core.

                Stack trace of thread 11196:
                #0  0x00007f17905ea6a0 n/a (n/a + 0x0)
                ELF object binary architecture: AMD x86-64

This situation persists for all games until I either run nvidia-smi once, or I manage to launch a game that successfully starts (usually non-DX12 games).

After this, all DX12 titles will work.

This issue seems to exist since around driver 580. It has also been reported to the NVIDIA forums by one user who reported the nvidia-smi trick which also works for me.

Ggalacticaledge 2026-04-17 github

Can we see if implementing an environment variable that ignores iGPUs can be made as a workaround?

Besides, the DXVK developer claims it's a 'setup issue', but if this issue impact iGPU/GPU setups, it makes me question the validity of that statement.

Kkakra 2026-04-17 github

Can we see if implementing an environment variable that ignores iGPUs can be made as a workaround?

Well, I'm using:

export DXVK_FILTER_DEVICE_NAME="NVIDIA"
export VKD3D_FILTER_DEVICE_NAME="NVIDIA"

but it doesn't fix my particular left-over problem, although it fixes a lot of other problems.