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
| Verdacht | Warum er naheliegend war | Ergebnis |
| Mein neuer Flughafen-Eintrag und die Wolken | Der Absturz trat zuerst dort auf | Der Absturz kam auch ohne beides |
Treiber-Einstellungen wie nodma oder das Abschalten von Threads | Die üblichen Schalter bei Treiberproblemen | Keine Besserung |
| Zu schnelle Neustarts | Die Abstürze kamen in Serien | Auch mit 60 Sekunden Pause 5 von 5 Abstürze |
| Die 3D-Rauschtextur | Sie stand im Stack direkt über dem Treiber | Verkleinern 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:
| Test | Starts | Abstürze |
| Ohne Variable, Serie am Abend | 21 | 20 |
| Ohne Variable, Rauschtextur verkleinert | 3 | 2 |
Mit OSG_VERTEX_BUFFER_HINT=VERTEX_BUFFER_OBJECT | 8 | 0 |
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 Variable | Starts | Abstürze |
| Mesa 26.1.6 | 8 | 0 |
| Mesa 25.0.7, lokal geladen | 8 | 0 |
| Mesa 26.1.6, alte Bilddaten und Effekte | 8 | 0 |
| Mesa 26.1.6, alte Startzeit | 8 | 0 |
| Mesa 26.1.6, Volllast auf allen Kernen | 8 | 0 |
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.