Glide vs Direct3D : la guerre des API qui a décidé l’avenir du jeu vidéo

Cet article vous a aidé ?

Vous êtes de garde. Un patch « simple » arrive. Soudain, votre ferme de build Windows ne parvient pas à reproduire un plantage que votre labo QA voit instantanément — seulement sur un pilote GPU spécifique, seulement après le chargement d’un niveau, seulement quand le v-sync est désactivé.
Si cette douleur vous semble moderne, félicitations : vous venez de revivre les années 1990, quand les API graphiques n’étaient pas tant des abstractions que des armes politiques.

Le combat Glide vs Direct3D ne portait pas seulement sur les triangles. Il portait sur qui possédait le temps du développeur, qui supportait le fardeau du pilote, et qui se faisait blâmer quand des images se transformaient en confettis.
Cette bataille a décidé comment le jeu PC allait évoluer — et elle enseigne encore aujourd’hui des leçons inconfortables sur les plateformes, la portabilité et la réalité opérationnelle.

Ce qui était réellement en jeu (et pourquoi cela vous concerne)

L’histoire de surface est familière : une API propriétaire (Glide) construite autour du matériel Voodoo de 3dfx contre le Direct3D généraliste de Microsoft.
Mais « API » ici n’était pas un contrat propre. C’était un canal de distribution, un choix d’expérience développeur, et un pari sur la fiabilité.

Glide offrait une interface étroite, alignée sur le matériel : moins de choix, moins de surprises et, dans de nombreux cas, des performances très élevées.
Direct3D offrait une abstraction large : plus d’appareils, plus de pilotes, plus de cas limites et, en fin de compte, plus de portée.

Si vous gérez des systèmes en production, vous connaissez déjà le schéma.
L’interface propriétaire est celle qui fait hurler votre démo. L’interface standardisée est celle qui survit au deuxième fournisseur, à la troisième mise à jour de l’OS et à la cinquième réorganisation d’équipe.

Le jeu à la fin des années 1990 était un laboratoire chaotique pour ce compromis.
Le côté gagnant n’était pas celui qui faisait les « meilleurs » triangles.
C’était celui qui rendait les triangles possibles sur le plus de machines avec le moins de drame continu.

Glide en pratique : rapide, étroit et dangereusement confortable

Glide était l’API de 3dfx pour le matériel de classe Voodoo. Le détail clé : elle était conçue pour se cartographier proprement sur ce que le matériel pouvait faire, pas pour décrire un « GPU idéal » abstrait.
Cela ressemble à une différence de philosophie mineure jusqu’à ce que vous ayez expédié un logiciel.

Quand l’API s’aligne sur le matériel, vous avez moins de « falaises de performance ». Vous avez aussi moins de « comportements indéfinis », parce que l’API refuse simplement d’exprimer de nombreuses combinaisons dangereuses.
En termes opérationnels : Glide a réduit le nombre d’états dans lesquels le système pouvait entrer. La fiabilité adore cela.

L’étroitesse de Glide a aussi produit une forme de dépendance développeur. Les jeux sortaient avec le « support Glide » en vedette, et pour les joueurs avec une carte Voodoo, souvent c’était visuellement et en performance meilleur que les alternatives.
Le problème survient quand vous n’avez pas cette carte. Ou quand cette carte devient « dernière génération » dans un marché qui se réinvente tous les 12–18 mois.

Glide n’était pas portable. Ce n’était pas son but. Du point de vue de 3dfx, ce n’était pas un bug ; c’était l’objectif.
Si vous construisez la meilleure route et que seules vos voitures peuvent y circuler, vous ne gérez pas un système de transport — vous faites payer un péage.

Ce que Glide a bien fait (la partie que l’on romanticise)

  • Performances prévisibles. Moins de couches signifiait moins de surprises et moins de surcharge CPU, surtout à une époque où les CPU peinaient à nourrir les GPU.
  • Modèle mental clair. Les développeurs pouvaient raisonner sur ce que faisait le pipeline Voodoo, puis écrire du code qui correspondait.
  • Moins de permutations de pilotes. Si vous ciblez un seul fournisseur et une famille de produits serrée, votre matrice de tests rétrécit drastiquement.

Ce que Glide a mal fait (la partie que l’on oublie)

  • Fragilité du marché. Votre « plateforme » n’est durable que tant que le bilan et la feuille de route de votre fournisseur tiennent.
  • Verrouillage des développeurs. Le verrouillage fonctionne dans les deux sens : il piège aussi le studio de jeu, pas seulement le client.
  • Risque opérationnel. Si le seul chemin de rendu acceptable est Glide et que le fournisseur n’arrive pas à suivre (fonctionnalités, pilotes, fabrication), vous êtes contraint à expédier des compromis.

Direct3D en pratique : désordonné, large et inévitable

Direct3D est entré dans le combat avec un handicap : les premières versions étaient célèbres pour être difficiles à utiliser et inconsistantes selon le matériel.
Microsoft essayait de définir un contrat graphique pour un marché qui n’avait pas encore décidé ce que signifiait « accélération 3D ».

Voici l’avantage injuste de Direct3D : il était intégré à Windows, et Windows était le mécanisme de distribution du jeu PC que cela plaise ou non.
Si vous vouliez expédier un jeu PC grand public, vous vouliez l’API présente sur l’OS cible sans cérémonie supplémentaire d’installations et de prières de compatibilité.

Le modèle de Direct3D correspondait aussi à la réalité désordonnée d’un monde multi-fournisseurs. Au lieu d’une cible matérielle unique, vous en aviez beaucoup. Au lieu d’une pile pilote unique, vous aviez une jungle.
Cela rendait Direct3D plus lent et plus bugué à court terme. À long terme, cela rendait Direct3D survivable.

L’angle fiabilité : là où Direct3D a discrètement gagné

Direct3D a créé une incitation d’écosystème : les IHV (fournisseurs de GPU) devaient faire fonctionner leurs pilotes avec l’API de Microsoft parce que le marché l’exigeait.
Cela déplace le fardeau loin de chaque studio de jeu maintenant des chemins sur mesure et vers les fournisseurs qui maintiennent compatibilité et performance pour une interface partagée.

Ce n’était pas beau. Mais ça a pris de l’ampleur. Une API standardisée transforme le « chaos par titre » en « responsabilité par pilote », puis le marché punit les pires pilotes.
Pas immédiatement, et pas toujours équitablement, mais finalement.

Blague n°1 : Les bugs de pilote sont comme des paillettes — une fois le sachet ouvert, vous en trouverez dans des endroits sans rapport pendant des mois.

Faits et contexte historique à utiliser au tableau blanc

Quelques points concrets qui comptent quand vous essayez de comprendre pourquoi cette guerre s’est terminée comme elle l’a fait :

  1. Les cartes additionnelles 3dfx Voodoo étaient initialement dédiées au 3D. De nombreux systèmes utilisaient une carte 2D plus une carte Voodoo avec un câble de passage.
  2. Glide était lié au pipeline matériel de 3dfx. Ce couplage serré aidait les performances mais limitait la portabilité et l’évolution des fonctionnalités.
  3. La réputation précoce de Direct3D a souffert de la fragmentation. Les matériels supportaient des capacités différentes ; les développeurs voyaient des résultats inconsistants.
  4. « DirectX » groupait plusieurs API multimédia. Pour les jeux, D3D a bénéficié d’être dans une histoire de plateforme plus large : entrée, son et graphismes sous un même parapluie.
  5. MiniGL existait comme un hack pragmatique. Certains fournisseurs proposaient une couche OpenGL réduite adaptée à des jeux spécifiques, montrant à quel point l’écosystème cherchait des chemins praticables.
  6. L’OpenGL de l’ère Quake a élevé les attentes. Même lorsque Glide était rapide, l’industrie a appris à valoriser les API non mono-fournisseur.
  7. La qualité des pilotes est devenue un avantage concurrentiel. Les fournisseurs qui expédiaient des pilotes D3D rapides et stables gagnaient en notoriété et en contrats OEM.
  8. 3dfx a acquis STB Systems. L’intégration verticale peut être intelligente, mais elle change aussi les relations de distribution et le risque d’exécution dans un marché rapide.
  9. 3dfx a finalement perdu la bataille de la plateforme et a été racheté par NVIDIA. La stratégie d’API propriétaire n’a pas survécu à l’entreprise qui la possédait.

Comment la guerre s’est terminée : économie, outils et la « taxe pilote »

Le récit facile est « Direct3D a gagné parce que Microsoft ». C’est vrai autant que « l’océan est humide » : exact, peu utile, et ça manque le mécanisme.

Le mécanisme était le coût total de possession pour les développeurs et éditeurs.
Si vous dirigez un studio, vous ne vous souciez pas seulement du FPS maximal sur la meilleure carte. Vous vous souciez de :

  • combien de machines clients peuvent exécuter votre jeu du tout,
  • à quelle fréquence vos lignes de support s’allument,
  • combien coûte votre labo de test,
  • quel est le risque pour votre date d’expédition quand le marché GPU change en plein projet.

Glide optimisait le haut de l’expérience pour une tranche du marché. Direct3D optimisait l’ampleur de l’expérience sur un marché qui s’étendait rapidement.
Quand les PC sont devenus une plateforme de jeu de masse, l’étendue a battu la pureté.

Il y a un second mécanisme : les outils et l’inertie de l’écosystème. D3D s’est amélioré. Microsoft a itéré. Les fournisseurs se sont adaptés. Les développeurs ont construit des pipelines autour.
Glide n’avait pas de « gradient de pression » multi-fournisseur pour le maintenir honnête. Il avait la feuille de route de 3dfx, et quand cette feuille de route a flanché, le sort de l’API était scellé.

La « taxe pilote » et qui la paie

Chaque pile graphique paie une taxe pilote : bizarreries de performance, surcharge de validation d’état, détection de fonctionnalités et bugs spécifiques aux fournisseurs.
La question clé est où cette taxe tombe.

Dans un monde d’API propriétaire, la taxe se paie en coûts de portage et clients perdus. Dans un monde d’API standardisée, la taxe se paie en ingénierie pilote et travail de conformité.
L’un s’étend sur tout le marché ; l’autre se répète par titre.

Leçons opérationnelles : ce qu’un SRE apprend d’une guerre d’API graphiques

Si vous plissez les yeux, les API graphiques sont des systèmes distribués. L’application, le runtime, le pilote, le noyau et le microcode GPU ont tous leurs modes de défaillance.
Votre « requête » est une image. Votre « SLO » est la constance du temps d’image. Votre « incident » est un crash, une réinitialisation de périphérique ou un saccade qui rend les joueurs malades.

L’histoire Glide vs Direct3D est une étude de cas sur la gestion du rayon d’explosion. Glide a réduit la variabilité en resserrant les cibles matérielles. Direct3D a réduit la variabilité en standardisant les interfaces
et en laissant les fournisseurs rivaliser sur l’implémentation.

Aucune approche n’élimine les défaillances. Elles les déplacent. Glide les déplace dans la dépendance au marché et le risque plateforme. D3D les déplace dans le comportement des pilotes et l’évolution de l’API.

Une citation qui compte encore

Werner Vogels (CTO d’Amazon) a dit : « Everything fails, all the time. »
En matière graphique, ce n’est pas tant une philosophie qu’une prévision.

Trois mini-récits d’entreprise depuis les tranchées

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

Un studio de jeu de taille moyenne (appelons-les Studio A) a expédié un titre PC avec une architecture à double moteur de rendu : D3D pour la plupart des utilisateurs, plus un « chemin rapide » pour la carte d’un fournisseur particulier.
Le chemin fournisseur ne s’appelait pas Glide, mais il aurait pu : il supposait un ensemble stable de comportements matériels et de bizarreries de pilote.

Tard dans le cycle de sortie, la QA a signalé des plantages aléatoires sur un sous-ensemble de machines après un alt-tab. Non reproductible sur les rigs de dev de l’équipe, tous haut de gamme.
La signature du crash ressemblait à un use-after-free à l’intérieur du renderer. L’équipe l’a traité comme une condition de course dans leur moteur.

La vraie cause : une mauvaise hypothèse sur la perte de périphérique et la durée de vie des ressources. Le chemin spécifique fournisseur supposait que la « perte de périphérique » était rare et que les ressources survivraient
à un changement de mode. Sur certains pilotes, alt-tab déclenchait une réinitialisation du périphérique qui invalidait les textures. Le moteur conservait des pointeurs vers des ressources qui n’étaient plus valides.

La correction n’était pas glamour. Ils ont implémenté une gestion robuste de la perte de périphérique pour les deux moteurs, rendu la propriété des ressources explicite, et ajouté un banc de test pour simuler les réinitialisations de périphérique.
Le taux de crash a chuté. Les tickets de support ont baissé. Les performances ont légèrement diminué parce que les chemins de validation et de recréation étaient maintenant du code réel, pas des pensées optimistes.

La leçon : les chemins rapides propriétaires ou spécifiques aux fournisseurs ont tendance à désactiver silencieusement les garde-fous dont vous ne réalisiez pas que vous dépendiez.
Les hypothèses sont bon marché ; les incidents ne le sont pas.

Mini-récit 2 : L’optimisation qui s’est retournée contre eux

Une autre entreprise (Éditeur B avec une équipe moteur interne) est devenue obsédée par le coût des draw-calls. Raisonnable. Ils visaient une scène limitée par le CPU.
Un ingénieur a proposé le « state shadowing » : suivre le dernier état GPU et ignorer les changements d’état redondants.

Sur le papier, c’était un gain. Dans des micro-benchmarks, cela réduisait les appels pilote et améliorait le temps CPU. Ça a été expédié en production.
Puis les rapports de bugs ont commencé : des textures « restaient » parfois des objets précédents, et certains matériaux rendaient avec le mauvais mode de blend — seulement sur le pilote d’un fournisseur, seulement après de longues sessions de jeu.

La cause racine était subtile. Leur couche d’ombre supposait que si le moteur n’appelait pas « set state », l’état du pilote restait inchangé. Mais le pilote effectuait des invalidations d’état internes
autour d’événements de pagination de ressources. Le modèle du monde du moteur et celui du pilote ont divergé.

L’« optimisation » est devenue une machine à désynchroniser l’état. Ils l’ont retirée et remplacée par une approche plus sûre : construire des objets d’état de pipeline immuables quand c’était possible,
et tolérer des appels redondants quand ce n’était pas le cas.

Les performances sont redevenues « correctes », et la justesse est redevenue « réelle ».
L’équipe moteur a appris une règle durable : vous pouvez mettre en cache l’état à la frontière de l’API, mais seulement si vous possédez aussi chaque événement qui peut invalider cet état. En graphisme, vous ne le faites rarement.

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

Une équipe plateforme dans une grande entreprise (oui, les entreprises expédient aussi des applications 3D) gérait un produit de visualisation basé sur Windows utilisé en environnements régulés.
Leurs clients détestaient les surprises plus qu’ils n’aimaient les FPS.

L’équipe maintenait une matrice de compatibilité : build OS, familles de modèles GPU et versions de pilotes validées.
Ils imposaient aussi des builds reproductibles avec chaînes d’outils figées et fichiers de symboles archivés pour chaque release.
Rien de tout cela n’était excitant. Ce n’était pas optionnel non plus.

Un jour, un client a mis à jour les pilotes GPU sur une flotte et a signalé une corruption d’affichage intermittente. Le pilote fournisseur avait une régression sur un chemin shader spécifique.
Parce que l’équipe avait figé des « pilotes connus bons » et pouvait comparer le comportement rapidement, ils ont isolé la régression en quelques heures plutôt qu’en semaines.

Ils ont publié un avis client : revenir aux pilotes validés, plus un contournement runtime temporaire qui évitait l’option de compilation shader problématique.
Le client est resté opérationnel. Le fournisseur a eu un repro minimal. Un pilote corrigé est finalement arrivé.

La leçon : les pratiques ennuyeuses — figer, matrices, symboles, builds reproductibles — ne semblent pas être du progrès jusqu’au jour où elles empêchent une panne de plusieurs semaines déguisée en « bizarrerie graphique ».

Tâches pratiques : commandes, sorties et décisions (12+)

Voici le genre de tâches que vous exécutez quand un pipeline de rendu est instable ou lent sur des machines Windows, des agents CI ou des machines utilisateur.
L’objectif n’est pas « collecter des données ». L’objectif est : prendre une décision rapidement.

Task 1: Identify GPU and driver version (Linux workstation or Steam Deck-style environment)

cr0x@server:~$ lspci -nn | grep -E "VGA|3D"
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU116 [GeForce GTX 1660] [10de:2184] (rev a1)

Sens de la sortie : Vous avez le fournisseur, l’ID PCI et la famille du modèle.

Décision : Choisir la bonne branche de pilote et la liste de problèmes connus pour cette famille GPU ; ne pas deviner uniquement parce que « c’est NVIDIA ».

Task 2: Confirm loaded kernel driver (Linux)

cr0x@server:~$ lsmod | egrep "nvidia|amdgpu|i915" | head
nvidia_drm             73728  4
nvidia_modeset       1114112  8
nvidia              56770560  345
drm_kms_helper        315392  2 nvidia_drm

Sens de la sortie : Quel pilote est réellement actif, pas seulement installé.

Décision : Si le module attendu n’est pas présent, arrêter l’analyse de performance. Corriger le chargement du pilote d’abord.

Task 3: Inspect OpenGL renderer and version (useful when triaging legacy ports/wrappers)

cr0x@server:~$ glxinfo -B | egrep "OpenGL vendor|OpenGL renderer|OpenGL version"
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA GeForce GTX 1660/PCIe/SSE2
OpenGL version string: 4.6.0 NVIDIA 550.54.14

Sens de la sortie : Confirme quelle pile fournit GL ; souvent corrèle avec le comportement des wrappers (comme d’anciens couches d’émulation Glide).

Décision : Si le renderer est « llvmpipe » ou « Software Rasterizer », vous rasterisez CPU ; traitez tous les temps d’image comme dénués de sens.

Task 4: Check Vulkan device and driver info (modern analog for capability enumeration)

cr0x@server:~$ vulkaninfo --summary | head -n 12
VULKANINFO SUMMARY
==================
Vulkan Instance Version: 1.3.275

Devices:
--------
GPU0:
    apiVersion         = 1.3.275
    driverVersion      = 550.54.14
    vendorID           = 0x10de
    deviceName         = NVIDIA GeForce GTX 1660

Sens de la sortie : Confirme le runtime, la version API et la version du pilote qui affecteront les couches de traduction et les compilateurs de shader.

Décision : Si driverVersion est connu comme mauvais, revenir en arrière ou figer. N’« optimisez » pas autour d’un pilote cassé tant que nécessaire.

Task 5: Capture GPU utilization in real time (NVIDIA)

cr0x@server:~$ nvidia-smi dmon -s pucm -d 1
# gpu   pwr gtemp mtemp    sm   mem   enc   dec  mclk  pclk
# Idx     W     C     C     %     %     %     %   MHz   MHz
    0    78    67     -    92    55     0     0  5000  1860
    0    81    68     -    94    58     0     0  5000  1860

Sens de la sortie : « sm » proche de 90% suggère GPU-bound ; « sm » bas avec CPU élevé suggère CPU-bound ou lié au driver/submit.

Décision : Si le GPU est saturé, arrêter de chasser le coût des draw-calls et regarder le coût des shaders, l’overdraw, la résolution et le post-traitement.

Task 6: Check CPU saturation and scheduling pressure (Linux)

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.8.0 (server) 	01/13/2026 	_x86_64_	(16 CPU)

11:32:20 AM  CPU   %usr %nice %sys %iowait %irq %soft  %steal %guest %gnice %idle
11:32:21 AM  all   68.50 0.00  9.12   0.20 0.00  0.88   0.00   0.00   0.00 21.30
11:32:21 AM    6   99.00 0.00  0.50   0.00 0.00  0.50   0.00   0.00   0.00  0.00

Sens de la sortie : Un cœur chaud à 99% indique souvent un goulot d’étranglement du thread principal dans le chemin de soumission de rendu.

Décision : Si un seul cœur est saturé, prioriser le regroupement, le tri d’état et la réduction des appels API — contraintes classiques de l’ère D3D, toujours réelles aujourd’hui.

Task 7: Find top CPU consumers and thread count (Linux)

cr0x@server:~$ ps -eLo pid,tid,psr,pcpu,comm --sort=-pcpu | head
 4121  4121   6 98.7 game.exe
 4121  4128   3 22.1 game.exe
 4121  4135   9 10.4 game.exe
 2380  2380  11  4.0 Xorg
 3012  3012   1  1.9 pulseaudio

Sens de la sortie : Montre si vous êtes limité sur un seul thread ou si une pool de workers est chaude.

Décision : Si le TID principal domine, commencer par le coût du thread de rendu et la construction de la frame. Si beaucoup de threads sont chauds, rechercher de la contention ou trop de travail en arrière-plan.

Task 8: Inspect memory pressure that causes stutter (Linux)

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 514232  61244 921440    0    0    12    18  420  980 72  9 19  0  0
 3  0      0 489120  61244 924880    0    0     8    24  500 1100 75  8 17  0  0
 5  1      0  50200  58000 890000    0    0  1200   900  900 3000 65 12 10 13  0

Sens de la sortie : Une augmentation de « b » (bloqué) et des IO « bi/bo » avec peu de mémoire libre peut signifier que le streaming de textures ou le thrash du cache shader tape le disque.

Décision : Si des pics IO coïncident avec des saccades, adresser le streaming d’actifs, l’emplacement du cache shader et les budgets mémoire avant de toucher aux « optimisations » GPU.

Task 9: Confirm disk latency for shader caches and asset streaming (Linux)

cr0x@server:~$ iostat -xz 1 3
Linux 6.8.0 (server) 	01/13/2026 	_x86_64_	(16 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          61.20    0.00    8.10    4.50    0.00   26.20

Device            r/s     w/s   rkB/s   wkB/s  avgqu-sz  await  %util
nvme0n1         120.0    90.0  4800.0  3500.0      2.10  6.20  78.00

Sens de la sortie : « await » de plusieurs ms et %util élevé sous charge peuvent créer des saccades visibles quand la compilation shader ou le streaming touche le stockage.

Décision : Si le stockage est chaud, déplacer les caches sur des médias plus rapides, réduire la compilation runtime ou précompiler. Ne blâmez pas le GPU pour le disque.

Task 10: Check Windows GPU driver resets (TDR) from logs (when analyzing a Windows volume offline)

cr0x@server:~$ grep -R "Display driver" -n /mnt/windows/Windows/Logs/System.evtx.txt | head
1842: Display driver nvlddmkm stopped responding and has successfully recovered.
3229: Display driver nvlddmkm stopped responding and has successfully recovered.

Sens de la sortie : Timeout Detection and Recovery classique : le pilote a réinitialisé le GPU après un blocage.

Décision : Traiter comme un incident de fiabilité : réduire les blocages longs de shader, éviter les charges GPU pathologiques, vérifier les versions de pilotes. Ne pas « juste augmenter TdrDelay » en premier geste.

Task 11: Verify which DLLs a legacy game or wrapper is loading (Windows artifacts inspected from Linux)

cr0x@server:~$ strings -a /mnt/windows/Games/OldTitle/game.exe | egrep -i "glide|d3d|opengl|ddraw" | head
d3d8.dll
ddraw.dll
opengl32.dll
glide2x.dll

Sens de la sortie : Confirme que l’application peut tenter plusieurs backends de rendu, y compris des shims de l’ère Glide.

Décision : Si à la fois Glide et D3D sont présents, assurer que le chemin sélectionné est délibéré ; forcer un backend connu bon pour réduire la variabilité.

Task 12: Measure frame-time stability, not just FPS (using MangoHud in a Linux gaming environment)

cr0x@server:~$ cat ~/.config/MangoHud/MangoHud.conf | egrep "fps|frametime|histogram" 
fps
frametime
histogram

Sens de la sortie : Vous avez activé des métriques qui montrent les pics. Le FPS moyen ment ; les pics de frametime disent la vérité.

Décision : Si l’histogramme des frametimes a de longues queues, prioriser les sources de saccades : compilation de shaders, pagination, points de synchronisation ou pics CPU.

Task 13: Detect shader cache growth and churn (Linux)

cr0x@server:~$ du -sh ~/.cache/mesa_shader_cache ~/.cache/nvidia 2>/dev/null
1.8G	/home/cr0x/.cache/mesa_shader_cache
642M	/home/cr0x/.cache/nvidia

Sens de la sortie : Les caches volumineux peuvent indiquer beaucoup de variantes ; le churn indique des reconstructions qui causent des saccades.

Décision : Si le cache est énorme ou reconstruit fréquemment, réduire le nombre de permutations shader, précompiler ou corriger les déclencheurs d’invalidation du cache (mises à jour de pilote, changements de chemin).

Task 14: Confirm you’re not accidentally running through a translation layer you didn’t intend

cr0x@server:~$ env | egrep "PROTON|DXVK|VKD3D|WINE" | head
PROTON_LOG=1
DXVK_HUD=0
VKD3D_CONFIG=none

Sens de la sortie : L’environnement indique si D3D est traduit (ex. D3D9→Vulkan) ce qui change les profils de performance et de bugs.

Décision : Si vous dépannez un problème D3D natif mais que vous passez par une traduction, arrêtez. Reproduisez d’abord dans la pile correcte.

Feuille de route pour un diagnostic rapide : trouver le goulot sans deviner

Vous voulez une séquence reproductible qui évite le piège classique : « J’ai changé trois choses et c’est mieux, donc je suis un génie. »
Non. Vous avez eu de la chance. Faites plutôt ceci.

Premier : déterminer si c’est un crash, un hang/réinitialisation, ou « juste » des performances

  • Crash : le processus se termine ; vous avez besoin de symboles, de dumps, de reproductions.
  • Hang/réinitialisation (TDR) : gel d’écran, récupération du pilote ; se concentrer sur les tâches GPU longues et la compilation de shaders.
  • Performance : se concentrer sur le temps d’image, pas le FPS ; classifier CPU-bound vs GPU-bound.

Deuxième : classer CPU-bound vs GPU-bound en 2 minutes

  • Vérifier l’utilisation GPU (Tâche 5) et un cœur saturé (Tâches 6/7).
  • Baisser la résolution ou désactiver les post-traitements coûteux.
  • Si baisser la résolution n’aide pas, vous êtes probablement CPU/driver/submit-bound.

Troisième : isoler « saccade » vs « lent »

  • Lent : temps d’image constamment élevé, stable.
  • Saccade : généralement correct, avec des pics périodiques.

La saccade est fréquemment liée au stockage, à la compilation shader, à la pagination ou à la synchronisation (verrous, fences, vsync). Utiliser les Tâches 8–9 et 13.

Quatrième : réduire délibérément votre matrice de test

  • Choisir un pilote connu bon et un pilote connu mauvais.
  • Reproduire sur une machine/profil utilisateur propre (les caches shader comptent).
  • Figerez le backend de rendu (chemin D3D, wrapper, couche de traduction).

Cinquième : seulement alors optimiser

Si vous tunez avant de pouvoir reproduire de manière fiable, vous n’optimisez pas. Vous jouez à la loterie avec des graphiques.

Blague n°2 : Si vous ne pouvez pas reproduire un bug graphique, ce n’est pas un « heisenbug » — c’est « nous n’avons pas encore de banc de test. »

Erreurs courantes : symptôme → cause racine → correction

1) « Ça tourne vite sur mon GPU, les joueurs se plaignent que c’est lent »

Symptôme : Excellente performance sur votre machine dev ; les GPU faibles ramènent la vitesse au ralenti.

Cause racine : Votre contenu suppose un fill-rate et une bande passante ; vous êtes GPU-bound sur les paliers inférieurs.

Correction : Ajouter des réglages évolutifs qui réduisent réellement le coût pixel (scaling de résolution, post-traitement moins coûteux, réduction de l’overdraw). Valider en utilisant l’utilisation GPU (Tâche 5).

2) « Perte de périphérique aléatoire / réinitialisation du pilote après un patch »

Symptôme : Écran noir périodique, message de récupération, ou terminaison de l’appli.

Cause racine : Shaders longs, boucles infinies, ou gros buffers de commandes déclenchant TDR.

Correction : Fractionner le travail en morceaux plus petits ; simplifier ou protéger les shaders ; valider avec des logs (Tâche 10) et reproduire avec les couches de debug si possible.

3) « Saccade à chaque apparition d’un nouvel effet »

Symptôme : Fluide, puis un pic en voyant de nouveaux matériaux/zones.

Cause racine : Compilation shader runtime et misses de cache.

Correction : Précompiler les shaders ; préchauffer les caches ; surveiller la croissance du cache (Tâche 13) et la latence stockage (Tâche 9).

4) « Corruption qui disparaît quand on désactive une optimisation »

Symptôme : Textures/mélanges incorrects, intermittents.

Cause racine : Cache d’état/desynchronisation avec le pilote ; comportement indéfini dépendant d’un état accessoire.

Correction : Rendre l’état du pipeline explicite ; éviter les élisions d’état astucieuses à moins de pouvoir prouver la correction sous toutes les invalidations.

5) « Cassé seulement sur un fournisseur »

Symptôme : Fonctionne sur le fournisseur A, cassé sur le fournisseur B.

Cause racine : Vous dépendez d’un comportement indéfini ou d’un bug/quirk de pilote.

Correction : Utiliser des couches de validation et des tests de conformité ; si c’est un bug fournisseur, construire un repro minimal et expédier un contournement ciblé avec une gate version pilote.

6) « Les performances plongent après mise à jour des pilotes »

Symptôme : Même build, nouveau pilote, pire temps d’image.

Cause racine : Régression dans le compilateur shader, le comportement du cache ou l’ordonnancement.

Correction : Figer les versions de pilote pour la QA et la release ; garder une matrice de compatibilité ; tester « connu bon » vs « dernier ».

7) « Alt-tab casse le rendu ou plante »

Symptôme : Perte de textures, écran noir, crash après changement de focus.

Cause racine : Gestion incorrecte de la perte de périphérique ; ressources non recréées ou référencées incorrectement.

Correction : Implémenter des flux de réinitialisation de périphérique robustes et un suivi explicite de la durée de vie des ressources ; ajouter des tests automatisés pour la perte de périphérique et les changements de mode.

Listes de vérification / plan étape par étape

Checklist A: Expédier un renderer across la diversité des fournisseurs (ce que Direct3D a forcé tout le monde à apprendre)

  1. Définir votre matrice de support. Versions OS, familles GPU et branches de pilote que vous testez et revendiquez.
  2. Figer et archiver. Versions de toolchain, shaders, symboles et artefacts de build par release.
  3. Construire une scène de test graphique reproductible. Chemin caméra déterministe, ordre de chargement des assets déterministe, seeds fixes.
  4. Mesurer le temps d’image. Suivre p50/p95/p99 du temps d’image, pas seulement le FPS moyen.
  5. Budgeter les permutations shader. Si un système de matériaux peut générer 10 000 variantes, il le fera.
  6. Prévoir la perte de périphérique. La traiter comme un événement normal, pas comme une apocalypse.
  7. Gater les contournements. Vérifications de version pilote et IDs fournisseur ; loguer clairement quand un contournement est actif.
  8. Garder un pipeline repro minimal. Quand un bug pilote frappe, vous avez besoin d’une reproduction petite et partageable rapidement.

Checklist B: Debuguer une régression de performance en une semaine, pas un trimestre

  1. Reproduire sur une machine/profil propre.
  2. Confirmer la sélection du backend (Tâches 11/14).
  3. Classifier CPU vs GPU bound (Tâches 5–7).
  4. Vérifier les sources de saccade : mémoire/IO/cache shader (Tâches 8–9/13).
  5. Comparer versions pilote connues-bonnes vs connues-mauvaises.
  6. Bisecter les changements de contenu et de code séparément.
  7. Déployer des atténuations derrière des flags ; mesurer l’impact.
  8. Consigner le résultat en termes opérationnels : ce qui a cassé, pourquoi, comment prévenir la récurrence.

Checklist C: Si vous devez supporter un « chemin rapide » propriétaire (comment le faire sans vous rendre la vie impossible)

  1. Exiger des tests de parité : le chemin rapide doit passer la même suite de correction.
  2. Construire un kill switch : flag de config, override d’environnement, fallback sûr.
  3. Instrumenter la sélection du backend et les infos pilote dans la télémétrie.
  4. Limiter le rayon d’action : activer seulement pour des combos matériel/pilote connus-bons.
  5. Assigner un propriétaire. « Tout le monde » ne corrige rien.

FAQ

1) Glide était-il techniquement meilleur que Direct3D ?

Au sens étroit — se mapper au matériel Voodoo et fournir des performances prévisibles — souvent oui. Au sens plateforme — portabilité, longévité, diversité des fournisseurs — non.
« Meilleur » dépend de votre objectif : performance de pointe sur une cible ou survivabilité sur le marché.

2) Pourquoi les développeurs ont-ils supporté Glide s’il était propriétaire ?

Parce que ça fonctionnait et ça vendait des copies. Si la version la plus belle de votre jeu tournait sur la carte la plus chaude du marché, le marketing vous aimait et les joueurs le voyaient.
À court terme, c’était un choix rationnel.

3) Pourquoi Direct3D a-t-il gagné malgré des premières versions pénibles ?

Distribution et écosystème. Direct3D était livré avec Windows et s’est amélioré avec le temps. Les fournisseurs avaient l’incitation à optimiser leurs pilotes pour lui. Les outils et l’expérience développeur ont rattrapé leur retard.
Glide n’a pas pu survivre au fabricant de son matériel.

4) Où OpenGL se situe-t-il dans cette histoire ?

OpenGL comptait, surtout pour certains moteurs et pour l’héritage workstation. Mais l’élan du jeu Windows grand public, les accords OEM et le bundle DirectX ont poussé D3D dans la voie par défaut.
L’industrie a aussi appris que « standard » n’aide que si les pilotes sont solides et les outils accessibles.

5) Quel est l’équivalent moderne de Glide ?

Extensions spécifiques au fournisseur, upscalers propriétaires et APIs ou fonctionnalités exclusives à une plateforme. Elles peuvent être excellentes. Elles portent aussi un risque plateforme.
Utilisez-les derrière des vérifications de capacité et avec un fallback propre.

6) Direct3D est-il intrinsèquement plus stable que les API propriétaires ?

Pas intrinsèquement. La stabilité vient de l’investissement de l’écosystème, de la validation et de la discipline opérationnelle.
Les API standard ont tendance à attirer plus d’effort de conformité et de tests larges, ce qui aide généralement avec le temps.

7) Si je débogue des saccades, pourquoi parlez-vous sans cesse de stockage ?

Parce que la saccade est fréquemment « le GPU a attendu autre chose ». La compilation shader, la pagination et le streaming touchent souvent le disque.
Si vos pics de temps d’image coïncident avec des IO ou des reconstructions de cache, votre goulot n’est pas le GPU — c’est le pipeline autour.

8) Dois-je figer les versions de pilote GPU en production ?

Oui, si vous tenez à la prévisibilité. Figer pour des configurations validées, et tester « latest » séparément pour planifier les mises à jour au lieu d’être surpris par elles.
C’est particulièrement important pour la visualisation entreprise, les environnements esports et les kiosques.

9) Quelle est la meilleure manière d’éviter le retour de bâton du « state shadowing » ?

Traiter l’état de pipeline explicite comme source de vérité. Quand vous devez mettre en cache, assurez-vous de pouvoir invalider correctement sur chaque événement important : perte de périphérique, éviction de ressource, changements de contexte et comportements du pilote.
Si vous ne pouvez pas modéliser l’invalidation, ne prétendez pas pouvoir le faire.

10) Que faire si le problème ne se reproduit que sur le pilote d’un seul fournisseur ?

D’abord, supposez que vous dépendez d’un comportement indéfini. Validez, réduisez à un repro minimal, puis seulement ensuite déposez un bug pilote.
En parallèle, expédiez un contournement gateé par fournisseur + version pilote avec un logging propre pour pouvoir le retirer plus tard.

Prochaines étapes qui ne vous feront pas perdre la semaine

Glide vs Direct3D n’était pas seulement une guerre d’API ; c’était un aperçu de la façon dont les plateformes gagnent. La plateforme qui réduit la douleur opérationnelle à long terme gagne, même si elle est maladroite au départ.
Glide a produit la meilleure version d’un jeu sur une classe de matériel. Direct3D l’a rendu expédiable sur tout le marché PC.

Si vous construisez ou maintenez aujourd’hui une pile de rendu, prenez au sérieux les leçons ennuyeuses :

  • Décidez votre matrice de support et faites-la respecter avec des pilotes figés et des builds reproductibles.
  • Instrumentez le temps d’image et classez rapidement les goulots avec la feuille de route.
  • Construisez un banc repro minimal pour les bugs pilotes — le vous du futur remerciera le vous du présent.
  • Utilisez les chemins rapides propriétaires avec précaution : gateés, testés et avec un kill switch.

L’argument des années 1990 était « rapide vs compatible ». L’argument moderne est « rapide vs opérable ».
Choisissez opérable d’abord. Puis rendez-le rapide.

← Précédent
Vitesse de restauration Proxmox : réglages PBS, choix de compression et pourquoi les restaurations sont lentes
Suivant →
Proxmox VFIO « device is in use » : détacher correctement les périphériques PCI de l’hôte

Laisser un commentaire