1 points par GN⁺ 2025-03-05 | 1 commentaires | Partager sur WhatsApp
  • Sur un IBM PS/1 486-DX2 66MHz, l’équivalent d’un PC haut de gamme en 1993, le DOOM original atteignait 21,5 fps sur demo1, tandis que fastDOOM montait à 30,1 fps dans les mêmes conditions, illustrant l’écart d’optimisation du port DOS
  • fastDOOM est parti de PCDOOM v2, qui combinait le noyau de Linux DOOM, les E/S de Heretic, APODMX et des E/S graphiques en Mode Y fondées sur la rétro-ingénierie par désassemblage de DOOM.EXE
  • Après avoir compilé et benchmarké 52 releases et 3 042 commits, il apparaît que le gain de performances ne vient pas d’un compilateur moderne à lui seul, mais de l’accumulation de petites optimisations
  • Parmi les améliorations les plus marquantes figurent l’omission du rendu de la barre d’état, l’inlining de FixedDiv, l’optimisation de la traversée BSP, la suppression de rendus visplane inutiles, l’élimination d’indirections de pointeurs et la séparation des exécutables par renderer
  • Le mode graphique le plus efficace dépend du CPU et du bus : sur les CPU lents, le Mode Y est avantageux, tandis que sur des CPU plus rapides avec VLB/PCI, le Mode 13h ou VESA direct peuvent être meilleurs, avec toutefois des contraintes comme VESA 2.0

L’écart de performances visible sur un 486-DX2

  • Sur un IBM PS/1 486-DX2 66MHz « Mini-Tower » modèle 2168, exécuter le DOOM original avec doom.exe -timedemo demo1 donne 1710 gametics in 2783 realtics
    • DOOM n’affiche pas directement les fps ; il faut donc calculer 1710/2783*35, ce qui donne 21,5 fps
  • Sur la même machine, fdoom.exe -timedemo demo1 affiche 1710 gametics in 1988 realtics, soit 30,1 fps
  • Sur des cartes plus lourdes comme demo1 de doom2, on passe de 16,8 fps pour l’original à 24,9 fps pour fastDOOM, soit 48 % plus rapide
  • En revanche, la prise en charge du joystick et du jeu en réseau a été supprimée ; ce n’est donc pas un port qui conserve toutes les fonctionnalités à l’identique

La lignée du code derrière fastDOOM

  • DOOM a été développé à l’origine sur NeXT Workstation, avec une structure facile à porter, séparant l’essentiel du code d’un petit sous-système d’E/S
  • La version DOS commerciale utilisait des E/S DOS écrites par id Software, mais à cause de sa dépendance à la bibliothèque audio propriétaire DMX, elle n’a pas pu être open source telle quelle en 1997
  • Le code publié correspond à la version Linux, préparée par Bernd Kreimeier dans le cadre d’un projet de livre expliquant le moteur
  • La version DOS PCDOOM v2 a été reconstituée à partir de la combinaison suivante
    • le noyau de Linux DOOM
    • les E/S de Heretic
    • APODMX pour imiter DMX
    • les E/S graphiques de i_ibm.c rétroconçues à partir du désassemblage de DOOM.EXE
  • fastDOOM prend ce PCDOOM v2 comme point de départ

L’évolution des performances suivie via les releases et les commits

  • Victor « Viti95 » Nieto publiait souvent fastDOOM, taguait chaque release et organisait ses commits pour qu’un commit corresponde à une tâche
  • L’historique Git de fastDOOM compte 3 042 commits, ce qui a permis de suivre l’évolution des performances commit par commit
  • Les 52 releases de fastDOOM, PCDOOM v2 et le DOOM.EXE original ont été téléchargés, puis un programme Go a généré un RUN.BAT exécutant -timedemo demo1, monté via mTCP NETDRIVE pour les tests
    • Les conditions étaient DOOM.WAD, son activé et screen size 10
    • La suite complète a été exécutée 5 fois afin de tracer un graphique de fps moyens
  • Bien que PCDOOM v2 ait été compilé avec OpenWatcom 2, l’amélioration face au DOOM.EXE original reste modeste, ce qui montre que les gains de fastDOOM sont difficiles à expliquer par le seul usage d’un compilateur moderne
  • Le graphique de taille des fichiers montre qu’au départ, le travail consistait surtout à alléger le code par nettoyage et suppression
    • bf0e983 : suppression de l’enregistrement audio
    • 5f38323 : suppression des chaînes de codes d’erreur
    • 8b9cac5 : remplacement de TASM par NASM

Les changements par release qui ont fait grimper les performances

  • Exécuter un timedemo sur les 3 042 builds aurait pris environ 9 jours ; le benchmark au niveau du commit s’est donc concentré sur v0.1, v0.6, v0.8, v0.9.2 et v0.9.7, où les gains étaient les plus importants
  • fastDOOM v0.1

    • v0.1 comprend 220 commits
    • Le plus gros patch est e16bab8 du build 36
      • La « Crispy optimization » transforme le rendu de la barre d’état en no-op tant que le pourcentage affiché ne change pas, évitant le rendu dans le scrap buffer et le blit vers l’écran
      • Ce seul changement apporte 2 fps de plus
    • a9359d5 du build 167 inline FixedDiv sous forme de macro
    • 9bd3f20 du build 207 reprend une optimisation de PSX Doom pour améliorer la traversée BSP
    • dc0f48e du build 212 inline la fonction de rendu de surfaces horizontales R_MakeSpans
    • Sur l’ensemble des commits, 100 étaient des suppressions, soit environ la moitié en suppression de code
  • fastDOOM v0.6

    • v0.6 se compose de 33 commits
    • 22819fd du build 342 saute les rendus visplane inutiles
    • 40e0d4b du build 359 et ccd296f du build 360 réduisent les indirections via le pointeur player
    • f29e665 du build 369 inline le screenspace line splitter
  • fastDOOM v0.8

    • v0.8 comprend 282 commits
    • Le système audio étant instable, le timedemo a été effectué sans son puis les fps ont été corrigés
    • Cette release se concentrait sur le renderer en mode texte, et les builds 670 et 730 ont subi des régressions avec la disparition de la Crispy optimization
    • Principales améliorations
      • f279b7d : séparation des exécutables par renderer, comme FDOOM.EXE et FDOOM13H.EXE
      • 1874ee8 : désactivation du débogage du compilateur
      • 6aae724 : restauration de la Crispy optimization
      • 1366ebf : compilation du minimum de code possible selon les cas
  • fastDOOM v0.9.2 et v0.9.7

    • v0.9.2 compte 110 commits, avec notamment une optimisation de la comparaison skyflatnum, une optimisation de R_DrawColumn pour le Mode Y et un nettoyage du code R_DrawSpan
    • v0.9.7 est présenté comme ayant 293 commits, mais la sortie de commande en affiche 294
    • Même après plusieurs benchmarks, le bruit n’a pas pu être réduit sur cette release
    • Les principaux changements portent sur des tests de modifications ASM x86, la sélection CPU et l’optimisation CR2 pour 386SX, l’optimisation ESP pour R_DrawSpan386SX, du code basé sur le rendu ASM fuzz column et la suppression d’une comparaison CMP par boucle

Comment choisir entre Mode 13h, Mode Y et VESA direct

  • fastDOOM explore de nombreuses optimisations pour différentes combinaisons de CPU et de bus vidéo : 386, 486, Pentium, Cyrix, avec ISA, VLB ou PCI
  • Sur l’IBM PS/1 486-DX2 66MHz, l’optimisation utilisant Mode 13h était plus lente que le Mode Y
  • Mode 13h

    • Le matériel répartit les données entre les quatre banques de VRAM du VGA, ce qui donne au CPU l’illusion d’un framebuffer linéaire unique en 320x200
    • Comme le double buffering n’est pas possible directement en VRAM, il faut bufferiser en RAM puis recopier vers la VRAM, ce qui revient à écrire les octets deux fois
    • Le moteur doit se bloquer sur le VSYNC
  • Mode Y

    • Les banques VGA étant accessibles individuellement, il permet le triple buffering en VRAM et n’écrit chaque octet qu’une seule fois directement en VRAM
    • La sélection de banque nécessite cependant l’instruction lente OUT
    • En écrivant simultanément sur deux banques VGA via les latchs, on peut dupliquer horizontalement les pixels et obtenir un mode low-detail
    • Le rendu de l’invisible Specter exige une relecture de la VRAM, ce qui est beaucoup plus lent
    • D’après l’explication de John Carmack, DOOM utilisait en mode VGA 320×200×256 un mode planaire entrelacé proche du Mode X, avec rotation entre trois pages d’affichage
    • Le texture mapping direct en mémoire vidéo pouvait apporter 10 % à 15 % de vitesse supplémentaire sur beaucoup de cartes vidéo
    • Cela permettait aussi un page flip sans tearing, contrairement au buffering en mémoire principale
    • Heretic est sorti en 1994 et, avec l’évolution du matériel, le Mode 13h est devenu plus attrayant ; Raven a donc orienté le moteur de DOOM dans cette direction
    • fastDOOM propose plusieurs exécutables à l’utilisateur
    • FDOOM.EXE
    • FDOOM13H.EXE
    • FDOOMVBD.EXE
  • Le Mode 13h et VESA direct dans fastDOOM

    • En Mode 13h, fastDOOM rend dans un framebuffer linéaire unique en RAM, puis copie la scène entière en VRAM une fois l’image terminée
    • Il ne force pas le VSYNC, ce qui peut provoquer du flickering
    • Sur un bus ISA 8-bit lent, une copie différentielle n’envoie que les pixels modifiés
    • Sur des bus plus rapides, comme ISA 16-bit, VLB ou PCI, le backbuffer complet est copié via REP MOVS
    • D’après les tests de Viti95, le meilleur mode sur CPU 486 est le VESA direct mode 320×200 de FDOOMVBD.EXE
      • Il combine les avantages du Mode Y avec le code de rendu optimisé de Heretic
      • Il évite les instructions OUT, sauf une fois par frame lors du changement de buffer
      • Il nécessite une carte graphique VLB ou PCI avec LFB activé et la prise en charge de VESA 2.0 ; il est lent en modes low-detail et potato-detail
    • L’IBM 2168 ne prenant pas en charge VESA 2.0, l’exécution de FDOOMVBP.EXE et FDOOMVBD provoque une erreur

Les tentatives infructueuses et l’impression d’ensemble

  • Les flags processeur spécifiques d’OpenWatcom, 4r/4s et 3r/3s, ont aussi été essayés avant d’être abandonnés
    • Les flags 386 et 486 de wcc386 ont tous deux été testés, et au final la version 386 semblait toujours plus rapide
  • Viti95 vise aussi un changement de compilateur pour fastDOOM, d’OpenWatcom v2 vers DJGPP, donc GCC
    • Il semble en effet que GCC génère un code plus rapide à partir de la même base source
    • Une autre possibilité souhaitable serait qu’OpenWatcom v2 progresse pour réduire cet écart de performances
  • Les performances de fastDOOM résultent de la réutilisation d’améliorations existantes issues de Crispy, PSX, GBA et Lee Killough, auxquelles s’ajoute une grande quantité de nouvelles optimisations
  • Des idées de Ken Silverman et une partie de son code ont aussi été intégrées aux fonctions de rendu pour CPU UMC Green, avec des gains de vitesse importants sur ce matériel
  • fastDOOM n’est pas né d’un changement magique unique, mais d’un empilement de milliers de petites optimisations qui ont fini par produire un port DOS plus rapide que le DOOM original

1 commentaires

 
GN⁺ 2025-03-05
Commentaires sur Hacker News
  • C’est un bon exemple qui montre que les goulots d’étranglement ne sont généralement pas là où on les attend, d’où la nécessité de profiler et mesurer
    Un rendu en pourcentage dans la barre d’état : pour un expert qui connaît bien l’architecture de Doom, c’était peut-être relativement évident, mais j’aurais sans doute jamais deviné à l’avance que ce serait le goulot d’étranglement

    • Par exemple, il y a eu un cas où une application utilisait sans raison apparente 60 % de CPU et 25 % de GPU, et on a découvert que c’était à cause d’une petite animation CSS
      https://www.granola.ai/blog/dont-animate-height
    • Ça fait aussi penser à un cas d’optimisation dans Super Mario World sur SNES, où l’affichage du score du joueur était très inefficace et consommait environ 1/6 du temps de frame
      Dans le pire des cas, presque 1/6 de la frame entière servait à afficher le score dans la barre d’état, ce qui abaissait le seuil à partir duquel le jeu ralentissait ; le patch a modifié le stockage et l’affichage du score pour les rendre quasiment en temps constant, et c’était même un peu plus rapide que le meilleur cas précédent
      https://www.smwcentral.net/?p=section&a=details&id=35746
    • Du point de vue d’un développeur de jeux, ce type de ralentissement est courant
      Le rendu de l’UI peut être critique à cause de la transparence, du layering, des redraws, et surtout de ce qui déclenche des allocations mémoire ; comparer l’ancienne valeur à la nouvelle avant de redessiner aide beaucoup
      J’ai aussi eu un projet en CSS où les couches et la transparence étaient le goulot d’étranglement, et la clé était alors de réduire le nombre de layers
    • Mon exemple préféré reste le problème du temps de chargement de GTA Online, qui venait au final d’un mauvais traitement d’un fichier JSON de 10 Mo, et c’est quelqu’un d’extérieur à l’organisation qui l’a remonté
      Le chargement est passé de 6 minutes à moins de 2 minutes
      https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times...
    • Ça rappelle aussi le moment où npm était 2 fois plus lent qu’avant à cause d’une barre de progression sophistiquée dans le terminal
      https://news.ycombinator.com/item?id=10974929
  • Je ne suis peut-être pas vraiment le public visé, mais le NETDRIVE de mTCP m’a intrigué
    Je ne pensais pas qu’il existait déjà à l’époque des options de stockage réseau réellement utilisables, mais en cherchant je suis tombé sur https://www.brutman.com/mTCP/mTCP_NetDrive.html et c’est vraiment excellent
    NetDrive est présenté comme un pilote qui permet, depuis DOS, d’accéder à une image disque distante hébergée par une autre machine comme à un périphérique local monté avec une lettre de lecteur

    • Au début des années 90, dans la salle informatique de mon école, il y avait environ 25 Mac Plus reliés en daisy chain via AppleTalk à un Mac II, et tous les Plus montaient le système de fichiers du Mac II
      C’était terriblement lent : les élèves perdaient 5 à 10 minutes au début du cours juste pour lancer leur traitement de texte ; le Xerox Alto utilisait aussi des montages réseau pour ses lecteurs
      Dès qu’il y a du réseau, quelqu’un veut rapidement copier des fichiers, et le moyen le plus pratique est de faire en sorte que cela ressemble à un système de fichiers local
      DOS n’avait pas de réseau intégré, donc il était en retard sur ce point et demandait beaucoup plus de travail manuel
    • Il existe une astuce élégante avec iPXE pour démarrer DOS sur le réseau depuis une cible iSCSI
      Ça donne un accès en lecture/écriture à un périphérique bloc réseau sans pilote ni configuration côté DOS, mais si on l’utilise comme un partage, ça se casse vite la figure : on est bien plus proche d’un périphérique bloc
      Ça semble magique, mais il me semble qu’iPXE patche le BIOS pour rediriger les accès disque vers iSCSI
    • Je me demande s’il existait déjà à l’époque de DOS des NAS ou des montages WebDAV
      Il y avait évidemment des choses comme FTP et telnet, mais je me demande si les montages distants étaient réellement utilisés ou si la faible bande passante les rendait impraticables
  • Le fil GitHub auquel participe Ken Silverman est un vrai trésor
    C’est fascinant de voir l’auteur de FastDOOM et Ken plonger dans les subtilités de l’efficacité des registres 486 et des cycles d’horloge
    Ça fait plaisir de voir qu’il y a encore des gens pour continuer à améliorer les performances de Doom

    • Ça faisait vraiment longtemps que je n’avais pas pensé à KenS, alors qu’il était extrêmement actif dans la scène du modding de Duke3D dans les années 90
      Ce scripting a littéralement été ma première forme de « code », et d’une certaine manière je lui dois toute ma carrière et ma situation financière, ce qui est formidable
    • L’an dernier, en développant un moteur de rendu 2.5D similaire, j’ai envoyé un e-mail à Ken Silverman au sujet d’un aspect peu documenté du Build Engine, et il m’a répondu comme s’il avait encore travaillé dessus la veille
    • Il y a là-dedans de vrais bijoux
      En particulier, l’idée d’utiliser CR2 et CR3 comme registres scratchpad sur les 386SX, où les accès mémoire sont très lents, et sur les 386DX sans cache, était excellente
      La technique qui consiste à utiliser ESP comme compteur de boucle sans désactiver les interruptions est aussi géniale, car elle garantit qu’il pointe toujours vers une position de pile valide
  • Dans FastDOOM, une fonctionnalité dont on parle peu ici, ce sont toutes sortes de modes vidéo étranges
    Mode texte IBM MDA : https://www.youtube.com/watch?v=Op2tr2lGK6Y
    EGA & Plantronics ColorPlus : https://www.youtube.com/watch?v=gxx6lJvrITk
    Le classique CGA bleu et rose : https://youtu.be/rD0UteHi2qM
    CGA 320x200x16 avec le hack « ANSI from Hell » : https://www.youtube.com/watch?v=ut0V1nGcTf8
    Hercules : https://www.youtube.com/watch?v=EEumutuyBBo
    La plupart semblent tourner plus lentement que le VGA, à cause d'opérations comme le remappage des couleurs

    • Ce serait bien qu'il prenne aussi en charge le Tandy Graphics Adapter
      Si je devais le faire tourner en CGA, ça ne m'emballerait pas, et s'il avait encore existé, il aurait probablement fallu un build 286 pour un Tandy 1000 TL/2
    • C'est vraiment génial, et ça montre bien pourquoi ce genre d'aspects d'un jeu devrait être découplé
      Ça me fait penser à la Clean Architecture « moderne » des applications backend
    • Le mode texte IBM MDA est horrible... donc j'adore
  • Le passage « IBM PS/1 486-DX2 66Mhz, “Mini-Tower”, model 2168. L'ordinateur dont j'ai toujours rêvé ado mais que je n'ai jamais pu m'offrir » m'a marqué
    Vers 1992, j'utilisais déjà mon quatrième PC monté moi-même, et le salon informatique KCS de Marlborough, MA, était une ressource incroyable pour les bidouilleurs
    J'achetais des composants, je montais un PC, je l'utilisais un moment, je le revendais, puis je rachetais des pièces
    Fin 1992, je faisais tourner un 486-DX3 100 avec un coprocesseur mathématique ULSI 487, et pendant un temps c'était le PC le plus rapide du campus, peut-être même l'ordinateur le plus rapide
    Il était plus rapide que plusieurs modèles de Pentium et ne faisait pas d'erreurs de calcul
    J'avais justifié ce dernier build pour mon mémoire de fin d'études, parce que les temps de recalcul étaient trop longs pour simuler une centrale de cogénération gaz/diesel dans une feuille Excel de 21 pages
    J'avais une spécialisation en sciences de l'environnement, mais toute ma carrière s'est finalement faite dans l'informatique

    • Je ne suis pas sûr que ce soit le genre de truc auquel répondre « wow »
      Est-ce qu'il fallait vraiment en remettre une couche à quelqu'un qui ne pouvait pas se payer un tel ordinateur en 1992 ?
      En plus, il n'y a jamais eu de « DX3 », et le premier 486 à 100 MHz, le DX4, est sorti en mars 1994, donc dire qu'il l'utilisait fin 1992 ne semble pas crédible
      Le premier ordinateur de notre foyer, si on exclut un XT déjà totalement dépassé qu'on nous a donné vers 1992, c'était un 486-DX2 66 MHz acheté début 1995
      Même des décennies plus tard, ça me pique encore un peu l'ego de voir quelqu'un se vanter bizarrement d'un ordinateur impossible, plus rapide que le mien malgré trois ans de handicap
    • Ça fait clairement remonter des souvenirs
      Vers 1992, j'étais un étudiant fauché et j'ai emprunté environ 2 000 dollars à la coopérative de crédit pour acheter un 486 DX2-50
      En monnaie d'aujourd'hui, ça ferait plus de 4 000 dollars pour un ordinateur assez basique, et je faisais un dual boot DOS/Linux dessus
    • Un 487 avec un 486DX ? Je croyais que le 487 n'était utile qu'avec les puces SX
      Après vérification, le 487 standard était en fait un 486DX complet qui désactivait et remplaçait le 486SX d'origine
      C'était peut-être un autre coprocesseur fabuleux dont je n'avais jamais entendu parler
    • Si « c'était plus rapide que plusieurs modèles de Pentium et ne faisait pas d'erreurs de calcul », alors c'est totalement le genre de chose dont on peut se vanter
      Il les avait complètement surclassés
  • Au-delà de la fréquence des releases, Viti95 a montré une excellente discipline Git : un commit ne fait qu'une seule chose et chaque release est taguée
    https://fabiensanglard.net/fastdoom/#:~:text=one%20commit%20...

  • Dans « avant de connaître fastDOOM, je m'étais résigné à jouer sous Ibuprofen », je ne vois pas ce que veut dire Ibuprofen

    • Ça veut sans doute dire qu'il fallait prendre un antidouleur à cause du mal de tête provoqué par le faible framerate
  • Si l'auteur lit ceci, il y a une faute dans tout le document : le nom de famille de John Carmack est écrit « Carnmack »

  • Si on veut expliquer sans cynisme pourquoi les logiciels modernes sont lents et n'intègrent pas ce genre d'optimisations, il y a l'hypothèse standardisation/optimisation
    Une fois qu'une chose devient un standard, l'optimisation suit
    Parce qu'on veut être le plus rapide tout en passant tous les tests du standard
    Doom est désormais lui aussi devenu un jeu standard à porter partout, que ce soit sur un nouveau CPU ou un grille-pain, et c'est un peu pareil pour les protocoles d'e-mail ou les standards de navigateur comme WebRTC et QUIC
    Si les applis web modernes ou les applis Electron ne sont pas rapides, c'est parce qu'elles sont encore en phase d'exploration
    Elles sont mises à jour chaque jour pour répondre à de nouvelles demandes des utilisateurs, et côté performances il suffit qu'elles soient assez rapides pour ne pas gêner
    C'est pour ça que les applis IRC sont très rapides, alors que Slack et Teams sont condamnés à rester lents

  • Revenir en arrière sur les versions pour vérifier les améliorations et les régressions, ce n'est pas anodin
    Certaines optimisations peuvent introduire des bugs découverts plus tard, et des fonctionnalités indispensables peuvent aussi faire baisser les performances
    Avoir des tests de performance lancés automatiquement avant chaque release rend donc la vie plus simple, et si un problème de performance est détecté, on peut alors écrire un test de régression comme d'habitude
    En gros, ce que je veux dire, c'est : faites des tests de performance