Kategorien
Ohne Kategorie

Störrische Nvidia-Grafik im Laptop: Treiber- oder Hardwareproblem?

Kürzlich versuchte ich die Nvidia-Grafikkarte eines älteren Laptops unter Linux zum Laufen zu bekommen. Betrieben wurde dieser ursprünglich mit Windows 8.1, doch dort kam es bereits zu Problemen. Witcher 3 beispielsweise lief damit nur mit fps-Werten nahe der eins, egal welche Einstellungen gewählt wurden. Weder Prozessor noch Arbeitsspeicher waren stark ausgelastet, also musste etwas anderes faul sein. Daher habe ich mal ein Linux auf das Gerät geworfen, um die Leistung damit zu testen.

Für das Modell (GeForce GT 630M) gibt es unter Linux zwei Treiber: Der proprietäre Treiber von Nvidia selbst oder der quelloffene nouveau-Treiber. Ersterer unterstützt die Grafikkarte des Laptops aber nur bis zur Version 390. Damit kann die Karte zwar grundsätzlich betrieben werden und bietet sogar nach eigener Angabe OpenGL 4.6 Unterstützung. Allerdings ist PRIME Render Offload erst aber Treiberversion 435 möglich, was bedeutet, dass Nvidia Optimus nur sehr rudimentär umgesetzt ist. Der freie nouveau-Treiber kann das dagegen schon länger. Dieser wiederum offeriert nur OpenGL 4.3 und auch eine etwas schlechtere 3D-Leistung.

Wenn der dedizierte Grafikchip nicht in Benutzung ist, soll er sich dann auch Schlafen legen. Das spart Akku und reduziert die Abwärme, im Falle des untersuchten Laptops senkt das die Temperatur am Lüfter bei ruhendem Desktop um ganze 15°C! Auch das sollte mit nouveau automatisch geschehen dank vga_switcheroo, doch geklappt hat das nicht. Ich vermutete, dass das Laptopmodell schlicht irgendwo inkompatibel ist oder eine fehlerhafte ACPI-Implementierung hat. Testweise habe ich dann bbswitch probiert, und das hat geklappt: Damit lässt sich die GPU aus- und wieder einschalten, wenn auch nur händisch.

Dabei kam aber ein interessantes Phänomen zum Vorschein: Nach dem Wiederanschalten waren beide Treiber nicht mehr in der Lage, die Grafikkarte erneut anzusprechen. nouveau erkannte das Modell nicht mehr und meldete einen unbekannten Chip mit der Nummer „0xffffffff“:

nouveau 0000:01:00.0: unknown chipset (ffffffff)

Hier war klar etwas schief gelaufen mit der Kommunikation, und die Ausgabe des proprietären Nvidia-Treibers schaffte etwas mehr Klarheit:

NVRM: GPU at 0000:01:00.0 has fallen off the bus.

Offenbar hatte sich die GPU von der PCIe-Schnittstelle verabschiedet, obwohl sie im eingeschalteten Zustand fröhlich weiter Energie verbrat. Einen Neustart später hatte sie sich zwar wieder beruhigt, doch das obige Problem war reproduzierbar. Für einen Wechsel zwischen Nvidia- und Intel-Grafik war so ein vollständiger Systemneustart nötig – und zu allem Überfluss war die 3D-Leistung der Nvidia-Grafik auch unter Linux nur marginal besser als die Intel-Grafik, was der Erfahrung mit Windows entspricht.

Einige Neustarts später kam dann die Erkenntnis: Die Hardware ist defekt. Denn plötzlich taucht die Nvidia-GPU gar nicht mehr auf! Sie wird vom PCI-Bus schlicht nicht mehr erkannt, entsprechend melden die Treiber, sie fänden keine Nvidia-Grafik im System. Auch habe ich das Gerät länger ohne Akku liegen lassen, doch das hat die Grafikkarte nicht wiederbelebt. Mein Stresstest hat ihr leider den Todesstoß versetzt.

Kategorien
Ohne Kategorie

Mit CMake + MinGW Windows-Ressourcen in die .exe bauen

Für den Bau einer Windows DLL oder EXE ist es meistens erforderlich, eine Ressourcendatei (.rc) zu integrieren. In dieser gibt man beispielsweise Versionsinformationen an oder versieht eine Anwendung mit einem Icon. Dazu übersetzt man die .rc-Datei mit dem Programm windres in eine Objektdatei und linkt diese in die ausführbare Datei.

CMake übernimmt diese Aufgabe automatisch, man muss lediglich die .rc-Datei als Quelldatei mit angeben:

add_executable(App main.c icon.rc version.rc)

So zumindest in der Theorie. So ganz automatisch ging das dann doch nicht, zumindest nicht bei mir. Zuerst musste ich CMake mitteilen, dass es die .rc-Dateien übersetzen soll:

enable_language(RC)

Damit funktioniert das ganze schon mal mit dem Microsoft-Compiler und dessen windres. Auch MinGW bringt den windres-Compiler mit, allerdings mit anderen Aufrufparametern. Daher schlug die Übersetzung der .rc-Dateien fehl. Um CMake den korrekten Aufruf mitzuteilen, war ein weiterer Befehl nötig:

if (${MINGW})
    SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
endif()

Eigentlich sollte CMake seit Version 2.8.7 auch mit MinGW-windres zusammenarbeiten, zumindest laut dem TigerVNC-Projekt. Trotz der von mir verwendeten Version 3.12 hatte ich jedoch nur mit obigem Workaround Erfolg.