Facepalm: Der rendert nicht oder ATI ist nicht NVidia

Lange ist es her, dass ich das letzte mal einen Artikel der Reihe Facepalm geschrieben habe, aber nun habe ich wieder einen aktuellen Anlass dafür. Im Terrain-Tutorial hatten sich beim letzten Teil mehrere User gemeldet und mir mitgeteilt, dass sie einfach nur einen blauen Bildschirm erhalten und nichts gerendert wird. Dies konnte ich leider nie bestätigen, da die Probleme – auch mit den User-Projekten – nicht auf meinem Rechner aufgetreten sind. Ein sehr ärgerlicher Fehler, da man diesen nicht debuggen kann.

Im Grunde genommen passieren solche Fehler häufig und XNA sollte diese Fehler weitestgehend abfangen, allerdings war dies in diesem speziellen Fall leider nicht so. Zunächst hatte ich bei diesen Problemen die XNA-Installation (z.B. XP-Install-Files unter Windows 7) im Verdacht, was durchaus ähnliche Probleme hervorrufen könnte. Es stellte sich jedoch schnell heraus, dass ich damit falsch lag. Schnell bin ich dann auf die Idee gekommen, dass sich einige Grafikkarten anders verhalten könnten als meine. Leider waren in allen meinen Rechner bzw. die Rechner auf die ich Zugriff hatte lediglich NVidia-Karten vorhanden. Damit konnte ich das Problem natürlich immer noch nicht nachstellen.

Kommen wir nun zur Facepalm: Glücklicherweise hat DirectX eine Art Debug-Modus für solche Dinge: Das Referenzdevice. Dieses ist eine Referenzimplementation in Software, dass das Standardverhalten bzw. Musterverhalten einer Grafikkarte unter DirectX vorgibt. Immer wenn etwas sich nicht so verhält, wie man meint, dass es sich verhält, kann man einfach mit dem Referenzdevice testen und schon sieht man, was das korrekte Verhalten ist und kann so verlässlich testen.

Seit XNA 4.0 ist es auch keine schwarze Magie mehr, dieses Referenzdevice einzuschalten. Das geht mit einer einzigen Zeile Code im Konstruktor von Game1:

GraphicsAdapter.UseReferenceDevice = true;

Diese einfache Zeile offenbarte mir unverzüglich den Fehler im Tutorial. Der folgende Aufruf versuchte in geschütztem Speicher zu schreiben:

GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 128 * 128, 0, 128 * 128 * 6 / 3);

Wenn versucht wird, in geschütztem Speicher zu schreiben, dann ist dies immer ein Hinweis darauf, dass man die Bereiche eines Puffers verlässt, was eigentlich immer ein Fehler ist. Ein wenig Hirnschmalz und die Analyse des restlichen Codes zeigten auf, dass der letzte Parameter sowohl optimiert werden konnte (6/3 ist immer 2), als auch schlicht und einfach falsch ist, denn es muss 127 * 127 * 2 heissen. Warum das so ist, ist hier nicht so wichtig, wichtig ist nur, dass dieser Parameter – er gibt die Anzahl der zu rendernden Primitive an – zu hoch war. Es sollten also mehr Primitive gerendert werden, als vorhanden.

Das Verhalten der einzelnen Grafikkarten und der Referenzimplementierung in Form des Referencedevice sind nun vollkommen unterschiedlich. Der NVidia-Treiber rendert einfach die Anzahl der verfügbaren Primitive. Das war der Grund, warum ich bei mir keinen Fehler sehen konnte. ATI-Grafikkarten haben den Fehler einfach stillschweigend ignoriert und einfach nichts gerendert. Dies ist bei den Usern aufgetreten, die mir das Problem gemeldet haben. Das Referenzdevice versucht in geschütztem Speicher zu schreiben und zeigt so den Fehler durch eine Exception indirekt an. Dies hat letztendlich dazu geführt, dass ich das Problem lösen konnte.

Die Moral von der Geschicht: Benutze das Reference-Device bei Fehlern, die du nicht nachvollziehen kannst. Das Reference-Device ist die Richtlinie für DirectX und gibt im Zweifelsfall das richtige Verhalten vor.

Advertisements

Veröffentlicht am 28.11.2011 in Facepalm und mit , , , , , getaggt. Setze ein Lesezeichen auf den Permalink. 2 Kommentare.

  1. internetfreak413

    Super Artikel.
    Ich muss sagen, ich programmiere mit XNA zwar nicht in 3D, sondern nur 2D (da es einfach einfacher ist und ich sowieso in 3D-Modeling usw keine Ahnung hab 😉 ), aber kann trotzdem immer mal wieder sowas „gebrauchen“.
    Ich habe selbst eine ATI Karte im PC und würde ich deine Tutorials ausprobieren, hätte ich wohl den selben Fehler auch gehabt.
    Dank diesem Artikel wüsste ich aber nun, worans liegt und könnte es beheben.
    Jedenfalls, weiter so, solche Blogger wie dich kann man immer gebrauchen (da es oftmals an guten Guides mangelt, vorallem in deutscher Sprache ist oftmals nicht viel vorhanden und mir ist ein deutsches Tutorial lieber, als ein englisches, auch wenn ich soweit Englisch lesen kann)

  1. Pingback: Terrain 101: Land in Sicht « "Mit ohne Haare"

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: