Multithreaded Rendering
-
Ich habe vor die Logik und das Rendering in seperaten Threads laufen zu lassen. Es gibt ein RenderEntity, welches VertexBuffer, IndexBuffer, Transformationen sowie Shader und dessen Constanten beinhaltet.
Wie du selbst bemerkt hast, ist das ein schlechter Ansatz fuer Parallelisierung. Normalerweise lagert man erstmal AI, Audio oder Input in einen separaten Thread aus. Dann kann man weitersehen ...
Hier ein bisschen was zum Lesen:
http://www.gamasutra.com/features/20051117/gabb_01.shtml
http://www.gamasutra.com/features/20060906/monkkonen_01.shtml
http://www.gamasutra.com/view/feature/3941/sponsored_feature_designing_the_.phpZusammenfassend von:
http://www.gamedev.net/community/forums/topic.asp?topic_id=525951
-
knivil schrieb:
Wie du selbst bemerkt hast, ist das ein schlechter Ansatz fuer Parallelisierung.
Das ist jetzt aber eine extrem subjektive Meinung.
Ich finde den Ansatz sehr gut und wir haben dieses Prinzip in unserer GameEngine bereits umgesetzt.
Im Endeffekt ist die eigentliche Render-Loop in den meisten Fällen das was am meisten CPU-Zeit frisst.
Wenn man dann noch die Logik in den gleichen Thread packt, kanns nur noch schlechter werden.
-
knivil schrieb:
Ich habe vor die Logik und das Rendering in seperaten Threads laufen zu lassen. Es gibt ein RenderEntity, welches VertexBuffer, IndexBuffer, Transformationen sowie Shader und dessen Constanten beinhaltet.
Wie du selbst bemerkt hast, ist das ein schlechter Ansatz fuer Parallelisierung. Normalerweise lagert man erstmal AI, Audio oder Input in einen separaten Thread aus.
eigentlich sollte rendering das meiste an rechenzeit ziehen, es macht wenig sinn etwas anderes vor dem rendering in einen thread auszulagern.
gerade input in einem thread macht so ziemlich keinen sinn.
-
@nurf: Du sagst ihr habt das so ähnlich eingebraucht und es funktioniert auch gut? Hättest du lust mir ein paar Tipps zu geben, wie ich das am besten anpacke, da du/ihr ja schon etwas mehr erfahrung damit gemacht habt?
-
rapso schrieb:
gerade input in einem thread macht so ziemlich keinen sinn.
Macht besonders Sinn für Egoshooter, wo die Leute ihre High-End Mäuse auch ausgereizt bekommen wollen.
Nehmen wir an das Rendering ist irgendwie limitiert auf 100fps, kann man trotzdem die Maus mit 1000Hz pollen.
Ansonsten erreicht man höhere Abtastraten, nur durch höhere Frameraten.Potatoman schrieb:
@nurf: Du sagst ihr habt das so ähnlich eingebraucht und es funktioniert auch gut? Hättest du lust mir ein paar Tipps zu geben, wie ich das am besten anpacke, da du/ihr ja schon etwas mehr erfahrung damit gemacht habt?
Im Endeffekt möchtest du bestimmt eine asynchrone Architektur.
Das bedeutet beispielsweise die Logik läuft mit 60Hz und der Renderer mit 132.57 Hz (variabel).
Daraus folgt du musst zwischen den Zeiteinheiten der beiden Threads interpolieren.Weiterhin besteht noch die Möglichkeit einer synchronen Architektur, dann würde man zur Synchronisation zwischen den Threads sowas wie eine Barrier nutzen.
Zum Datenaustausch würde man DoubleBuffering verwenden, sprich der Logik-Thread arbeitet auf dem Backbuffer und der Renderthread arbeitet auf dem Frontbuffer.
Der Nachteil dabei ist, man hat nur so viele FPS wie der langsamste Thread.
-
nurf schrieb:
rapso schrieb:
gerade input in einem thread macht so ziemlich keinen sinn.
Macht besonders Sinn für Egoshooter, wo die Leute ihre High-End Mäuse auch ausgereizt bekommen wollen.
Nehmen wir an das Rendering ist irgendwie limitiert auf 100fps, kann man trotzdem die Maus mit 1000Hz pollen.daten zu pollen ohne sie zu verarbeiten macht ehrlich keinen sinn.
Das OS hat schon mechanismen die auf input reagieren und ihn zwischenspeichern, ob jetzt
maus -> OS -> input thread -> logik
oder
maus -> OS -> logik
gemacht wird, hat fuer das resultat keinen einfluss, aber man hat halt verschleisserscheinungen wegen einem nutzlosen thread.Ansonsten erreicht man höhere Abtastraten, nur durch höhere Frameraten.
die abtastung wird in der maus gemacht, nicht auf dem pc. dieser bekommt das resultat lediglich zugeschickt afaik.
Potatoman schrieb:
@nurf: Du sagst ihr habt das so ähnlich eingebraucht und es funktioniert auch gut? Hättest du lust mir ein paar Tipps zu geben, wie ich das am besten anpacke, da du/ihr ja schon etwas mehr erfahrung damit gemacht habt?
Im Endeffekt möchtest du bestimmt eine asynchrone Architektur.
Das bedeutet beispielsweise die Logik läuft mit 60Hz und der Renderer mit 132.57 Hz (variabel).
Daraus folgt du musst zwischen den Zeiteinheiten der beiden Threads interpolieren.Weiterhin besteht noch die Möglichkeit einer synchronen Architektur, dann würde man zur Synchronisation zwischen den Threads sowas wie eine Barrier nutzen.
Zum Datenaustausch würde man DoubleBuffering verwenden, sprich der Logik-Thread arbeitet auf dem Backbuffer und der Renderthread arbeitet auf dem Frontbuffer.
Der Nachteil dabei ist, man hat nur so viele FPS wie der langsamste Thread.ein fester logiktick mit variablen render aufrufen ist glaube ich nicht mit renderthreads zu vermischen.
ein renderthread ist normalerweise nur der "worker" ohne dass man das design des main loops aendert. das design vom momentan gaengigen festen logikstep + render call wurde hier vor einiger zeit seitenweise diskutiert, falls du nachschauen willst
-
logikstep + render call wurde hier vor einiger zeit seitenweise diskutiert, falls du nachschauen willst
Das ist gut! Hättest du zufällig ein Link parat? Ansonsten gehe ich das Forum durchforsten
Im Endeffekt möchtest du bestimmt eine asynchrone Architektur.
Weder noch ..., der Plan war eigentlich die Daten zu sammeln, und dann den RenderThread zu starten. Während dessen der Thread noch fleißig am rendern ist, sammelt man schon wieder die nächten Daten. Nachteil ist natürlich, dass die Kerne erst optimal ausgenutzt werden, wenn beide Threads zeitgleich fertig werden.
Werd mich mal im Forum anmelden, gefällt mir hier^^
-
rapso schrieb:
Ansonsten erreicht man höhere Abtastraten, nur durch höhere Frameraten.
die abtastung wird in der maus gemacht, nicht auf dem pc. dieser bekommt das resultat lediglich zugeschickt afaik.
Wenn man also das Input-System deiner Wahl benutzt, bekommt man nicht nur die aktuelle Mausposition, sondern auch die letzten 10 Stück.
Das Input-System würde ich gerne auch kennen lernen.Normalerweise kriegt man sowas wie "MouseMoved" und damit hat man die aktuelle Position.
Wenn man nur einmal pro Sekunde die MausPosition auswertet ist die Bewegung entsprechend ruckelig.Analog bei der Tastatur, man bekommt KeyPressed und KeyReleased.
Was ist aber wenn die Dauer des Tastendrucks relevant ist ?
Um die KeyPressed-Dauer genau zu messen, muss das InputSystem häufig genug arbeiten.
Bei 1000Hz Polling-Rate ist die KeyPressed Auflösung übrigens 1ms.
-
Ich finde den Ansatz sehr gut und wir haben dieses Prinzip in unserer GameEngine bereits umgesetzt ...
Und habt ihr auch Performancemessungen gemacht?
Normalerweise wird ein Schnappschuss der Spielewelt gerendert. Dabei darf niemand "wackeln", die Spielelogik darf die Welt nicht updaten. Spielelogik und Renderer konkurrieren also um die Spielewelt, nur einer darf exklusiven Zugriff darauf haben. Auch wenn sie in unterschiedlichen Threads laufen, sind sie normalerweise sequentiell, da die Spielewelt das Synchronisationsobjekt ist.
-
@knivil:
Wenn die Spielewelt schnell genug kopierbar ist, sprich das Kopieren deutlich schneller geht als das Rendern, dann kann man den Schnappschuss von dem du sprichst auch wörtlich nehmen, und eben eine Kopie ziehen.Die Kopie kann man dann rendern, ohne dass man das Lock weiter halten muss.
Und natürlich muss man auch nicht die ganze Spielewelt kopieren, es reicht ja wenn man die für's Rendern relevanten Teile kopiert.
-
knivil schrieb:
Und habt ihr auch Performancemessungen gemacht?
Die gemessenen Frames per Second sind auch relativ pro Rechner.
Unser bisheriger Rekord sind 1700FPS im Test-Level.
Andere bei uns im Team mit PentiumIV und Geforce4 MX oder abstrusen Notebook-Grafikkarten sind froh, wenns grade flüssig läuft.
-
OMG ...
-
nurf schrieb:
Unser bisheriger Rekord sind 1700FPS im Test-Level.
Euer Clan heißt "German Elite Fighters", oder?
MfG SideWinder
-
SideWinder schrieb:
Euer Clan heißt "German Elite Fighters", oder?
Den gibts bestimmt, hat aber nichts mit uns zu tun.
Siehe USP
-
Ich werd mich einfach mal dran setzten und dann schauen wie es so läuft. Und dann, wenn es fertig ist, es folgender maßen testen:
1. Welche FPS erreiche ich ohne Mutltithreading und ohne Texturen/Shader sortierung.
2. Welche FPS erreiche ich mit Multithreading aber ohne Texture/Shader sortierung.
3. Welche FPS erreiche ich mit Multithreading und Texture/Shader sortierung.
4. Wie wirkt sich das kopieren von den Entities in den Stage auf die FPS aus.Danach sollte es mir wohl einfacher fallen, mich für ein system zu entscheiden. Sollte aber auch nur im geringen Maße eine bessere Performance zu sehen sein, hat sich der ganze Spaß auf jeden fall gelohnt. Sollte das nutzen eines Threads zum rendern jedoch langsamer als stures rendern sein, habe ich eine Menge Zeit in den Sand gesetzt
Aber eigentlich habe ich damit ja auch eine weunderbare Möglichkeit geschaffen, alles nach Texturen/Shader oder sonst was zu sortieren?