La course aux armements DirectX : pourquoi les pilotes battent parfois le silicium

Cet article vous a aidé ?

Vous avez changé de GPU. La fiche technique promettait la lune. Puis votre graphique des temps de trame ressemble à un sismographe,
le CPU bloque un cœur, et la carte « plus rapide » se comporte comme si elle faisait du bénévolat pour le silicium de l’année dernière.
Si vous avez déjà vu une nouvelle version de pilote réparer magiquement un jeu que vous pensiez « lié au GPU », vous avez vu
la vérité gênante : dans le monde DirectX, le pilote est souvent le produit de performance.

Ce n’est pas une conspiration des fabricants ; c’est de l’architecture. DirectX est un contrat avec des échappatoires, et le pilote est
l’avocat, le juge, et parfois la personne qui déplace discrètement les meubles pour que votre application cesse de trébucher.
Parlons de comment les pilotes peuvent battre le silicium, ce que cela signifie pour des systèmes de production réels (oui, les jeux comptent),
et comment diagnostiquer les goulots d’étranglement sans se contenter de crier « mets à jour les pilotes lol ».

Pilotes vs silicium : d’où vient vraiment la performance

Les GPU sont brutalement rapides pour le travail pour lequel ils sont conçus. Ils sont aussi extrêmement exigeants sur la manière dont on les alimente.
La différence entre « le GPU est utilisé à 40 % » et « le GPU est saturé » n’est souvent pas des transistors. C’est
la soumission des commandes, la compilation des shaders, l’ordonnancement, la gestion de la résidence mémoire, et mille petites décisions
sur les transitions d’état et la synchronisation.

En pratique, votre temps de trame est la somme de :

  • Travail côté CPU : construction des listes de commandes, culling, physique, animation, et le coût de communiquer avec le pilote/runtime.
  • Travail du pilote/runtime : traduction des appels API en paquets matériels, validation, mise en cache, gestion de la mémoire et de l’état.
  • Travail côté GPU : exécution des shaders, étapes fixed-function, rastérisation, cœurs RT, moteurs de copie, etc.
  • Present et pacing : composition, vsync, comportement du modèle flip, et ordonnancement OS autour de cela.

Les GPU modernes peuvent être inactifs parce que le CPU n’a pas pu soumettre le travail assez vite, ou parce que le pilote n’a pas
su le traduire efficacement, ou parce que le GPU attend la résidence mémoire, ou parce que le compositeur OS a décidé que votre fenêtre est « spéciale » aujourd’hui.
Les pilotes sont la colle, et la colle peut être la partie la plus rapide de votre système ou celle qui devient collante sous pression.

Quand on dit « les pilotes battent parfois le silicium », cela signifie ceci : une mise à jour de pilote peut débloquer un débit que
le matériel avait déjà, parce que le pilote est celui qui choisit le codegen, le regroupement, l’ordonnancement et la mise en cache.
Deux versions de pilote différentes peuvent faire paraître le même GPU comme deux produits différents.

Ce que DirectX promet réellement (et ce qu’il ne promet pas)

DirectX n’est pas « une couche mince au-dessus du matériel ». C’est une promesse de compatibilité avec un ensemble d’abstractions.
Ces abstractions évoluent avec le temps — Direct3D 9 vs 11 vs 12 sont presque des religions différentes — et chaque évolution
change qui paie quels coûts.

Direct3D 11 : le pilote faisait beaucoup de travail invisible

D3D11 a rendu les développeurs productifs en leur permettant d’être légèrement irresponsables. Vous pouviez inonder d’appels de dessin,
changer l’état constamment, et compter sur le pilote pour jongler avec les hazards, réordonner le travail, et corriger les décisions.
Ce n’était pas gratuit. Le pilote effectuait souvent un lourd travail CPU par dessin, et ce surcoût pouvait dominer le temps de trame.

Les fournisseurs sont devenus très bons en optimisation de pilote D3D11 parce qu’ils devaient l’être. Si votre pilote ne pouvait pas « digérer »
un titre D3D11 réel, votre GPU paraissait lent dans les benchmarks qui vendaient des GPU. Le pilote est devenu une arme compétitive,
et l’arme la plus impitoyable est celle que les utilisateurs ne voient pas.

Direct3D 12 : vous obtenez la puissance, mais vous recevez aussi la facture

D3D12 est une API de plus bas niveau. L’application est censée gérer plus explicitement : états des ressources, synchronisation,
heaps de descripteurs, PSO, et souvent la stratégie de compilation des shaders. En théorie, moins de surcharge pilote.
En réalité, plus d’occasions de créer des charges pathologiques puis d’accuser « le pilote ».

Le pilote compte toujours énormément en D3D12 parce que :

  • La compilation des shaders, la mise en cache et le codegen côté pilote peuvent encore différer selon le fournisseur et la version.
  • La résidence mémoire et le paging sont toujours médiés par WDDM et la politique du pilote.
  • L’ordonnancement dépend toujours des règles OS + pilote (queues matérielles, priorités, granularité de préemption).
  • Le comportement des bibliothèques de pipeline et du cache PSO peut décider si votre « première exécution » est un festival de stutter.

DirectX est une cible mouvante, et la « cible » est votre jeu/application expédié

Le détail opérationnel le plus important : les pilotes sont régulièrement mis à jour. Votre matériel est expédié une fois.
Cela signifie que la « spécification de performance » d’un GPU pour une charge DirectX est en fait une fonction de :
matériel + version du pilote + build de l’OS + build du jeu + paramètres + overlays + compositeurs d’arrière-plan.
Félicitations, votre benchmark est maintenant un système distribué.

Comment les pilotes gagnent : les leviers de performance invisibles

Si vous voulez un modèle mental : le silicium fournit le potentiel, les pilotes décident si vous le convertissez en rendement.
Voici les leviers principaux où les pilotes déplacent couramment la performance suffisamment pour compenser des écarts matériels bruts.

1) Compilateurs de shaders : les faiseurs de rois discrets

HLSL se compile en DXIL (ou en ancien bytecode), puis le pilote recompile en ISA pour le GPU.
Cette dernière étape est là où vit beaucoup de « magie du pilote » : ordonnancement des instructions, allocation des registres,
décisions d’occupation des vagues, transformations mathématiques, et spécialisation basée sur des particularités matérielles connues.

Une mise à jour de pilote peut changer le codegen suffisamment pour :

  • Augmenter l’occupation (moins de registres) et booster le débit dans des charges favorables à la bande passante.
  • Réduire les stalls en améliorant l’ordonnancement des instructions autour de la latence des fetchs de textures.
  • Corriger des miscompiles ou des problèmes de précision qui forçaient des chemins de repli plus lents.
  • Ajuster le comportement des opérations de sous-groupe/vague qui affectent le coût de divergence.

Les compilateurs de shaders sont aussi l’endroit où « ça devient plus rapide chez tel fournisseur » arrive, car chaque fournisseur
possède des heuristiques et une maturité différentes. Ce n’est pas de la triche ; c’est de l’ingénierie. Mais c’est de l’ingénierie qui
change le produit après que vous l’ayez acheté.

2) Gestion et mise en cache des Pipeline State Objects (PSO)

Les PSO de D3D12 sont destinés à être créés en amont. Si vous créez des PSO à l’exécution au milieu d’une trame, vous méritez le stutter
que vous obtenez. Mais la réalité est sale : pipelines de contenu, mods, permutations dynamiques et modifications live-service.
Le pilote peut aider en mettant efficacement en cache les PSO compilés, ou nuire en invalidant les caches lors des mises à jour.

Sous Windows, il existe aussi des caches disque et des caches par application. Quand une mise à jour de pilote les réinitialise,
votre « première exécution » devient un festival de compilations. La deuxième exécution est correcte, et tout le monde débat sur les forums
du placebo.

3) Soumission de commandes et regroupement

Même avec D3D12, il y a une surcharge autour de la soumission des listes de commandes, des primitives de synchronisation, et de la gestion des queues.
Les pilotes peuvent optimiser la manière dont ils tamponnent et soumettent le travail au noyau, et comment ils fusionnent de petites soumissions.

D3D11 est plus spectaculaire : le pilote réordonne parfois, regroupe et déduplique les changements d’état. Un pilote qui devient plus malin
à propos de « ce changement d’état ne fait rien » peut accélérer un titre sans toucher au jeu.

4) Résidence mémoire, paging et la « falaise VRAM »

La gestion de la mémoire graphique sous Windows est un problème à trois corps : intention de l’app, politique du pilote, politique OS.
Quand votre working set tient dans la VRAM, tout va bien. Quand il n’y tient pas, vous tombez d’une falaise vers le paging,
les stalls, et le fameux « pourquoi mes 1 % bas sont si mauvais ? »

Les pilotes influencent les décisions de résidence, les heuristiques d’éviction et l’agressivité du préfetch.
Deux versions de pilote peuvent se comporter différemment sous pression : l’une thrash, l’autre dégrade plus progressivement.
Si vous traquez le stutter, supposez que vous êtes proche d’une frontière de résidence tant que l’on ne vous a pas prouvé le contraire.

5) Ordonnancement et préemption : WDDM n’est pas votre ami, c’est votre propriétaire

Les politiques d’ordonnancement WDDM déterminent comment les contextes partagent le GPU. Les jeux concurrencent les navigateurs, la lecture vidéo,
les overlays de capture, les panneaux de contrôle RGB, et le compositeur OS. Le pilote participe à cet ordonnancement.

Une mise à jour de pilote peut ajuster la granularité de préemption, les priorités de queue, ou le comportement temporel autour du present.
Cela peut changer significativement le pacing des trames même si la moyenne FPS reste la même.

6) Modes de present, pacing et « fluidité » en tant que propriété d’ingénierie

L’utilisateur n’expérimente pas le « FPS moyen ». Il expérimente les temps de trame et le pacing.
Le mode de present (flip vs blit), le vsync, le VRR, et le comportement du compositeur décident si votre budget de 16,6 ms
est stable ou une roulette russe.

Les pilotes peuvent :

  • Améliorer les heuristiques de pacing pour certains patterns de present.
  • Changer leur interaction avec le compositeur en fenêtré sans bordure vs plein écran exclusif.
  • Corriger des bugs temporels qui causent du microstutter sur certains taux de rafraîchissement d’écran.

7) Contournements : l’art peu glamour de l’expédition

La base de données du pilote d’aplombs d’applications et de contournements est énorme. Certains sont des bascules officielles,
d’autres sont silencieux. Ces contournements peuvent désactiver des chemins rapides buggués, forcer différentes options de compilation de shader,
ou ajuster la gestion des ressources pour des titres spécifiques.

C’est pourquoi vous voyez parfois un nouveau jeu « mieux fonctionner chez le fournisseur X » dès le jour 1 : ce n’est pas que le silicium
a appris de nouveaux tours du jour au lendemain. Le pilote a appris à survivre au comportement de ce jeu.

Blague n°1 : Les pilotes sont comme le café — tout le monde prétend pouvoir s’en passer, puis on les regarde essayer.

Faits et histoire : la course aux armements en 10 cicatrices

  • Ère D3D9 : les « remplacements de shaders » étaient courants : les pilotes remplaçaient parfois des motifs de code shader par des équivalents plus rapides quand ils les reconnaissaient.
  • D3D10 a introduit une réinitialisation majeure : il a resserré le modèle API et cassé beaucoup de comportements pilotes « astucieux » de D3D9.
  • D3D11 a popularisé le rendu multithread… en quelque sorte : les deferred contexts existaient, mais beaucoup de moteurs bloquaient encore sur des verrous pilotes et des goulots CPU.
  • Mantle a influencé D3D12 : l’industrie a compris que la surcharge pilote tuait les scènes lourdes en draw calls.
  • L’évolution de WDDM a changé les performances : WDDM 1.x vs 2.x a apporté des dynamiques différentes de gestion mémoire et d’ordonnancement pour les GPU modernes.
  • Shader Model 6 a migré vers DXIL : la pipeline de compilation est devenue plus standardisée, mais la backend pilote décide toujours de l’ISA finale.
  • Le mode flip est devenu la norme : Windows moderne privilégie le modèle flip pour l’efficacité ; cela change latence et pacing comparé aux anciens chemins blit.
  • L’adoption de DXR a exposé des écarts de maturité pilotes : les performances early ray tracing ont souvent fortement varié avec les mises à jour pilotes car la pile était nouvelle et les chemins rapides évoluaient.
  • Resizable BAR a compté davantage dans certains workloads DX : permettre l’accès CPU à des plages VRAM plus larges a modifié les patterns de transfert et réduit la surcharge dans certains scénarios.
  • Les « pilotes day-one » sont devenus une attente du marché : pas parce que le marketing l’a demandé, mais parce que les contournements côté pilote et l’ajustement des caches shaders faisaient partie de la préparation au lancement.

Modes de défaillance courants : quand le pilote devient le goulot

Si vous exploitez des systèmes de production, vous apprenez à détester les files invisibles. Les pilotes graphiques sont essentiellement
des files invisibles avec un ventilateur attaché. Voici les modes de défaillance qui apparaissent dans de véritables déploiements DirectX.

Surcharge CPU du pilote (surtout D3D11)

Symptômes : un cœur CPU coincé, GPU sous-utilisé, FPS plafonné par le « thread de rendu », évolutivité meilleure avec des CPU plus rapides qu’avec des GPU plus rapides.
Les causes racines incluent des changements d’état bavards, des appels de dessin excessifs, des mises à jour de ressources inefficaces, ou une sérialisation du pilote liée aux verrous.

Stutter de compilation de shaders (DX12, et aussi DX11 si mal fait)

Symptômes : pics énormes à la première apparition d’un effet, « la première passe est horrible », la seconde exécution est correcte, les pics coïncident avec de nouveaux matériaux.
Cause racine : compilation de shaders/PSO à la demande, invalidations de cache, ou cache shader pilote désactivé/effacé.

Thrash de résidence VRAM

Symptômes : stalls périodiques, chutes soudaines en tournant la caméra, grande variance avec textures haute résolution, pire en fenêtré sans bordure avec d’autres apps ouvertes.
Cause racine : le working set dépasse la VRAM ou la fragmentation cause des évictions ; paging par le pilote/OS vers la mémoire système.

Problèmes de present/composition

Symptômes : « le FPS est élevé mais c’est désagréable », latence d’entrée incohérente, stutter uniquement en fenêtré sans bordure, problèmes après activation HDR/VRR.
Causes racines : changements de chemin compositeur, modes de rafraîchissement incompatibles, overlays interceptant le present, ou bugs pilote dans des modes de present spécifiques.

Régressions pilote et « corrections » qui déplacent le problème

Symptômes : un jeu devient plus rapide, un autre devient plus lent, ou votre workload stable devient instable après une mise à jour.
Cause racine : changements d’heuristiques, changements de cache, ou activations/désactivations de chemins rapides via des contournements.

Playbook de diagnostic rapide (premier/deuxième/troisième)

Voici la liste que j’utilise quand quelqu’un dit « la perf DX est bizarre » et que je veux du signal en 15 minutes.
L’objectif est d’identifier quelle file est affamée : CPU, pilote, GPU, résidence mémoire, ou present.

Premier : décidez si vous êtes lié CPU/pilote ou GPU

  • Surveillez l’utilisation CPU par cœur et l’utilisation des moteurs GPU.
  • Si l’utilisation GPU est faible mais qu’un cœur CPU est chaud, suspectez une surcharge pilote ou un goulot du thread de rendu.
  • Si le GPU est à ~95–100 % et le CPU modéré, vous êtes probablement lié au GPU (puis concentrez-vous sur les shaders, la bande passante, les réglages).

Second : identifiez la classe de stutter (compilation, résidence, present)

  • Stutter sur effets rencontrés la première fois : compilation shader/PSO.
  • Stutter en tournant la caméra ou en entrant de nouvelles zones : streaming/résidence.
  • Stutter avec un temps GPU stable mais present irrégulier : pacing/compositeur/overlays.

Troisième : bisectez agressivement les variables

  • Basculez plein écran vs sans bordure.
  • Désactivez les overlays (capture, chat, monitoring).
  • Essayez une version de pilote connue pour être stable (pas forcément « la plus récente »).
  • N’effacez les caches shader que si vous cherchez intentionnellement à reproduire le comportement « première exécution ».

La règle de décision : si vous ne pouvez pas nommer la file goulot, vous n’êtes pas en train de diagnostiquer — vous racontez une histoire.

Tâches pratiques avec commandes : mesurer, décider, répéter

Ces tâches sont conçues pour des systèmes Windows, mais j’utilise un shell de type bash (Git Bash, MSYS2, WSL appelant des utilitaires Windows).
Les commandes sont réalistes. L’idée est la discipline : capturer des preuves, les interpréter, décider quoi faire ensuite.

Tâche 1 : Confirmer le modèle GPU et la version du pilote

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate | Format-Table -Auto"
Name                          DriverVersion      DriverDate
----                          -------------      ----------
NVIDIA GeForce RTX 4070       31.0.15.5212       11/28/2024 12:00:00 AM

Ce que cela signifie : Vous avez maintenant la vérité terrain pour le triage de régression et les rapports de bogues constructeur.
Décision : Si les performances ont changé récemment, épinglez la dernière version de pilote connue bonne et planifiez un bisect (ne devinez pas).

Tâche 2 : Vérifier la build Windows et les indices de version WDDM

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-ComputerInfo | Select-Object WindowsProductName,WindowsVersion,OsBuildNumber | Format-List"
WindowsProductName : Windows 11 Pro
WindowsVersion     : 23H2
OsBuildNumber      : 22631

Ce que cela signifie : Les builds OS peuvent changer le comportement du compositeur, l’ordonnancement et les bizarreries de la pile graphique.
Décision : Si un problème apparaît après une mise à jour Windows, reproduisez sur une machine témoin ou revenez en arrière pour confirmation avant d’accuser le GPU.

Tâche 3 : Capturer rapidement l’utilisation des moteurs GPU

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Counter '\GPU Engine(*)\Utilization Percentage' -SampleInterval 1 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object InstanceName,CookedValue | Sort-Object CookedValue -Descending | Select-Object -First 10 | Format-Table -Auto"
InstanceName                                        CookedValue
------------                                        ----------
pid_1234_luid_0x00000000_0x0000_engtype_3D             92.3412
pid_1234_luid_0x00000000_0x0000_engtype_Copy            4.1201
pid_5678_luid_0x00000000_0x0000_engtype_VideoDecode     1.0033

Ce que cela signifie : Une haute utilisation 3D suggère un lien côté GPU ; un 3D bas avec un CPU élevé suggère un problème de soumission/pilote.
Décision : Si le 3D est bas, arrêtez de modifier les réglages graphiques et commencez à profiler la surcharge CPU/pilote.

Tâche 4 : Vérifier le CPU par processus et identifier la saturation mono-cœur

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Process | Sort-Object CPU -Descending | Select-Object -First 8 Name,Id,CPU,Threads | Format-Table -Auto"
Name        Id    CPU   Threads
----        --    ---   -------
GameClient  1234  987.4  62
Discord     4321  112.6  45
chrome      8888   71.9  83

Ce que cela signifie : Un grand temps CPU et un grand nombre de threads ne prouvent pas un rendu multithread ; cela masque souvent un thread de rendu brûlant.
Décision : Si le FPS est bas et qu’un cœur est épinglé dans le Gestionnaire des tâches, traitez comme lié CPU/pilote tant que le temps GPU ne prouve le contraire.

Tâche 5 : Inspecter les erreurs DXGI et liées au pilote dans les logs de l’Event Viewer

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-WinEvent -LogName System -MaxEvents 50 | Where-Object {$_.ProviderName -match 'Display|dxgkrnl'} | Select-Object TimeCreated,Id,ProviderName,Message | Format-Table -Wrap"
TimeCreated           Id ProviderName Message
-----------           -- ------------ -------
1/12/2026 9:41:02 PM 4101 Display     Display driver nvlddmkm stopped responding and has successfully recovered.

Ce que cela signifie : Les TDR et resets de pilote se déguisent souvent en « stutter aléatoire » ou « hitching bizarre ».
Décision : Si vous voyez 4101 ou des avertissements dxgkrnl, arrêtez d’optimiser et commencez par stabiliser : fréquences, températures, alimentation et cohérence du pilote d’abord.

Tâche 6 : Vérifier l’état de composition DWM et la configuration de rafraîchissement

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Process dwm | Select-Object Name,Id,CPU,StartTime | Format-List"
Name      : dwm
Id        : 1024
CPU       : 58.12
StartTime : 1/12/2026 7:03:11 PM

Ce que cela signifie : Si le CPU de DWM monte pendant le jeu en mode sans bordure, la composition/les overlays peuvent interférer.
Décision : Testez le plein écran exclusif ou désactivez les overlays ; si cela corrige le pacing, vous avez un problème de chemin de present, pas un problème de shader.

Tâche 7 : Identifier overlays et hooks de capture comme suspects de première classe

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Process | Where-Object {$_.Name -match 'GameBar|Xbox|RTSS|obs|Discord|Steam|nvcontainer'} | Select-Object Name,Id | Format-Table -Auto"
Name         Id
----         --
GameBar      7777
Discord      4321
Steam        2468
nvcontainer  1357

Ce que cela signifie : Les overlays peuvent hooker Present, ajouter du travail GPU, ou changer le comportement du flip.
Décision : Pour le diagnostic, exécutez en propre : désactivez les overlays un par un et mesurez les changements de pacing.

Tâche 8 : Vérifier l’activité disque et la pression sur l’emplacement du cache shader

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Counter '\PhysicalDisk(_Total)\Disk Bytes/sec' -SampleInterval 1 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object CookedValue"
CookedValue
-----------
124928512
98234368
110231552

Ce que cela signifie : De grosses rafales disque pendant le jeu correspondent souvent à des écritures du cache shader ou au streaming d’actifs.
Décision : Si le stutter coïncide avec des pics disque, séparez la compilation shader (effet première exécution) du streaming (nouvelle zone) en répétant la même scène.

Tâche 9 : Confirmer l’état du fichier d’échange (le paging peut amplifier les problèmes de résidence)

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-CimInstance Win32_PageFileSetting | Select-Object Name,InitialSize,MaximumSize | Format-Table -Auto"
Name               InitialSize MaximumSize
----               ----------- -----------
C:\pagefile.sys    16384       32768

Ce que cela signifie : Des pagefiles trop petits peuvent provoquer un comportement de pression mémoire agressif qui ressemble à de l’instabilité GPU.
Décision : Si vous êtes proche des limites RAM en jouant/créant du contenu, utilisez la gestion système du pagefile ou une taille fixe raisonnable ; ne « désactivez pas le pagefile pour les performances ».

Tâche 10 : Vérifier rapidement la pression mémoire

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Counter '\Memory\Available MBytes' -SampleInterval 1 -MaxSamples 3 | Select-Object -ExpandProperty CounterSamples | Select-Object CookedValue"
CookedValue
-----------
812
790
765

Ce que cela signifie : Une faible RAM disponible augmente la probabilité de stutter dû au paging et à la contention du streaming d’actifs.
Décision : Si la RAM disponible descend sous ~1–2 Go pendant le jeu, fermez les applications en arrière-plan avant d’accuser le GPU.

Tâche 11 : Vérifier que le jeu utilise réellement DX12 (ou DX11)

cr0x@server:~$ powershell.exe -NoProfile -Command "Get-Process GameClient | Select-Object -ExpandProperty Modules | Where-Object {$_.ModuleName -match 'd3d12|d3d11|dxgi'} | Select-Object ModuleName,FileName | Format-Table -Auto"
ModuleName FileName
---------- --------
dxgi.dll   C:\Windows\System32\dxgi.dll
d3d12.dll  C:\Windows\System32\d3d12.dll

Ce que cela signifie : Vous seriez surpris de voir à quelle fréquence la « performance DX12 » est testée alors que l’application est retombée silencieusement en DX11.
Décision : Si l’API chargée est incorrecte, corrigez les options de lancement/config d’abord ; n’interprétez pas les chiffres de performance tant que le chemin API n’est pas confirmé.

Tâche 12 : Vérifier le plan d’alimentation et le comportement de fréquence CPU

cr0x@server:~$ powercfg.exe /getactivescheme
Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e  (Balanced)

Ce que cela signifie : Les économies d’énergie agressives peuvent augmenter la latence et empirer le pacing dans les scénarios limités CPU/pilote.
Décision : Pour le diagnostic, utilisez un plan haute performance sur les desktops, puis validez l’impact avant de le conserver (les laptops sont différents).

Tâche 13 : Détecter la pression mémoire GPU via les outils fournisseurs (exemple NVIDIA)

cr0x@server:~$ nvidia-smi --query-gpu=name,driver_version,utilization.gpu,memory.used,memory.total --format=csv
name, driver_version, utilization.gpu [%], memory.used [MiB], memory.total [MiB]
NVIDIA GeForce RTX 4070, 552.12, 91 %, 11342 MiB, 12282 MiB

Ce que cela signifie : Une mémoire utilisée proche du total suggère que vous frôlez l’éviction et le paging (surtout en 4K + textures élevées).
Décision : Si la mémoire est >90% et que vous voyez du stutter, réduisez d’abord la qualité des textures ou la résolution ; ne poursuivez pas encore les « réglages pilote ».

Tâche 14 : Capturer une trace ETW rapide pour l’ordonnancement GPU/present (setup)

cr0x@server:~$ wpr.exe -start GPU -filemode
WPR: Started recording with profile GPU.

Ce que cela signifie : Vous enregistrez une trace ETW qui peut être inspectée plus tard dans WPA pour voir les délais de present, les queues GPU et la soumission CPU.
Décision : Si vous ne pouvez pas identifier le goulot avec des compteurs, prenez une trace. Deviner est plus lent que mesurer.

Tâche 15 : Arrêter la trace et l’enregistrer

cr0x@server:~$ wpr.exe -stop C:\temp\gpu-trace.etl
WPR: Trace successfully saved to C:\temp\gpu-trace.etl

Ce que cela signifie : Vous avez maintenant un fichier qui montre où le temps est passé : CPU, GPU, present, DWM, files pilote.
Décision : Utilisez WPA pour confirmer : êtes-vous bloqué sur le present, en attente du GPU, ou limité CPU dans les appels pilote ?

Tâche 16 : Sanity check réseau basique (oui, ça compte pour les rapports de « stutter »)

cr0x@server:~$ ping -n 10 1.1.1.1
Pinging 1.1.1.1 with 32 bytes of data:
Reply from 1.1.1.1: bytes=32 time=15ms TTL=58
Reply from 1.1.1.1: bytes=32 time=16ms TTL=58
Reply from 1.1.1.1: bytes=32 time=120ms TTL=58
Reply from 1.1.1.1: bytes=32 time=16ms TTL=58

Ping statistics for 1.1.1.1:
    Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 15ms, Maximum = 120ms, Average = 26ms

Ce que cela signifie : Les joueurs signalent du « stutter » qui est en réalité de la gigue réseau causant des hitchs d’animation/streaming dans les titres en ligne.
Décision : Si les graphiques de temps de trame ne montrent pas de hitchs mais que l’expérience utilisateur le fait, vérifiez la variance réseau avant de réécrire votre renderer.

Trois mini-récits issus de la réalité d’entreprise

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Un studio a livré une mise à jour DX12 pour un jeu live. La liste de changements semblait propre : moins d’appels de dessin, meilleur batching,
barrières plus explicites, et une belle étape de précompilation des PSO pendant les écrans de chargement. L’équipe a supposé que si le jeu
fonctionnait bien sur leurs machines de test internes, il fonctionnerait bien chez les clients avec des « GPU similaires ».

La semaine de lancement, les tickets de support ont afflué : freezes aléatoires de 2–3 secondes lors du premier match, parfois suivis d’un crash.
Le freeze ne se reproduisait pas de façon consistante au bureau. Quand il se reproduisait, quelqu’un hausse les épaules et blâmait « Windows being Windows ».
Pendant ce temps, le canal incident était rempli de joueurs partageant des contournements comme « joue un match bot d’abord » et « ne pas alt-tab ».

La mauvaise hypothèse était subtile : ils supposaient que la compilation shader et le comportement du cache PSO étaient identiques entre versions de pilote et builds Windows.
Sur une fraction de systèmes clients, le cache shader du pilote était essentiellement froid à chaque exécution à cause d’un réglage de profil et d’un outil de nettoyage disque
qui supprimait les répertoires de cache. Leur étape « préconstruire les PSO pendant le chargement » compilait certains mais pas toutes les permutations.
Celles manquantes se compilaient à la demande pendant le premier firefight, au moment où le jeu streamait aussi des textures.

La correction n’a pas été « dites aux joueurs de mettre à jour les pilotes », bien que cela ait réduit la portée. La vraie correction a été d’ingénierie :
ajouter un chemin de warmup shader/PSO déterministe couvrant les permutations courantes, persister un cache PSO côté application,
et ajouter de la télémétrie pour les événements de compilation corrélés aux pics de trame. Ils ont aussi mis à jour le runbook incident pour poser
« est-ce une invalidation de cache ? » avant d’accuser le renderer.

Mini-récit 2 : L’optimisation qui a mal tourné

Une application de visualisation d’entreprise (pensez CAD + rendu temps réel) a connu un goulot CPU en D3D11. Le thread de rendu chauffait,
et l’équipe a fait ce que font les équipes sous deadline : ils ont déplacé plus de travail sur des worker threads en utilisant des deferred contexts.
L’idée était simple — paralléliser l’enregistrement des commandes, réduire le temps passé dans le pilote sur le thread principal,
et garder le GPU occupé.

Dans des tests synthétiques, le FPS moyen s’est amélioré. L’équipe a célébré. Puis les utilisateurs ont commencé à signaler des « hitchs aléatoires » lors
de la rotation de grands assemblages. Le hitching était pire sur des CPU haut de gamme, ce qui est toujours un excellent moyen d’entamer une réunion.

Le retour de bâton venait du comportement du pilote et des coûts de synchronisation. Le chemin deferred context a augmenté la quantité de fusion
par trame des listes de commandes et introduit une contention dans les mises à jour de ressources qui n’étaient pas conçues pour le parallélisme.
Le pilote a aussi frappé des verrous internes plus souvent parce que l’app créait une tempête de petites listes de commandes, chacune avec des changements d’état
que le pilote pouvait auparavant dédupliquer dans un flux mono-thread.

Ils ont finalement annulé le changement pour les pires cas et implémenté une correction plus ennuyeuse mais efficace : réduire les changements d’état, batcher les draws par matériau,
et mettre en cache agressivement les objets d’état immuables. Ils ont aussi limité les deferred contexts à des workloads spécifiques où cela aidait de manière constante.
La leçon n’était pas « les threads sont mauvais ». C’était « la surcharge pilote n’est pas une fonction pure des cœurs CPU ».

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la journée

Une petite équipe ops supportait une flotte de kiosques Windows exécutant une expérience interactive basée sur DirectX. Le matériel était identique
à l’achat, mais le monde réel en a décidé autrement : des mises à jour Windows sont arrivées, les pilotes GPU ont dérivé, et un fournisseur a expédié
un nouvel utilitaire d’overlay qui « aidait » en surveillant les performances.

Ils avaient une pratique que personne ne voulait payer jusqu’à ce que cela importe : une image dorée avec versions de pilote épinglées,
un build OS connu, et une fenêtre de maintenance mensuelle où les changements étaient mis en scène, testés, puis déployés progressivement.
C’était ennuyeux. C’était aussi la différence entre « une flotte stable » et « un cauchemar de support ».

Un mois, une nouvelle version de pilote a amélioré les performances dans un benchmark de jeu populaire, et la direction a demandé pourquoi les kiosques n’étaient pas mis à jour immédiatement.
L’équipe ops a résisté. Ils ont d’abord mis en scène. En staging, ils ont trouvé un problème de timing du mode de present sur la dalle 60Hz spécifique du kiosque qui causait du microstutter — pas de perte FPS, juste une sensation dégradée.

Ils ont retenu la mise à jour, déposé un ticket fournisseur avec une reproduction minimale (plus des traces ETW), et ont expédié les kiosques avec la version épinglée.
La journée a été sauvée par une pratique dont personne ne se vante aux conférences : déploiement contrôlé, métriques de base, et le courage de dire « pas encore ».

Blague n°2 : Une mise à jour de pilote est un billet de loterie dont le prix est « votre app fonctionne comme mardi dernier ».

Erreurs communes : symptômes → cause racine → correction

Cette section existe pour vous empêcher de perdre une semaine. Ce sont des récidivistes que j’ai vus dans les jeux, la visualisation,
et les applications d’entreprise utilisant DirectX comme compositeur d’UI.

1) Symptôme : utilisation GPU faible, FPS bas

  • Cause racine : goulot de soumission CPU/pilote (trop d’appels draw, changements d’état, ou surcharge D3D11).
  • Correction : Réduire les draw calls ; batcher par matériau ; éviter les changements d’état redondants ; passer à D3D12 seulement si vous pouvez réellement gérer les coûts explicites.

2) Symptôme : les 1 % bas sont terribles, les moyennes sont correctes

  • Cause racine : stutter de compilation shader, création de PSO en milieu de trame, ou thrash de résidence VRAM.
  • Correction : Précompiler/warmup des PSO ; persister les bibliothèques PSO ; s’assurer que le cache shader est activé ; réduire les textures si la VRAM est proche du plein.

3) Symptôme : la fenêtre sans bordure stuttere ; le plein écran exclusif est fluide

  • Cause racine : chemin de composition/overlays/interaction de timing DWM.
  • Correction : Désactiver les overlays ; tester différents modes de present ; privilégier le modèle flip ; envisager le plein écran exclusif pour les apps sensibles à la latence.

4) Symptôme : le stutter apparaît après une mise à jour pilote, puis disparaît après « quelque temps »

  • Cause racine : caches shader invalidés ; recompilation graduelle au fur et à mesure que le contenu est rencontré.
  • Correction : Fournir un warmup shader en-app ; ne pas interpréter la performance « première exécution » comme l’état stable ; documenter le comportement des caches pour le support.

5) Symptôme : freezes aléatoires, parfois avec un événement de reset pilote

  • Cause racine : TDR déclenché par un hang GPU, fréquences instables/undervolt, ou bug pilote frappant un chemin shader spécifique.
  • Correction : Revenir aux réglages d’usine des fréquences ; réduire les undervolts agressifs ; capturer ETW + dump ; si reproductible, minimiser le shader et déposer un bug fournisseur.

6) Symptôme : performances très différentes entre fournisseurs pour le même contenu DX12

  • Cause racine : backends de compilateur et heuristiques différentes ; points optimaux différents pour la taille de vague, la pression des registres, et les patterns de barrières.
  • Correction : Utiliser du profiling agnostique fournisseur (PIX + outils fournisseurs) ; éviter les comportements indéfinis ; tester plusieurs variantes de shader si nécessaire.

7) Symptôme : « J’ai changé de GPU mais pas d’amélioration »

  • Cause racine : goulot CPU/pilote, problèmes de lien PCIe, contraintes du plan d’alimentation, ou l’app est plafonnée par present/vsync.
  • Correction : Valider les caps present/vsync ; vérifier la saturation des cœurs CPU ; confirmer la vitesse du lien PCIe dans les outils fournisseur ; tester le mode non plafonné pour le diagnostic.

8) Symptôme : microstutter sans pics CPU/GPU évidents

  • Cause racine : pacing de trame et irrégularités de la file de present (souvent compositeur/VRR/décalage de rafraîchissement).
  • Correction : Changer le mode de present (exclusif vs sans bordure) ; aligner les réglages de rafraîchissement ; réduire les clients GPU en arrière-plan ; tracer le present avec ETW.

Listes de contrôle / plan étape par étape

Checklist A : Hygiène de reproduction (cessez de vous gaslighter)

  1. Épinglez la version exacte du pilote et le build OS pour le test.
  2. Désactivez les overlays et outils de capture pour les runs de base.
  3. Enregistrez les paramètres : résolution, vsync/VRR, mode fenêtre, suréchantillonneurs.
  4. Exécutez la même scène trois fois : cold start, warm run, warm run encore.
  5. Consignez les stats de temps de trame (moyenne, 1 % low) et notez où les stutters surviennent.

Checklist B : Décider quel sous-système est coupable

  1. Si l’utilisation GPU est faible et qu’un cœur CPU est chaud : concentrez-vous sur la soumission/surcharge pilote.
  2. Si l’utilisation GPU est élevée : concentrez-vous sur le coût des shaders, la bande passante, et les réglages.
  3. Si le stutter survient sur des effets de première exécution : concentrez-vous sur la compilation shader/PSO.
  4. Si le stutter survient dans de nouvelles zones : concentrez-vous sur le streaming et la résidence.
  5. Si le stutter dépend du mode (sans bordure vs plein écran) : concentrez-vous sur le present/compositeur.

Checklist C : Triage de régression (comment arrêter les disputes sur Slack)

  1. Reproduire sur deux machines : une témoin, une affectée.
  2. Bisecter les versions de pilote (dernière bonne → première mauvaise) si possible.
  3. Capturer des traces ETW sur les deux et comparer le comportement du present + des queues GPU.
  4. Vérifier le comportement du cache shader (est-ce qu’il se réinitialise ? s’écrit-il sur disque ?).
  5. Si la régression est spécifique à un fournisseur, réduire au test minimal et le soumettre correctement.

Checklist D : Conseils pour l’expédition (quoi faire avant la sortie)

  1. Implémenter la préconstruction des PSO et un cache géré par l’application pour les permutations courantes.
  2. Fournir une option de « warmup shader » ou l’exécuter automatiquement pendant des moments non interactifs.
  3. Suivre les événements de compilation et les délais de present dans la télémétrie (avec conformité opt-in/confidentialité).
  4. Tester sur plusieurs versions de pilote, y compris des versions plus anciennes « stables populaires ».
  5. Documenter les overlays connus problématiques et fournir des conseils utilisateurs qui ne les blâment pas.

FAQ

1) Comment une mise à jour de pilote peut-elle rendre mon GPU plus rapide sans changer le matériel ?

Parce que le pilote contrôle le codegen backend des shaders, la mise en cache, le regroupement, la politique de résidence mémoire et les interactions d’ordonnancement.
Si le pilote réduit la surcharge CPU ou génère une ISA meilleure pour des shaders chauds, vous obtenez de vrais gains sur le même silicium.

2) DX12 est-il toujours plus rapide que DX11 ?

Non. DX12 réduit certaines surcharges pilote, mais il transfère la responsabilité à l’application. Si le moteur crée des PSO en milieu de trame,
gère mal les barrières ou inonde le système de petites soumissions, DX12 peut être plus lent ou causer plus de stutter.

3) Pourquoi ai-je du stutter seulement au premier match ou au premier chargement ?

Généralement la compilation des shaders ou la création de PSO à la demande, plus des caches froids. Les mises à jour pilotes peuvent aussi invalider les caches.
La correction est la précompilation/warmup et la persistance des caches, pas seulement « plus de FPS ».

4) Quelle est la différence entre « lié GPU » et « lié pilote » ?

Lié GPU signifie que le GPU est occupé à exécuter du travail et que le temps de trame suit le temps GPU. Lié pilote signifie que le CPU/pilote ne peut pas soumettre ou préparer
le travail assez vite, donc le GPU attend. Une faible utilisation GPU avec un thread de rendu chaud est l’indice classique.

5) Les overlays comptent-ils vraiment autant ?

Oui. Beaucoup d’overlays interceptent Present, ajoutent du travail de composition, ou introduisent de la synchronisation. Ils peuvent aussi changer le mode de present ou interférer
avec le VRR. Pour le diagnostic, désactivez-les. Pour l’expédition, supposez que les utilisateurs vont les exécuter et rendez votre chemin de present robuste.

6) Pourquoi la « fluidité » change-t-elle même quand le FPS moyen est inchangé ?

Le pacing des trames concerne la variance, pas la moyenne. Le comportement de la file de present, le timing du compositeur, et l’ordonnancement peuvent rendre les trames irrégulières.
Les pilotes peuvent changer cela avec des mises à jour car ils modifient des heuristiques temporelles et des comportements de synchronisation.

7) Dois-je dire aux utilisateurs d’installer toujours le dernier pilote ?

Pour les consommateurs, « le dernier » est souvent acceptable, mais dans des environnements gérés vous voulez un « connu bon ». Épinglez une version validée,
déployez par étapes, et mettez à jour progressivement. Traitez les pilotes comme toute autre dépendance avec un risque de régression.

8) Les pilotes peuvent-ils inclure des optimisations et contournements par jeu ?

Absolument. C’est courant et souvent nécessaire. L’échange est l’imprévisibilité : des heuristiques ajustées pour un titre peuvent affecter un autre.
C’est pourquoi le triage des régressions nécessite l’épinglage de versions et des traces reproductibles.

9) Quelle est la manière la plus rapide pour trouver le goulot ?

Corrélez les pics de temps de trame soit avec le temps de soumission CPU, soit avec le temps d’exécution GPU, soit avec le délai de present. Si les compteurs ne suffisent pas,
prenez une trace ETW (WPR/WPA) et regardez les queues GPU et les événements Present.

10) Est-ce de la « triche » quand les pilotes optimisent pour des motifs spécifiques ?

Pas intrinsèquement. Ça devient un problème quand les optimisations reposent sur un comportement indéfini ou brisent la correction. En tant qu’ingénieur,
vous devriez préférer des chemins explicites et conformes à la spécification pour ne pas être à la merci des heuristiques par version.

Un principe opérationnel à garder

Idée paraphrasée, attribuée à Gene Kim : améliorez le flux et raccourcissez les boucles de rétroaction ; de petits changements mesurables battent les suppositions héroïques.
Cela s’applique aux régressions pilotes et au travail de performance autant qu’aux incidents de disponibilité.

Conclusion : prochaines étapes qui font vraiment la différence

La course aux armements DirectX n’est pas seulement des fournisseurs qui se battent avec le silicium. Ce sont des fournisseurs qui expédient des compilateurs,
des ordonnanceurs, des caches et des contournements à haute fréquence. Le pilote est une surface de performance, et il peut absolument rendre le GPU d’hier
meilleur que celui d’aujourd’hui si la pile logicielle lui est plus favorable.

Prochaines étapes pratiques :

  1. Cessez de diagnostiquer avec des vibes. Confirmez le chemin API, la version du pilote, le build OS et le mode de present avant de comparer quoi que ce soit.
  2. Classifiez la file goulot. CPU/pilote vs GPU vs résidence vs present. Puis optimisez la bonne chose.
  3. Rendez la compilation ennuyeuse. Préconstruisez les PSO, warmpez les shaders, et persistez les caches pour que la « première exécution » ne soit pas un cauchemar.
  4. Traitez les pilotes comme des dépendances. Épinglez, mettez en scène, déployez progressivement, et gardez un chemin connu bon.
  5. Utilisez des traces quand les compteurs mentent. ETW est le geste adulte quand le pacing des trames devient étrange.

Si vous faites ces cinq choses, vous passerez moins de temps à vous disputer sur quel GPU est « meilleur » et plus de temps à expédier un renderer qui se comporte
comme un système professionnel : mesurable, débogable, et prévisible en performance.

← Précédent
Proxmox vs VMware ESXi : quel hyperviseur choisir en 2026 ?
Suivant →
ZFS : utiliser NVMe comme L2ARC — quand l’ARC ne suffit pas

Laisser un commentaire