News Portierung: Tomb Raider (2013) für SteamOS verfügbar

V

VikingGe

Gast
Das sind keine Beta-Builds, das sind veraltete Builds (bzw. 743 ist anscheinend der aktuelle, den man auch so bekommt).
Warum die überhaupt zum Download angeboten werden? Gute Frage.
 
Zuletzt bearbeitet:

var const

Cadet 2nd Year
Dabei seit
Aug. 2014
Beiträge
26
Wenn ich mir mal nen apitrace von Tomb Raider anschaue, wundert mich nicht mehr, dass das Spiel scheiße läuft.
Das Spiel macht an fraglicher Stelle über 60000 GL-Calls pro Frame, von denen locker die Hälfte unnötig ist. Da muss bei Feral dringend was passieren./ATTACH]
Interessanter Ausschnitt. Sieht so aus, als wüsste Feral nicht, was ein VAO ist - peinlich.
 

NoXPhasma

Lieutenant
Dabei seit
Jan. 2010
Beiträge
638
@VikingGe Am besten wäre es wenn du den Support von Feral bezüglich dem apitrace anschreibst. Evtl ändert sich dann ja was. linuxsupport@feralinteractive.com
 
V

VikingGe

Gast
Ich weiß ehrlich gesagt nicht so ganz, was ich denen schreiben soll. Vor allem, wenn dabei mehr herumkommen soll als "have you tried playing with lower settings?" oder "your system doesn't meet the requirements". Hatte bislang nie mit dem Feral-Support zu tun, aber normalerweise ist es ja so, dass die Antwort umso spärlicher ausfällt, je technischer die Anfrage ist.

AFAIK benutzt Feral auch nur einen eigenen Dx11 => OpenGL-Wrapper. Insofern dürfte es auch nicht gerade einfach sein, solche Probleme zu beheben. Ich bin gerade dabei, anhand kleiner Beispielprogramme herauszufinden, wo die größten Probleme liegen - mein Gefühl sagt mir nämlich, dass es nicht nur die redundanten Vertex Attribute-Setups sind (ca. 20000 Calls von ~60000), sondern vor allem glNamedBufferSubData-Calls (~7700 Calls). Da wird für fast jeden Draw Call ein Buffer teilweise komplett überschrieben - wenn die Dx11-Version aber genau so funktioniert, wird es schwierig, das zu beheben, ohne den ganzen Renderer umzubauen.
 

var const

Cadet 2nd Year
Dabei seit
Aug. 2014
Beiträge
26
Ich dachte eigentlich, dass Feral nicht nur von einer API auf die andere wrappt. So macht es doch Virtual Programming mit eON.

Die glNamedBufferSubData-Calls finde ich eigentlich nicht so schlimm. Das sind keine VBOs sondern Uniform Buffer! Zumindest auf deinem Screenshot werden auch nur 384 Bytes übertragen. Im Prinzip ist das also nur ein glUniform. Wie viel die ganzen Enable/DisableVertexAttribArray-Aufrufe wirklich kosten, kann ich natürlich auch nicht sagen und das ist auch treiberabhängig. Aber VAOs ordentlich zu benutzen ist Pflicht. Das lernt man doch in jedem Anfängertutorial.
 

Zehkul

Admiral
Dabei seit
Feb. 2011
Beiträge
8.644
wenn die Dx11-Version aber genau so funktioniert, wird es schwierig, das zu beheben, ohne den ganzen Renderer umzubauen.
Und das ist ja genau die Krux von Linux Ports. OpenGL an sich ist nicht schlecht, aber in der Praxis dann eben doch, denn es funktioniert nur extrem schlecht mit einigen Dingen, die unter DX11 vielleicht auch nicht unbedingt beste Tischmanieren sind, aber trotzdem mehr oder weniger gut laufen. Mehr oder weniger reicht bei einem begrenzten Budget einfach oft genug aus. Schlimmster Übeltäter, Texturstreaming, Stotterei ahoi …

Es könnte mit Vulkan tatsächlich oft leichter und billiger sein, einen DX11 Renderer für Linux hinzubiegen. Für Tomb Raider aber natürlich viel zu spät.
 

Iapetos

Commander
Dabei seit
Mai 2007
Beiträge
2.059
Was glaubst du wieso es Tomb Raider nicht im freien Handel oder über GoG zu kaufen gibt? Weil hier jemand ein toller Linux Unterstützer ist oder doch eher weil Valve hier Geld gezahlt hat um die eigene Marktposition zu stärken? Im Moment ist die Konkurrenz seitens Microsoft eher willkommen, da es in letzter Zeit die meisten Spiele sonst nur noch über Steam gab und auf Dauer ist ein Monopol egal von welcher Seite nie gut.

Wenn man zu dem was du sagst stehen sollte, dürfte die einzige Plattform über die man Spiele bezieht GoG sein und auch dort nur für die Spiele, die ohne den Galaxy Client laufen.
Der Unterschied zwischen Valves und Microsofts Vertriebsplattformen ist, dass ich bei ersterer zumindest das Betriebssystem recht frei wählen darf. Man muss Valve anrechnen, dass sie das Interesse an Linux als alternative Spieleplattform gefördert haben. Deshalb habe ich auch kein schlechtes Gewissen, wenn ich ein Spiel über Steam kaufe, dessen Linux-Version dank Valves Finanzspritze für eine lange Zeit steam-exklusiv sein wird - solange es ordentlich läuft und nicht halbherzig hingeklatscht ist (Negativbeispiele gibt es leider bei Feral Interactive zur Genüge).

Wenn ich beim Kauf eines Spiels zwischen Steam und GOG wählen kann, entscheide ich mich grundsätzlich für GOG, auch wenn es manchmal etwas teurer ist. Den Galaxy-Client gibt es, so weit ich weiß, noch nicht für Linux, außerdem soll er optional sein.

Glücklicherweise bin ich in der komfortablen Situation, nicht dem letzten Schrei und dem heißesten Scheiß hinterherlaufen zu müssen, weshalb ich mich bei meinen Kaufentscheidungen an der Verfügbarkeit für der Plattform meiner Wahl orientiere.
 
V

VikingGe

Gast
Die glNamedBufferSubData-Calls finde ich eigentlich nicht so schlimm. Das sind keine VBOs sondern Uniform Buffer!
Was das für Buffer sind, ist erstmal herzlich egal. All buffers are created equal (zumindest was das Target angeht). Die Daten dienen als Shader-Input und müssen auch entsprechend synchronisiert werden.
Das Problem ist auch nicht die Menge der Daten, sondern dass da im Grunde folgendes passiert:

1. Client schickt Daten an den Treiber. Treiber puffert die erstmal irgendwo zwischen, allokiert ggf. irgendwo neuen Speicher, der gerade nicht aktiv von der GPU gelesen wird, und sagt der GPU, sie soll per DMA die Daten kopieren.
2. Client schickt Draw Call los. Treiber muss zusehen, dass die Daten aus Schritt 1 für die GPU lesbar sind. Und zwar vollständig.
3. Client schickt neue Daten an den Treiber. Nun ist der Draw Call aber noch nicht fertig. Bleibt also entweder warten (ugh) oder neuen Speicher reservieren (immerhin wird hier der ganze Buffer überschrieben, da geht das), was aber in der Summe auch einiges an Verwaltungsaufwand darstellt. Vielleicht ist ja auch irgendwo noch ein Block von vor ein paar Draw Calls frei. (ugh)
4. Client schickt nächsten Draw Call los, der aber wieder erst ausgeführt werden kann, wenn alle Daten irgendwo sind.
5. Wiederhole Schritte 3-4 etwa 7000 Mal.

Ein gut optimierter Treiber mag das zwar ohne viel Synchronisation hinbekommen. Sonderlich effizient ist das trotzdem nicht.

Weitaus sinnvoller wäre:
- Uniform-Daten für n (n einigermaßen groß) Objekte in einen größeren Buffer schreiben
- n Objekte per Instancing und/oder MultiDraw rendern und dann per gl_InstanceID oder einem Per-Instance-Vertexattribut auf die entsprechenden Uniform-Daten zugreifen

Ändert zwar am grundlegenden Problem nichts, man müsste es aber statt ~7000 Mal allenfalls einige hundert Male lösen. Ich bin mir ziemlich sicher, dass man die Anzahl der GL-Calls in der Szene um 90% reduzieren könnte. Aber dafür müsste man wie gesagt den Renderer entsprechend anpassen, ein Dx11->GL-Wrapper reicht da nicht.
 

Iapetos

Commander
Dabei seit
Mai 2007
Beiträge
2.059
Also darf man vorsichtig behaupten, dass Feral Interactive nicht maßgeblich für die miese Leistung des Spiels verantwortlich ist, sondern dass schon das Original von Crystal Dynamics mies mit Ressourcen umgeht. Überoptimierte DX11- und DX9-Treiber haben das jedoch bisher verschleiert und den Programmierern vorgegaukelt, sie hätten einen guten Job erledigt (#Schulterklopfen). Der OpenGL-Port hat die Mängel zutage gefördert und weil man auch nicht übermäßig viel Geld dafür ausgeben kann, sind die Unzulänglichkeiten des Renderers nicht behoben worden.

Die Quintessenz: Wenn man plattformübergreifend entwickeln will, sollte man das von Anfang an mit kontinuierlicher Qualitätskontrolle tun. Das wollte Crystal Dynamics jedoch nicht.
 

var const

Cadet 2nd Year
Dabei seit
Aug. 2014
Beiträge
26
@VikingGe:
Hier würde ich gerne mal die Meinung eines Treiberentwicklers zu hören. Denn im Prinzip passiert hier auch nichts anderes als
glUniform
glDrawElementsInstancedBaseVertex

Nur, dass statt glUniform eben glNamedBufferSubData genommen wurde. Bei glUniform ist es ja so, dass der Treiber die Änderungen erstmal auf Client-Seite zwischenpuffert und irgendwann zeitgleich mit dem Drawcall an den Server überträgt - es wird also gar nichts synchronisiert, die GPU muss nicht auf die CPU warten (und umgekehrt). Die Anforderungen an die Synchronisation sind hier genau die gleichen. Instancing wird bereits verwendet. Die Anzahl der Drawcalls lässt sich möglicherweise dennoch weiter reduzieren, das kann man aber nicht am apitrace ablesen.
 
V

VikingGe

Gast
Die Anzahl der Drawcalls lässt sich möglicherweise dennoch weiter reduzieren, das kann man aber nicht am apitrace ablesen.
Doch, kann man, und zwar daran, dass sich zwischen zwei Draw Calls lediglich die Inhalte des Uniform-Buffers ändern. Das kann man immer vereinen, man müsste nur mal Arrays in Uniform-Buffern verwenden. Wenn man von Hand programmiert, wird man zumindest im Jahre 2016 wohl kaum für lausige 300 Bytes einen Buffer erstellen, wenn der auf die Art und Weise genutzt wird wie es hier der Fall ist.

Dass die beiden Draw Calls aus dem Screenshot Instancing verwenden, ist glücklicher Zufall, nur ein Bruchteil der Draw Calls ist instanced (das Muster ist aber immer mehr oder weniger das gleiche - paar hundert Bytes an Uniform-Daten ändern -> Draw Call, deutlich seltener werden mal Texturbindings geändert o.ä.). Die Art zu rendern ist quasi eine Antwort auf die Frage "wie erzeuge ich den größtmöglichen API-Overhead in OpenGL".

Anyway, ich habe gestern ein paar kleine Tests gemacht und das Problem liegt weder an den vielen Draw Calls an sich, noch an den redundanten Vertex-Format-Setups (NVidias Treiber ignoriert die Calls anscheinend, wenn sich nichts ändert), und auch nicht an den glNamedBufferSubData-Calls an sich. Ist schwierig, mit einfachen Mitteln eine vergleichbare Situation aufzubauen.
Die Performance dürfte trotzdem auf die Nutzung von OpenGL zurückuführen sein, denn ein Replay des apitrace läuft auch nicht nennenswert besser als das Spiel.
 

var const

Cadet 2nd Year
Dabei seit
Aug. 2014
Beiträge
26
Doch, kann man, und zwar daran, dass sich zwischen zwei Draw Calls lediglich die Inhalte des Uniform-Buffers ändern. Das kann man immer vereinen, man müsste nur mal Arrays in Uniform-Buffern verwenden. Wenn man von Hand programmiert, wird man zumindest im Jahre 2016 wohl kaum für lausige 300 Bytes einen Buffer erstellen, wenn der auf die Art und Weise genutzt wird wie es hier der Fall ist.
Hast natürlich Recht, prinzipiell kann man so etwas immer vereinen. Ist aber gut möglich, dass die Drawcalls von unterschiedlichen Sichtbarkeitsabfragen abhängig sind oder sonst irgendwie nicht logisch zusammenhängen und deshalb getrennt gerendert werden. Um das zu beurteilen, müsste man die Programmlogik dahinter einsehen können. Wenn sich das allerdings wie ein roter Faden durch den ganzen Trace zieht, sollte Feral hier nochmal nachbessern.

Anyway, ich habe gestern ein paar kleine Tests gemacht und das Problem liegt weder an den vielen Draw Calls an sich, noch an den redundanten Vertex-Format-Setups (NVidias Treiber ignoriert die Calls anscheinend, wenn sich nichts ändert), und auch nicht an den glNamedBufferSubData-Calls an sich.
Wie hast du das getestet? Hast du die trace-Datei bearbeitet? Wenn ja, mit welchem Tool?
 
V

VikingGe

Gast
Nein, ich hab lediglich versucht, from scratch eine vergleichbare Situation aufzubauen und da eben genau das zu machen, was das Spiel macht (zu rendern gab es bunte Quadrate mit einem recht trivialen Fragmentshader). Das ist allerdings nicht gelungen, das Ergebnis waren jedes Mal dreistellige Frameraten.

Wüsste nicht, dass man die Traces irgendwie bearbeiten kann.
 
Zuletzt bearbeitet:
Top