Projektziel: FlightGear stürzte auf meiner Radeon RX 9060 immer wieder kurz nach dem Laden ab, manchmal einmal, manchmal zwanzigmal hintereinander. Im Log stand nur eine Zeile. Dieser Beitrag zeigt den Weg von dieser Zeile bis zu einer einzelnen Funktion im Grafiktreiber, inklusive aller falschen Verdächtigen. Ergebnis vorweg: Die Stelle im Treiber ist gefunden, die Ursache aber noch nicht. Die Umgebungsvariable, die zunächst wie die Lösung aussah, hielt der Gegenprobe nicht stand.

Das Symptom

Im Log steht jedes Mal dieselbe Meldung, kurz danach ist das Programm weg:


amdgpu: command stream overflowed (current: 5904, max: 5568)

Der Befehlspuffer an die Grafikkarte ist übergelaufen, und der Treiber bricht das Programm mit abort() ab. Das Kernel-Log blieb sauber, es gab keinen Reset der Karte. Ein Hardwarefehler war also unwahrscheinlich. Das System: FlightGear 2024.1, Mesa 26.1.6 mit dem Treiber radeonsi, Debian.

Vier falsche Verdächtige

VerdachtWarum er naheliegend warErgebnis
Mein neuer Flughafen-Eintrag und die WolkenDer Absturz trat zuerst dort aufDer Absturz kam auch ohne beides
Treiber-Einstellungen wie nodma oder das Abschalten von ThreadsDie üblichen Schalter bei TreiberproblemenKeine Besserung
Zu schnelle NeustartsDie Abstürze kamen in SerienAuch mit 60 Sekunden Pause 5 von 5 Abstürze
Die 3D-RauschtexturSie stand im Stack direkt über dem TreiberVerkleinern von 64 auf 32 Pixel half nicht

Besonders der letzte Verdacht sah überzeugend aus. Der Stack aus coredumpctl zeigte OpenSceneGraph mitten beim Hochladen einer 3D-Textur, darunter nur namenlose Adressen im Treiber:


#3  n/a (libgallium-26.1.6.so + 0xbe5f34)
...
#17 n/a (libgallium-26.1.6.so + 0x227aa9)
#18 osg::Texture3D::applyTexImage3D(...)
#19 osg::Texture3D::apply(osg::State&)

Der entscheidende Schritt: Debug-Symbole

Statt weiter zu raten, habe ich die Adressen aufgelöst. Debian stellt die Symbole über einen debuginfod-Server bereit, man braucht dafür nur die Build-ID der Bibliothek:


readelf -n libgallium-26.1.6.so | grep "Build ID"
curl -o gallium.debug https://debuginfod.debian.net/buildid/BUILD_ID/debuginfo
addr2line -f -e gallium.debug 0xbe5fe7 0xbe8381 0xbc700d 0x131367f

Damit war der Stack lesbar, und mein Verdacht war erledigt:


amdgpu_pad_ib            Puffer zu voll, Abbruch
amdgpu_cs_flush
si_flush_gfx_cs
si_draw_vertex_state     hier läuft der Puffer über
tc_batch_execute         wartende Befehle werden abgearbeitet
_tc_sync
tc_texture_map           die Textur will Zugriff und erzwingt das Warten
st_MapTextureImage
_mesa_TexImage3D

Die Textur ist unschuldig. Der Treiber sammelt Zeichenbefehle in einem eigenen Thread. Will das Programm auf eine Textur zugreifen, muss er vorher alles Wartende abarbeiten, und genau dabei läuft der Puffer in si_draw_vertex_state über. Die Textur stand also nur zufällig am Tatort. Das erklärt auch, warum ihre Größe keine Rolle spielte.

Die scheinbare Lösung: keine Display Lists

Mesa nutzt si_draw_vertex_state nach meinem Verständnis für Display Lists, eine alte OpenGL-Technik, die OpenSceneGraph für viele Modelle verwendet. FlightGear hat zwar die Einstellung /sim/rendering/use-vbos, sie war bei mir aber schon an und half nicht. OpenSceneGraph selbst bietet eine Umgebungsvariable, die früher ansetzt:


export OSG_VERTEX_BUFFER_HINT=VERTEX_BUFFER_OBJECT

Das Ergebnis mit derselben Startposition und demselben Flugzeug:

TestStartsAbstürze
Ohne Variable, Serie am Abend2120
Ohne Variable, Rauschtextur verkleinert32
Mit OSG_VERTEX_BUFFER_HINT=VERTEX_BUFFER_OBJECT80

Das sah eindeutig aus, also habe ich es als Lösung abgehakt.

Die Gegenprobe

Eigentlich wollte ich nur eine ältere Mesa-Version vergleichen. Dazu gehört ein Kontrolllauf ohne die Variable, und der stürzte nicht ab. Auch alle Versuche, den alten Zustand wiederherzustellen, blieben stabil:

Lauf ohne VariableStartsAbstürze
Mesa 26.1.680
Mesa 25.0.7, lokal geladen80
Mesa 26.1.6, alte Bilddaten und Effekte80
Mesa 26.1.6, alte Startzeit80
Mesa 26.1.6, Volllast auf allen Kernen80

Der Absturz verschwand also gleichzeitig mit dem Einbau der Variable, aber nicht ihretwegen, jedenfalls lässt sich das nicht mehr zeigen. Solange er sich nicht nachstellen lässt, sagt auch der Vergleich der Mesa-Versionen nichts aus.

Fazit

Belegt ist die Stelle im Treiber, an der der Puffer überläuft. Nicht belegt sind der Auslöser, die Wirkung der Variable und ob auch andere betroffen sind. Die Variable bleibt bei mir als Vorsorge gesetzt, weil sie keine sichtbare Bildrate kostet. Eine Lösung nenne ich sie aber nicht mehr.

Die wichtigste Lehre: Die oberste lesbare Zeile im Stack ist nicht automatisch der Täter. Ich habe mehrere Stunden mit Vermutungen verbracht, die Debug-Symbole haben dann nur wenige Minuten gebraucht. Die zweite Lehre: Bei einem Fehler, der in Serien kommt, gehört zu jedem Test ein Kontrolllauf, und zwar zur selben Zeit. Wer FlightGear oder eine andere OpenSceneGraph-Anwendung auf einer aktuellen AMD-Karte mit dieser Meldung abstürzen sieht, kann die Variable in einer Minute ausprobieren. Über Rückmeldungen, ob sie dort hilft, würde ich mich freuen.