Vous n’avez pas vraiment rencontré les « graphismes » tant que vous n’avez pas vu un curseur se traîner sur l’écran comme s’il tirait un canapé en montée.
Dans le monde pré-NVIDIA, le goulot d’étranglement n’était pas un bug exotique de shader. C’était vous, un CPU, un bus mémoire et un bloc de RAM
mappé à l’écran.
C’est l’époque où un « sous-système graphique » pouvait signifier : un contrôleur CRT, une palette, une organisation en bitplanes à ne pas mal interpréter,
et un pilote qui faisait parfois plus d’improvisation artistique que de rendu. Si vous exploitez des systèmes en production aujourd’hui, vous reconnaîtrez les schémas :
limites de bande passante cachées, métriques trompeuses et « optimisations » qui déplacent le problème d’un goulot d’étranglement à un autre.
Ce que « graphismes » signifiait avant les GPU
Aujourd’hui « graphismes » implique un pipeline : shaders, textures, buffers de commandes, VRAM et une pile de pilotes à mi-chemin entre noyau et magie noire.
Avant que NVIDIA ne popularise le mot « GPU », les « graphismes » consistaient surtout à mettre des pixels dans un frame buffer assez vite pour que les humains
ne remarquent pas que vous simuliez le mouvement.
La plupart des systèmes vivaient dans l’un des trois mondes suivants :
-
Mode texte faisant semblant d’être graphique. Cellules de caractères, ROM de polices et peut-être des caractères blocs pour l’interface.
Peu coûteux, fiable et rapide parce que l’on déplaçait des octets, pas des pixels. -
Bitmaps 2D avec accélération minimale. Un frame buffer en VRAM ; dessiner signifiait copier des rectangles, tracer des lignes
et remplir des régions. Si vous aviez un blitter, vous viviez confortablement. -
3D comme taxe spécialisée. Stations de travail avec cartes d’extension coûteuses ou pipelines propriétaires. Sur les PC grand public,
la « 3D » voulait souvent dire rendu logiciel : mathématiques astucieuses, astuces en virgule fixe et acceptation.
Le fil conducteur : bouger de la mémoire. Le « rendu » n’était pas un débat philosophique. C’était « combien d’octets puis-je pousser par image »
et « combien de fois touche-t-on chaque pixel ».
Si vous voulez le modèle mental central, le voilà : les graphismes pré-GPU, c’est de l’IO.
Votre écran est un dispositif mémoire lu en continu. Votre travail est de mettre à jour cette mémoire sans buter sur le bus, le cache CPU
ou le timing de rafraîchissement de l’affichage.
Faits concrets et contexte historique
Quelques points courts et marquants qui expliquent pourquoi le logiciel était écrit de cette façon :
API, formats de fichiers, bibliothèques UI et folklore de performance ne sortaient pas de nulle part.
-
Le VGA d’IBM (1987) a standardisé 640×480 avec 16 couleurs et un mode 320×200 en 256 couleurs.
Le mode 320×200×8bpp est devenu le canevas par défaut des jeux parce que c’était un point d’équilibre pour la vitesse et la mémoire. -
Le « Mode 13h » (320×200, 256 couleurs) sur DOS mappeait la VRAM linéairement.
L’adressage linéaire permettait au CPU d’écrire des pixels avec une arithmétique de pointeurs simple—pas de gymnastique planaire. -
Les modes planaires étaient courants et pénibles.
En modes VGA 16 couleurs, les pixels étaient répartis sur des bitplanes. Un seul écrit de pixel pouvait nécessiter un read-modify-write sur plusieurs plans.
Cela a façonné tout, des moteurs de sprite à l’apparence de certaines polices. -
Les VESA BIOS Extensions (VBE) ont rendu possibles des résolutions plus élevées sous DOS.
Ce n’était pas du « plug and play » ; c’était « si vous avez de la chance et si le firmware de la carte se comporte ». -
L’accélération 2D initiale portait sur les rectangles, pas les triangles.
BitBLT (bit block transfer), tracé de lignes matériel et curseurs matériels importaient plus que tout ce qui touchait à la « 3D ». -
Le bus était le destin : ISA vs VLB vs PCI.
La bande passante et la latence d’ISA limitaient les écritures au frame buffer ; VLB et PCI ont rendu pratique la graphique à plus haut débit en alimentant la VRAM plus rapidement. -
Les palettes de couleurs étaient une fonctionnalité de performance.
La couleur indexée 8 bits signifiait qu’un buffer plein pouvait tenir dans ~64 Ko (320×200) ou ~300 Ko (640×480), assez petit pour l’époque.
Le cycling de palette permettait d’animer sans toucher la plupart des pixels. -
Les accélérateurs 3D initiaux étaient des aides à fonctions fixes.
Les premières cartes 3D grand public accéléraient le mapping de textures et l’organisation de triangles ; le CPU faisait encore beaucoup, notamment la logique de jeu et les transformations. -
Le double buffering n’était pas « gratuit ».
Avoir deux buffers complets signifiait doubler l’usage de VRAM et augmenter la bande passante de copie. Beaucoup de systèmes utilisaient des dirty rectangles à la place.
Le vieux pipeline : du CPU au phosphore
1) Le frame buffer n’était pas une métaphore
Une pile de pilotes GPU moderne queue du travail ; le GPU le récupère et écrit en VRAM avec un parallélisme interne massif.
Dans l’ancien monde, le CPU était le moteur de rendu. Si vous vouliez qu’un pixel s’allume, vous écriviez à l’adresse qui représentait ce pixel.
Le contrôleur d’affichage scannait la VRAM en continu et générait le signal vidéo.
Cet agencement créait une vérité simple mais impitoyable : la performance graphique était la performance mémoire.
Pas seulement de la « RAM rapide », mais où la RAM se trouvait et combien il était coûteux d’y accéder.
De la VRAM derrière un bus lent, c’est comme un bucket S3 accédé par modem : techniquement correct, pratiquement cruel.
2) Ce que « accélération » signifiait
L’accélération pré-GPU signifiait généralement une puce capable de :
- copier un rectangle d’une zone de VRAM vers une autre (BitBLT)
- remplir un rectangle avec une couleur unie
- dessiner des lignes
- supporter un curseur matériel en overlay (pour que la souris ne déchire pas ou ne lag pas)
C’était énorme. Si vous pouvez copier des rectangles en matériel, vous pouvez faire défiler des fenêtres, déplacer des sprites et redessiner des éléments d’UI
sans dévorer le CPU. C’est la même raison pour laquelle les systèmes modernes aiment le DMA : les moteurs de copie libèrent le calcul pour le vrai travail.
3) Pourquoi les formats de pixels obsédaient les gens
Les formats de pixels n’étaient pas esthétiques ; ils étaient de la survie. Choisir 8bpp indexé réduit l’empreinte mémoire et la bande passante.
Choisir 16bpp (souvent 5-6-5 RGB) augmente la bande passante mais simplifie le shading et évite les astuces de palette. Choisir 24bpp,
c’est demander au bus de faire du cardio.
Et les formats n’étaient pas toujours linéaires. Dispositions planaires, frame buffers bancés (où vous changez quel morceau de VRAM est visible),
et contraintes d’alignement faisaient qu’un simple « boucle sur les pixels » naïf pouvait être catastrophiquement lent.
4) Le tearing et la tyrannie du rafraîchissement
Le contrôleur d’affichage lit la VRAM à un rythme fixe. Si vous écrivez dans la VRAM pendant qu’il la balaye, vous pouvez voir des images à moitié mises à jour :
tearing. La bonne correction est la synchronisation—attendre le blank vertical ou utiliser le page flipping. La correction coûteuse est la copie.
La correction bon marché est « ne pas redessiner trop et espérer que personne ne remarque ».
Les systèmes qui géraient ça correctement paraissaient magiques. Les autres faisaient l’impression que vos yeux faisaient du débogage.
Blague #1 : À l’époque, « rendu temps réel » voulait dire « rendu à temps pour la prochaine réunion ». Parfois, ça marchait pour les deux.
Où le temps partait : goulots d’étranglement perceptibles
Bande passante : le budget silencieux
Si vous voulez une règle pratique pour les graphismes à l’ancienne, calculez votre budget d’écriture brut.
Un écran 640×480 en 8bpp fait ~300 Ko. À 60 fps c’est ~18 Mo/s juste pour écrire une image complète—sans compter les lectures,
sans compter l’overdraw, sans compter les blits, et sans compter tout le reste que font le CPU et le bus.
Sur le papier cela semble modeste aujourd’hui. Dans le contexte, c’était fréquemment toute la machine.
Les anciens bus, caches et contrôleurs mémoire pouvaient transformer ces « 18 Mo/s » en fantasme une fois que l’on ajoute contention et états d’attente.
C’est pourquoi le redraw partiel (dirty rectangles) n’était pas un micro-optimisation ; c’était la différence entre utilisable et insultant.
Latence : pourquoi un seul pixel pouvait être coûteux
La VRAM derrière un bus peut avoir des motifs d’accès atroces. Les écritures séquentielles peuvent aller ; les écritures dispersées deviennent un cauchemar.
Vous voyez ça dans les moteurs de sprites logiciels : ils batchent, ils alignent, ils préfèrent des spans. Ils font tout pour transformer des écritures aléatoires en écritures linéaires.
Overdraw : peindre le même pixel plusieurs fois
Dans un moteur logiciel, chaque fois que vous touchez un pixel vous payez. Si votre toolkit UI redessine toute la fenêtre pour un curseur clignotant,
ce n’est pas un « bug d’UI ». C’est un problème de débit. Même dans les jeux : si vous dessinez l’arrière-plan, puis les sprites, puis redessinez l’UI,
le même pixel peut être écrit trois fois.
L’instinct correct à l’époque était : minimiser les touches. Peindre une fois. Cacher agressivement. Clipper sans pitié.
Parfois, la meilleure technique de rendu était « ne pas rendre ».
Cycles CPU : mathématiques vs mémoire
Les anciens débats sur le rendu (« utiliser la virgule fixe », « pré-calculer des tables », « éviter les divisions ») n’étaient pas académiques.
Les CPU étaient assez lents pour que les mathématiques dominent. Mais souvent c’était l’inverse : le CPU pouvait calculer plus vite qu’il n’écrivait
dans le frame buffer. C’est là que l’on voit des astuces comme dessiner dans un buffer en mémoire système puis copier en blocs plus grands.
Ça semble gaspiller — jusqu’à ce que vous vous rappeliez que les caches existent et que les bus ne pardonnent pas.
Pilotes : la couche mince entre vous et la douleur
Sous DOS, vous appeliez le BIOS ou accédiez directement aux registres. Sous les premières versions de Windows ou X11,
vous faisiez confiance à un modèle de pilote qui pouvait avoir été écrit par un fournisseur dont le KPI principal était « boote la plupart du temps ».
Dans les stations de travail (SGI, Sun, HP), l’intégration était souvent meilleure—aux prix des stations de travail.
En termes opérationnels : la fiabilité de vos graphismes était un problème de chaîne d’approvisionnement.
Votre « correction de rendu » dépendait du firmware, des timings du bus et des bizarreries du chipset.
L’angle fiabilité : les graphismes comme dépendance opérationnelle
On oublie combien les « graphismes » étaient critiques en entreprise :
salles de trading, stations CAO, imagerie médicale, bornes, centres d’appels. Si l’UI laggait, l’entreprise laggait.
Si l’écran passait au noir après une suspension/reprise, le support avait une nouvelle passion.
Une pile graphique pré-GPU est une parabole SRE : falaises de performance, pannes partielles, limites non évidentes,
et interactions compliquées entre matériel et logiciel. Vous ne « l’ajustez pas une fois ». Vous la gardez stable.
Une citation, parce qu’elle s’applique à toutes les ères de systèmes et à tout écran qui a déjà hoqueté :
L’espoir n’est pas une stratégie.
— idée paraphrasée souvent évoquée en opérations ; considérez-la comme un rappel, pas une citation.
Trois mini-récits d’entreprise depuis le terrain
Mini-récit 1 : L’incident causé par une mauvaise hypothèse (profondeur de couleur vue comme « juste un réglage »)
Un tableau de bord logistique interne a été déployé sur quelques centaines de thin clients et de bureaux reconditionnés.
C’était surtout du 2D : graphiques, grilles et un widget de carte. Le déploiement s’est bien passé dans le pilote — machines récentes, graphique PCI décent,
suffisamment de RAM. Puis il est arrivé sur le plancher d’entrepôt.
Le symptôme était étrangement humain : les travailleurs se plaignaient que l’UI « collait ». Les mouvements de souris étaient retardés, le défilement saccadait,
et après quelques minutes l’application « rattrapait » son retard par à-coups. Elle ne plantait pas. Elle se figait simplement.
Le support a essayé l’habituel : réinstaller, redémarrer, changer la souris, blâmer le réseau. Rien de consistant.
La mauvaise hypothèse était que passer de 16 bits à 32 bits de couleur était une amélioration cosmétique sans conséquence.
La nouvelle build activait par défaut le 32bpp parce que c’était plus net sur les écrans modernes et évitait le banding sur les dégradés.
Sur les machines anciennes, les écritures du frame buffer ont doublé, et le pilote est retombé de chemins 2D accélérés à un chemin logiciel lent
pour certaines opérations en 32bpp.
Le comble : l’application redessinait de larges régions à chaque tick de minuteur — acceptable en 16bpp sur le matériel pilote, catastrophique en 32bpp sur des restes époque ISA.
Vous pouviez voir l’utilisation CPU rester modérée tandis que le bus s’étouffait ; le thread UI n’était pas saturé, il était bloqué sur des écritures lentes et des appels pilote.
La correction n’était pas héroïque. Ils ont verrouillé la flotte en 16bpp sur ces endpoints, patché l’app pour réduire les régions à redessiner,
et ajouté un contrôle de démarrage qui refusait d’activer les « beaux dégradés » sauf si un petit benchmark passait.
La leçon : les « réglages » font partie du contrat de performance. Traitez-les comme un changement de schéma.
Mini-récit 2 : L’optimisation qui a échoué (double buffering partout)
Une équipe produit de bornes voulait des animations plus fluides : pas de tearing, pas de scintillement. Ils ont fait ce que dit tout article :
implémenter le double buffering. Rendre dans un buffer hors-écran, puis blitter vers l’écran. Propre. Prévisible. Moderne.
Ils l’ont expédié, fiers du nouvel aspect.
Deux semaines plus tard, les rapports du terrain arrivent : arrêts aléatoires, images noires occasionnelles et une lente dérive vers le lag après plusieurs heures.
Les appareils avaient une RAM modeste et un graphique intégré partageant la bande passante mémoire avec le CPU. Les bornes faisaient aussi du travail en arrière-plan :
journal local, uploads occasionnels et décodage d’images.
Le double buffering a transformé de petites mises à jour incrémentales en copies d’image complète. L’ancien code utilisait des dirty rectangles ;
il ne redessinait que ce qui changeait. Le nouveau code rendait toujours la scène complète (même l’arrière-plan statique) dans le back buffer
puis copiait le tout vers le front. La bande passante a explosé. La pression cache a augmenté. Et quand la mémoire s’est resserrée,
le paging a commencé à grignoter les bords.
Pire : leur appel « blit to screen » n’utilisait pas toujours l’accélération matérielle sur certains chipsets. En labo c’était rapide ;
sur le terrain il retombait parfois sur un chemin plus lent, spécialement à certaines profondeurs de couleur. L’optimisation était correcte en théorie,
et fausse en déploiement.
Ils ont annulé le double buffering universel et mis en place un hybride :
double buffering seulement pour la région animée, garder les dirty rectangles pour le reste, et ajouter un watchdog qui détecte quand les blits
ralentissent et dégrade l’animation en douceur. Ils ont aussi épinglé l’usage mémoire pour éviter le swapping.
La leçon : une image plus lisse n’a de valeur que si vous pouvez la soutenir. N’optimisez pas pour l’esthétique sans mesurer le bus.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise (capture de baseline + rollback)
Un département financier exécutait une application X11 legacy sur des thin clients Linux depuis des années. Ce n’était pas joli, mais c’était stable.
L’équipe responsable des endpoints avait une habitude qui paraissait excessivement conservatrice : avant toute mise à jour de pilote, ils capturaient une baseline
des IDs hardware, modules kernel, logs Xorg et métriques 2D basiques. Puis ils stockaient tout ça avec la demande de changement.
Un fournisseur a poussé une « mise à jour de sécurité » incluant un rafraîchissement de la pile graphique. Après le déploiement sur un sous-ensemble, des utilisateurs ont signalé que les déplacements de fenêtres
laissaient des traînées et que le texte redessinait lentement. Pas tout le monde — seulement certains modèles. Le support a commencé à collecter des captures d’écran. Les ingénieurs ont commencé à deviner.
C’est ainsi que le temps meurt.
L’équipe endpoint a comparé les nouveaux logs avec leur baseline. Ils ont immédiatement vu que l’accélération était désactivée sur les unités affectées :
le module du pilote avait changé, mais ces clients avaient une révision PCI légèrement différente. La nouvelle pile les traitait comme non supportés et retombait
sur un pilote framebuffer générique.
Parce qu’ils avaient des baselines, ils n’ont pas eu besoin d’une salle de crise. Ils ont rollbacké le paquet graphique pour ces modèles, épinglé les versions,
et ouvert un ticket fournisseur avec des preuves précises : mismatch de module, chemin de fallback, et étapes reproductibles.
La leçon : l’instrumentation ennuyeuse bat le débogage héroïque. Les baselines ne sont pas de la paperasse ; ce sont des voyages dans le temps.
Blague #2 : Rien ne remonte le moral d’équipe comme découvrir que votre « régression de performance » est en fait « on a désactivé l’accélération ». C’est comme réparer une fuite en réouvrant l’eau.
Tâches pratiques : commandes, sorties et ce que signifie la sortie
Ces tâches supposent que vous diagnostiquez une voie graphique de type legacy sur Linux : framebuffer, X11 ou DRM/KMS basique.
Même si vous n’exécutez pas du matériel rétro, les mêmes vérifications exposent les modes d’échec classiques : pilotes de fallback, accélération désactivée,
saturation de bande passante et tempêtes de redraw.
Tâche 1 : Identifier le GPU / contrôleur graphique
cr0x@server:~$ lspci -nn | egrep -i 'vga|3d|display'
00:02.0 VGA compatible controller [0300]: Intel Corporation 82865G Integrated Graphics Controller [8086:2572] (rev 02)
Signification : Vous n’êtes plus en supposition ; vous avez les IDs vendeur et device.
Décision : Cherchez quel pilote devrait être lié (i915, nouveau, mga, etc.). Si vous voyez un contrôleur intégré ancien,
supposez une bande passante mémoire partagée et des chemins d’accélération fragiles.
Tâche 2 : Voir quel pilote kernel est réellement lié au périphérique
cr0x@server:~$ lspci -k -s 00:02.0
00:02.0 VGA compatible controller: Intel Corporation 82865G Integrated Graphics Controller (rev 02)
Subsystem: Dell Device 0163
Kernel driver in use: i915
Kernel modules: i915
Signification : « Kernel driver in use » est la vérité. « Kernel modules » indique ce qui pourrait être utilisé.
Décision : Si ça indique vesafb ou fbdev alors que vous attendez un driver DRM natif, vous êtes probablement sur un chemin lent.
Tâche 3 : Confirmer l’état DRM/KMS et détecter un fallback vers simpledrm
cr0x@server:~$ dmesg | egrep -i 'drm|fb0|simpledrm|vesafb' | tail -n 12
[ 1.234567] simpledrm: framebuffer at 0xe0000000, 0x300000 bytes
[ 1.234890] simpledrm: format=a8r8g8b8, mode=1024x768x32, linelength=4096
[ 2.101010] [drm] Initialized i915 1.6.0 20201103 for 0000:00:02.0 on minor 0
Signification : Le démarrage peut commencer avec simpledrm puis passer à un vrai pilote. C’est normal.
Décision : Si vous ne voyez jamais le vrai pilote initialiser, vous êtes coincé sur un framebuffer générique. Attendez-vous à de mauvaises performances 2D.
Tâche 4 : Vérifier Xorg pour voir si l’accélération est désactivée
cr0x@server:~$ grep -E "(EE|WW|Accel|glamor|uxa|sna)" /var/log/Xorg.0.log | tail -n 20
[ 22.123] (II) modeset(0): glamor X acceleration enabled on Mesa DRI Intel(R) 865G
[ 22.125] (WW) modeset(0): Disabling glamor because of old hardware
[ 22.126] (II) modeset(0): Using shadow framebuffer
Signification : « shadow framebuffer » est le code pour « le logiciel fera des copies supplémentaires ».
Décision : Sur du matériel ancien cela peut être inévitable ; dans ce cas réduisez le redraw et la profondeur de pixel. Sur du matériel plus récent, c’est une mauvaise configuration.
Tâche 5 : Vérifier quel renderer OpenGL vous obtenez (matériel vs logiciel)
cr0x@server:~$ glxinfo -B | egrep 'OpenGL vendor|OpenGL renderer|OpenGL version'
OpenGL vendor string: Mesa
OpenGL renderer string: llvmpipe (LLVM 15.0.7, 256 bits)
OpenGL version string: 4.5 (Compatibility Profile) Mesa 23.0.4
Signification : llvmpipe signifie rendu logiciel. Votre CPU est maintenant le GPU.
Décision : Si vous attendiez l’accélération matérielle, arrêtez d’optimiser l’app et corrigez la pile de pilotes. Si vous acceptez le rendu logiciel,
contraignez la résolution/les effets et budgetez le CPU en conséquence.
Tâche 6 : Voir si le rendu direct est activé
cr0x@server:~$ glxinfo | grep -i "direct rendering"
direct rendering: Yes
Signification : « Yes » suggère que DRI fonctionne, mais cela ne garantit pas la performance (cela peut toujours être logiciel).
Décision : Associez-le à la chaîne du renderer. Si le rendu direct est « No », attendez-vous à une lenteur sévère et du tearing.
Tâche 7 : Confirmer le mode courant (résolution + rafraîchissement)
cr0x@server:~$ xrandr --current
Screen 0: minimum 320 x 200, current 1024 x 768, maximum 8192 x 8192
VGA-1 connected primary 1024x768+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
1024x768 60.00*+
800x600 60.32
640x480 59.94
Signification : Vous avez 1024×768@60. C’est le budget brut de pixels que vous devez redessiner.
Décision : Si la performance est mauvaise, baissez la résolution ou la profondeur de couleur d’abord. C’est le levier le plus rapide avec l’effet le plus grand.
Tâche 8 : Vérifier si le kernel rapporte des hangs ou resets GPU
cr0x@server:~$ dmesg | egrep -i 'hang|reset|gpu|ring|fault' | tail -n 20
[ 912.332100] i915 0000:00:02.0: GPU HANG: ecode 9:1:0x85dffffb, in Xorg [1234]
[ 913.001234] i915 0000:00:02.0: Resetting chip for hang on rcs0
Signification : Vous n’êtes pas face à de la « lenteur » ; vous avez une instabilité qui provoque des arrêts.
Décision : Réduisez les fonctionnalités d’accélération, essayez un pilote plus ancien/plus récent, ou changez la charge (désactivez la composition).
Ne colmatez pas ça côté application avec des sleeps.
Tâche 9 : Mesurer la saturation CPU et les changements de contexte pendant un lag UI
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 512000 42000 320000 0 0 1 2 180 300 25 10 65 0 0
5 1 0 98000 41000 250000 0 0 0 120 900 3200 65 20 10 5 0
4 2 20480 12000 20000 120000 20 40 10 600 1200 5000 70 15 5 10 0
Signification : Un r qui augmente, un id faible et des si/so non nuls indiquent contention et swapping.
Décision : Si le swap démarre, corrigez d’abord la pression mémoire (baisser la résolution, désactiver la composition, réduire les caches ou ajouter de la RAM).
Le swapping transforme « graphismes » en « systèmes distribués », et pas de façon agréable.
Tâche 10 : Identifier la pression sur la bande passante mémoire (proxy rapide via perf)
cr0x@server:~$ sudo perf stat -a -e cycles,instructions,cache-misses,context-switches -d -- sleep 5
Performance counter stats for 'system wide':
12,345,678,901 cycles
6,789,012,345 instructions # 0.55 insn per cycle
234,567,890 cache-misses
12,345 context-switches
5.001234567 seconds time elapsed
Signification : Un IPC bas plus des cache misses élevés pendant un hoquet est cohérent avec un rendu lié à la mémoire ou des chemins riches en copies.
Décision : Réduisez le touchage de pixels (dirty rectangles), réduisez la profondeur de couleur et évitez les blends par pixel qui forcent des lectures.
Tâche 11 : Vérifier l’état du compositeur (une taxe cachée fréquente)
cr0x@server:~$ ps -ef | egrep -i 'picom|compton|mutter|kwin_x11' | grep -v grep
cr0x 1888 1 5 10:01 ? 00:02:11 picom --config /home/cr0x/.config/picom.conf
Signification : Un compositeur peut transformer de simples copies 2D en textures mélangées et buffering supplémentaire.
Décision : Sur des GPU faibles/anciens ou en rendu logiciel, désactivez la composition. Si vous en avez besoin, ajustez-la (vsync off/on, ombres off).
Tâche 12 : Capturer un benchmark X11 léger (vérification de bon sens)
cr0x@server:~$ x11perf -copywinwin500 | head -n 20
x11perf: description: local server
x11perf: drawing to window 500x500
CopyWinWin500 200 reps @ 4.50 msec ( 444.4/sec): Copy 500x500 from window to window
Signification : Cela approximera la vitesse à laquelle le système peut copier un rectangle modéré—exactement ce que font les UI 2D à l’ancienne.
Décision : Comparez entre machines ou avant/après changements. Si c’est un ordre de grandeur plus lent après une mise à jour, suspectez un fallback pilote.
Tâche 13 : Vérifier les détails du périphérique framebuffer (lorsque vous êtes vraiment en fbdev)
cr0x@server:~$ cat /sys/class/graphics/fb0/virtual_size
1024,768
Signification : Confirme la taille virtuelle du framebuffer ; utile quand les apps supposent un mode mais que le kernel en a choisi un autre.
Décision : Si cela ne correspond pas à votre mode attendu, corrigez le KMS mode setting ou la config Xorg avant de toucher l’app.
Tâche 14 : Vérifier la liste des modules kernel pour des framebuffers en conflit
cr0x@server:~$ lsmod | egrep 'i915|nouveau|radeon|amdgpu|vesafb|simpledrm|fbdev' | head
i915 3121152 3
drm_kms_helper 315392 1 i915
drm 622592 4 drm_kms_helper,i915
simpledrm 20480 1
Signification : Plusieurs drivers framebuffer peuvent coexister, mais des conflits peuvent vous coincer sur un driver générique.
Décision : Si vesafb est chargé aux côtés d’un vrai DRM et que vous voyez des problèmes, blacklistiez le générique prudemment et testez.
Tâche 15 : Détecter les « tempêtes de redraw » causées par une app (trafic X11 élevé)
cr0x@server:~$ xrestop -b | head -n 12
res-base win pix GC col fnt pmap other total PID Login Name
36 12 820 18 12 2 0 45 945 2444 cr0x legacy-dashboard
22 8 120 10 6 1 0 18 177 1888 cr0x picom
Signification : L’augmentation des pixmaps et ressources peut indiquer un buffering offscreen excessif ou des fuites qui dégradent la performance au fil du temps.
Décision : Si les pixmaps d’une app montent indéfiniment, traitez cela comme une fuite mémoire ; une politique de redémarrage ou un patch est justifié.
Tâche 16 : Vérifier l’IO disque et la pression de journalisation (parce que swap et journaux arrivent)
cr0x@server:~$ iostat -xz 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
35.21 0.00 12.10 9.88 0.00 42.81
Device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await %util
sda 2.00 45.00 64.00 980.00 45.16 0.90 19.50 92.00
Signification : Un %util et un await élevés indiquent que le disque est occupé ; si l’UI lagge, vous pourriez être en paging ou lié aux logs.
Décision : Arrêtez la fuite IO : réduisez la verbosité des logs, déplacez-les, ajoutez de la RAM ou réparez le disque. Les graphismes n’existent pas en isolation.
Méthode de diagnostic rapide
Quand un système « semble lent », la façon la plus rapide de perdre du temps est de discuter des impressions.
Lancez ce qui suit dans l’ordre et vous identifierez généralement la classe de goulot d’étranglement en moins de 10 minutes.
Première étape : confirmez que vous n’êtes pas sur un pilote de fallback
- Exécutez
lspci -ket vérifiez que le pilote kernel attendu est en use. - Vérifiez
dmesgpoursimpledrm/vesafbuniquement, sans initialisation DRM correcte. - Vérifiez
glxinfo -Bet voyez si vous êtes surllvmpipe.
Si vous êtes sur un fallback : arrêtez. Corrigez cela en premier. Tout le reste, c’est du vernis sur un framebuffer.
Deuxième étape : isolez si vous êtes CPU-bound, mémoire-bound ou IO-bound
vmstat 1pendant la reproduction du lag : cherchez unus/syélevé (CPU), unsi/soélevé (swap), unwaélevé (IO wait).iostat -xz 1si swap ou IO wait apparaît.perf statcomme signal rapide pour les cache misses et un IPC faible sous charge.
Décision : Si vous swappez ou êtes IO-bound, corrigez la mémoire/disque en premier. Si le CPU est saturé, réduisez la charge de rendu logiciel ou activez l’accélération.
Si les cache misses grimpent, réduisez le touchage de pixels et les copies.
Troisième étape : réduisez sans pitié le budget de pixels
- Baissez la résolution (
xrandr), puis testez à nouveau. - Réduisez la profondeur de couleur si possible (les stacks legacy le permettent encore ; les modernes moins).
- Désactivez la composition et les « effets lissés ».
Décision : Si la performance s’améliore immédiatement, votre goulot est la bande passante / les copies, pas la « logique applicative ».
Quatrième étape : validez les motifs de redraw
- Utilisez
x11perfpour un check rapide des opérations 2D. - Surveillez la croissance des ressources avec
xrestoppour détecter fuites ou buffering excessif.
Décision : Si l’app génère des tempêtes de redraw, corrigez l’invalidation et le clipping de l’app au lieu de courir après les flags du pilote.
Erreurs courantes (symptôme → cause → correction)
1) La souris bouge mais les fenêtres « collent » pendant le glissement
Symptôme : Le curseur reste réactif ; le drag de fenêtre laisse des traînées ; le redraw se fait par blocs.
Cause : Le overlay du curseur matériel fonctionne, mais l’accélération 2D est désactivée ; les mises à jour sont des copies logicielles via shadow framebuffer.
Correction : Confirmez le binding du pilote ; désactivez le compositeur ; réduisez la profondeur de couleur/résolution ; assurez-vous du bon pilote Xorg (modesetting vs vendor).
2) Fluide en labo, lent sur le terrain
Symptôme : Même logiciel ; sites différents ; seulement certaines machines rampent.
Cause : Révisions de périphérique ou firmware différents ; le pilote retombe sur certains PCI IDs ; ou mémoire insuffisante causant du swap.
Correction : Inventaire des hardware IDs ; comparer les logs Xorg ; épingler des versions de pilotes connues bonnes par modèle ; imposer une RAM minimale.
3) « Visuels améliorés » provoquent des saccades sans CPU élevé
Symptôme : L’UI saccade ; le CPU n’est pas saturé ; l’utilisateur dit que c’est « collant ».
Cause : Saturation du bus/VRAM ; augmentation du trafic mémoire due à une bpp plus élevée et au blending alpha ; threads bloqués dans des appels pilotes.
Correction : Réduisez la bpp/les effets ; clippez les régions à redessiner ; remplacez les blends par pixel par des assets précomposés ; adoptez des dirty rectangles.
4) Images noires aléatoires ou scintillement après activation du double buffering
Symptôme : Blancs périodiques, surtout sous charge ; parfois seulement sur certains moniteurs.
Cause : Les blits d’image complète ratent le timing de rafraîchissement ; le page flipping n’est pas supporté de façon fiable ; pression VRAM provoque des échecs d’allocation.
Correction : Buffering hybride : ne bufferisez que les régions animées ; utilisez vsync/page-flip seulement quand supporté ; réduisez la résolution ; limitez la fréquence d’images.
5) La performance se dégrade sur plusieurs heures
Symptôme : Démarre bien ; devient progressivement lent ; un reboot « règle » le problème.
Cause : Fuite de ressources (pixmaps, surfaces offscreen), creep de swap, croissance IO de logs, ou ballooning du cache du compositeur.
Correction : Suivez les ressources (xrestop), la mémoire (vmstat), le disque (iostat) ; implémentez une politique de redémarrage ; corrigez les fuites.
6) Tearing visible sur animations et défilement
Symptôme : Lignes de déchirure horizontales lors des mouvements.
Cause : Pas de vsync/page flipping ; écritures directes sur le front buffer ; compositeur désactivé ou mal configuré.
Correction : Activez le vsync quand il est supporté ; utilisez la composition sur du matériel capable ; ou réduisez le mouvement/le coût de rafraîchissement si le matériel ne suit pas.
7) « Nous avons activé l’accélération » mais tout a empiré
Symptôme : Augmentation de l’utilisation CPU, réactivité en baisse après le changement de pilote.
Cause : Le chemin d’accélération déclenche des fallback coûteux (ex. opérations non supportées forcent des readbacks) ; mismatch Mesa/driver.
Correction : Validez le renderer réel (glxinfo -B) ; essayez une méthode d’accélération alternative (UXA/SNA/glamor selon la pile) ;
gardez les versions cohérentes ; préférez moins de fonctionnalités à des fonctionnalités buggy.
Listes de contrôle / plan étape par étape
Étape par étape : stabiliser un environnement graphique legacy
-
Inventaire du matériel. Capturez
lspci -nnet stockez-le avec le profil machine.
Pourquoi : Les révisions se comportent différemment ; vous ne pouvez pas gérer ce que vous ne nommez pas. -
Verrouillez des pilotes connus bons par classe matérielle.
Pourquoi : Les piles graphiques régressent. Traitez-les comme des kernels : déploiement par étapes et épinglage. -
Baseline de performance. Enregistrez
x11perf -copywinwin500, résolution, statut du compositeur.
Pourquoi : Quand quelqu’un dit « ça semble plus lent », vous pouvez répondre avec des chiffres. -
Définissez un mode par défaut sensé. Choisissez une résolution et un rafraîchissement que le matériel soutient.
Pourquoi : Le gain de performance le plus économique, c’est moins de pixels. -
Décidez explicitement de la composition. Désactivez-la ou configurez-la ; ne la laissez pas « arriver toute seule ».
Pourquoi : Les compositeurs ajoutent buffering et blending, précisément là où les anciens systèmes meurent. -
Budgétez la mémoire. Assurez-vous que le système ne swappe pas en charge normale.
Pourquoi : Le swap transforme de petits hoquets en secondes de silence. -
Contrôlez les patterns de redraw dans les apps. Préférez les dirty rectangles ; évitez les repaint complets sur timers.
Pourquoi : Les écritures dans le framebuffer sont votre « appel API » le plus coûteux. -
Testez avec les assets pire cas. Polices les plus grandes, écrans les plus chargés, densité de données maximale.
Pourquoi : Si ça passe à peine en conditions idéales, ça échouera en production. -
Définissez des modes de dégradation. Réduire animations, diminuer l’alpha, basculer vers un rendu plus simple si la perf chute.
Pourquoi : Une UI stable « moins jolie » vaut mieux qu’une UI jolie qui se bloque. -
Maintenez une capacité de rollback. Conservez les paquets et configs connus bons.
Pourquoi : Quand les graphismes cassent, vous devez souvent récupérer sans UI locale fonctionnelle.
Checklist : validation avant changement (mise à jour pilote, refresh OS, nouvelle UI)
- Confirmer le binding du pilote kernel (
lspci -k). - Vérifier le chemin du renderer (
glxinfo -B). - Enregistrer le mode courant (
xrandr --current). - Lancer un quick benchmark 2D (
x11perfsubset). - Confirmer le choix et la configuration du compositeur (
ps -ef). - Vérifier l’absence de hangs GPU dans les logs après stress (
dmesg). - Contrôler la marge mémoire sous charge (
vmstat). - Vérifier que le disque n’est pas saturé (
iostat), spécialement sur des thin clients avec flash bon marché.
Checklist : réponse d’urgence quand l’UI est inutilisable
- Baisser la résolution via shell distant quand possible.
- Désactiver la composition et redémarrer la session.
- Rollback des paquets de la pile graphique vers la baseline.
- Si coincé sur fbdev de fallback, bootez avec des paramètres kernel connus bons et confirmez le load des modules.
- Réduire la charge de redraw de l’app : désactiver animations, baisser fréquence d’update, simplifier les visuels.
FAQ
1) Que faisait réellement une « carte graphique » avant les GPU ?
Souvent : scanner un frame buffer vers le moniteur, gérer une palette et peut-être accélérer des opérations 2D comme les copies de rectangles et les remplissages.
Le CPU dessinait encore la plupart des choses, surtout tout ce qui n’était pas un simple transfert de bloc.
2) Pourquoi 320×200 était-il si courant dans les vieux jeux PC ?
Parce que c’était rapide et simple. Ça tenait bien en mémoire, se mappait linéairement dans le fameux mode 256 couleurs, et ne demandait pas beaucoup de bande passante.
Les jeux pouvaient mettre à jour une portion significative de l’écran sans tomber d’un précipice de performance.
3) Qu’est-ce qu’un « blitter », et pourquoi en importer ?
Un blitter est du matériel dédié au déplacement de blocs de pixels (BitBLT) et parfois à de simples opérations raster.
Il importait parce que l’UI et les jeux 2D sont dominés par « copier ce rectangle », pas « calculer ce triangle ».
En termes opérationnels, c’est un moteur DMA pour pixels.
4) Le rendu logiciel était-il toujours lent ?
Pas toujours. Il était souvent surprenamment compétitif parce que le CPU pouvait être correct en calcul, et les programmeurs ingénieux minimisaient les écritures mémoire.
Mais c’était fragile : une passe en plus sur le frame buffer, un blend de plus, ou une profondeur de couleur supérieure pouvaient effondrer la perf.
5) Pourquoi les changements de profondeur de couleur causaient-ils des désastres ?
Parce que la bande passante et le stockage évoluent avec les octets par pixel. Passer de 16bpp à 32bpp double le trafic du frame buffer.
Sur les anciens bus et graphiques intégrés, ce n’est pas un « petit » changement ; ça peut être tout le budget.
6) Comment évitait-on le scintillement sans compositeurs modernes ?
Dirty rectangles, ordre soigneux des dessins, synchronisation avec le blank vertical quand possible, et parfois page flipping
si le matériel supportait plusieurs buffers. Ils concevaient aussi des UIs qui ne redessinaient pas constamment—parce qu’ils ne le pouvaient pas.
7) Quelle est l’équivalence moderne d’un « goulot framebuffer » ?
Toute situation où vous êtes dominé par des copies mémoire et la bande passante : composition logicielle, bureaux distants poussant des mises à jour plein écran,
ou applications forçant des readbacks GPU. Les étiquettes ont changé ; la physique non.
8) Si mon système affiche llvmpipe, est-ce toujours mauvais ?
Cela dépend de la charge. Pour des tableaux statiques ou du 2D léger, ça peut être acceptable. Pour de la composition lourde, de la vidéo ou de la 3D, c’est généralement problématique.
La démarche pratique est de traiter llvmpipe comme un signal de capacité : vous dépensez du CPU pour faire la partie graphique.
9) Quel est le levier d’optimisation le plus puissant sur les vieux systèmes graphiques ?
Réduire les pixels touchés par seconde. Cela signifie généralement baisser la résolution, éviter les repaint complets de fenêtre, diminuer les blends et la composition.
Si vous devez optimiser, optimisez la stratégie de redraw avant de micro-optimiser les mathématiques.
10) Pourquoi les problèmes graphiques legacy semblent-ils « aléatoires » ?
Parce qu’ils se situent souvent à l’intersection des révisions matérielles, bizarreries firmware et fallbacks pilotes.
Deux machines qui semblent identiques à l’achat peuvent se comporter différemment pour un pilote.
C’est pourquoi les baselines et les hardware IDs comptent.
Conclusion : étapes pratiques suivantes
Avant NVIDIA et l’ère GPU, les « graphismes » étaient un budget quantifiable : octets par pixel, pixels par image, images par seconde,
et le bus qui devait tout porter. La culture d’ingénierie issue de cette période — dirty rectangles, astuces de palette,
buffering prudent et méfiance envers les « améliorations visuelles gratuites » — n’était pas de la nostalgie. C’était ce qui fonctionnait sous forte contrainte.
Si vous exploitez ou modernisez quelque chose qui sent encore cette époque (bornes intégrées, thin clients, IHM industrielles,
bureaux distants, applications X11 legacy), faites trois choses cette semaine :
- Prouvez le chemin de rendu. Confirmez le pilote réel et le renderer en usage ; bannissez les fallbacks silencieux.
- Baselinez et épinglez. Capturez logs et benchmarks simples, et épinglez une pile graphique connue bonne par classe matérielle.
- Réduisez le redraw. Diminuez le touchage de pixels : résolution, profondeur de couleur, composition et stratégie de repaint.
Le monde pré-GPU n’était pas plus gentil. Il était juste plus honnête : vous pouviez voir le goulot d’étranglement à l’œil nu.
Traitez cette honnêteté comme un avantage diagnostic, et vous maintiendrez même des graphismes legacy assez stables pour que le business fonctionne.