Seite 3 von 7

Re: meine derzeitige GameLoop

Verfasst: 29.08.2011 21:40
von ZeHa
@ Stargate, das ist natürlich auch richtig. Wenn (in einem tilebasierten Spiel) Deine Tiles 32 Pixel breit sind, aber ein Objekt sich pro Frame bereits mehr als 32 Pixel bewegt, dann kann das im Prinzip jederzeit auftreten ;)
Aber wer so etwas in seinem Spiel drin hat, der wird dafür so oder so dann eine Lösung finden müssen, egal welche GameLoop er verwendet :)

Re: meine derzeitige GameLoop

Verfasst: 29.08.2011 23:21
von PMV
ZeHa hat geschrieben:Das ist aber was völlig anderes - sag mir Bescheid falls ich mich irre, aber meinst Du nicht einfach nur die Parallelisierung der Grafik-Prozessoren?
Bescheid. :mrgreen:

Grafikkarten haben immer eine GPU. Für die 2-GPU-Lösung brauchts spezielle
Grafiktreiber, die nVidia und ATI jeweils für das entsprechende Spiel raus bringen
müssen. Grafikkarten, die direkt 2 GPUs eingebaut haben, sind halt von Haus
als 2 Grafikkarten an zu sehen. Und diese Variante gibs eigentlich immer nur mit
den Spitzenmodellen. Die 2. bringt nur was, wenn es entsprechende Treiber für
das Spiel gibt. Es gibt auch andere Möglichkeiten, um eine 2. Grafikkarte aus zu
nutzen, aber das ist nicht Sache des Spieleentwicklers, sondern Treibereinstellung.
:wink: Unter Multithreading ist immer die CPU gemeint, also auch bei DX11.
Wobei natürlich hier vorallem CPU-Aufgaben zwecks der Grafik im Fordergrund
stehen. Aber das nur am Rande, für uns PB-Jünger spielt das natürlich weniger
eine Rolle. Höchstens wenn OGRE mal DX11 kann. Ich wollte das nur mal erwähnen.
:wink:

Doch zurück zum eigentlichen Thema. Ich hab aktuell in meinem Spiel an vielen
stellen Erstellung neuer Objekte, Entfernen, Schleifen in denen die Objektpositionen
aktualisiert werden usw. Um die Gamelogik nun splitten zu können, muss ich
zwangsweise alles grafische bündeln. Erst wenn alles sauber getrennt ist, kann
ich überhaupt mit Threads anfangen. Da DX9 alls in einem Thread braucht, liegt
es daher nahe, auch einen entsprechenden Thread dafür zu starten. Ich werd mir
dafür ein kleines Eventsystem basteln, das alle Grafikaktionen wie erstellen und
entfernen von Entities behandeln kann. Die einen Threads schreiben rein, der
Grafikthread liest alles aus und verarbeitet dann. Nach dem alles verarbeitet ist, wird
gerendert. Während des Verarbeitens und Renderns können die Gamelogik-Threads
wieder neue Events generieren. Und wenn man es richtig macht, kann sogar
teilweise während des einlesens von Events weiter neue Events generiert werden. :wink:

So kann das Spiel mit 25 FPS laufen ... die Steuerung reagiert trotzdem flüssig,
Kollision bleibt sauber, Pathfinding lässt die Kerne glühen und die Bewegung
verläuft intern ohne sprünge, so das selbst wenn die FPS mal in den Keller fallen
sollte, das Spiel stabil weiter läuft. Aber vorallem, während des Renderns muss die
CPU nicht auf die Grafikkarte warten.

Und wen es interessiert: So lange wir keine "StaticGeometry" haben, läuft bei der
OGRE3D implementierung (DX9) von PureBasic mehr über die CPU, als einem lieb
ist. Da ist es sogar unumgänglich, einen eigenen Thread für die Grafikbefehle zu
haben. Und ich kann nur hoffen, das PB mir keinen Strich durch die Rechnung macht
durch einen Bug, der Auftaucht wenn ich Threads nutze. :coderselixir:

MFG PMV

Re: meine derzeitige GameLoop

Verfasst: 30.08.2011 00:34
von Thorium
Es gibt ne Menge Aufgaben, die sich mit teilweise enormem Performancezuwachs parallelisieren lassen.
In vielen Fällen macht es keinen Sinn Threads verschiedene Aufgaben zu geben, da Aufgabe B das Ergebnis von Aufgabe A braucht. Was aber Sinn macht ist es viele Threads an der gleichen Aufgabe werkeln zu lassen. Nur so reizt man Multicores aus.

Z.B. Kollisionserkennung. Warum nur ein Objekt testen, wenn ich jeden weiteren Core ein weiteres zur gleichen Zeit testen lassen kann?

Re: meine derzeitige GameLoop

Verfasst: 30.08.2011 01:22
von STARGÅTE
Das heißt, man könnte bei 5 Objekten (10 Paarungen) jeweils 5 Paarungen auf beide Kerne verteilen.
Diese müssten dann nur bei einer Kollision in eine gemeinsamme Liste schreiben welche Paarung eine Kollision erzeugt.

Problem ist aber, wie verteile ich die Paarungen, schließlich können nicht beide Theads gleichzeitig die Liste der Obejkte durchgehen. Und für je ein Paar ein Thread zu öffnen ist vermutlich eh noch langsammer oder ?

Das heißt, dort müsste man erst zwei Listen anlegen für beide Threads in denne dann die jeweiligen Paarungen vordefiniert werden.
In den Threads wird dann nur noch auf Kollision überprüft.

Werde das mal näher austesten...

Re: meine derzeitige GameLoop

Verfasst: 30.08.2011 02:37
von Thorium
STARGÅTE hat geschrieben:Das heißt, man könnte bei 5 Objekten (10 Paarungen) jeweils 5 Paarungen auf beide Kerne verteilen.
Diese müssten dann nur bei einer Kollision in eine gemeinsamme Liste schreiben welche Paarung eine Kollision erzeugt.

Problem ist aber, wie verteile ich die Paarungen, schließlich können nicht beide Theads gleichzeitig die Liste der Obejkte durchgehen. Und für je ein Paar ein Thread zu öffnen ist vermutlich eh noch langsammer oder ?

Das heißt, dort müsste man erst zwei Listen anlegen für beide Threads in denne dann die jeweiligen Paarungen vordefiniert werden.
In den Threads wird dann nur noch auf Kollision überprüft.

Werde das mal näher austesten...
Kollision war nur ein Beispiel. Aber ja, man muss immer überlegen wie man es aufteilen kann. Ich mache es so das der Mainthread Jobs an die anderen Threads verteilt, diese haben also keinen Zugriff auf solche Listen, sondern bekommen nur die Daten, die sie brauchen. Und liefern das Ergebnis beim Mainthread ab, der die Einzeljobs dann wieder zu einem Ergebnis zusammenführt.
Am besten funktioniert das natürlich, wenn große Datenmengen durchgeackert werden müssen. Die teilt man durch die Anzahl Cores und verteilt die Jobs als Teilmenge der Daten an die Threads. Funktioniert natürlich nur mit parallelisierbaren Aufgaben.

Ich hatte als POC eine pixelgenaue Kollisionserkennung gemacht, welche mit Collisionmaps in Bitform arbeitet, dort können sogar mehrere Threads an der gleichen Kollision arbeiten, lohnt sich aber nur wenn große Sprites da sind, da diese Kollisionserkennung sowieso bis zu 128 Pixel aufeinmal testet. Das heisst mit 4 Cores könnte sie 512 pixel gleichzeitig testen.

Re: meine derzeitige GameLoop

Verfasst: 31.08.2011 15:30
von 7x7
@Zeha
Ich programmiere keine Spiele, aber ich bin ein Freund von Multi-Threading.

Um dein Spielablauf-Beispiel parallelisieren zu können, würde ich ein Double-Buffering wie folgt wählen:

Code: Alles auswählen

Vereinfachtes Programmschema:

StartThread:
Do:
	Do:
	   Daten in Buffer Ready?
	Loop:
	
	Buffer sperren
	Rendere Daten aus Buffer
	Buffer freigeben
Loop:



StartMain:
Do:
        Berechne neue Spieldaten
        Do:
           Buffer1 freigegeben?
        Loop:
	     Spieldaten ablegen in Buffer1 und setze Ready-Flag
        
        Berechne neue Spieldaten
        Do:
           Buffer2 freigegeben?
        Loop:       
	     Spieldaten ablegen in Buffer2 und setze Ready-Flag

Loop: 
Während die Mainloop die Daten für den 2.Buffer berechnet, kann der Threadloop
die Daten des 1.Buffers bearbeiten und umgekehrt. Der "Mainloop" kann natürlich auch
ein Threadloop sein und von anderen freigegebenen Spielparametern abhängig sein usw.

Re: meine derzeitige GameLoop

Verfasst: 03.09.2011 11:05
von ZeHa
Damit müssen aber wieder beide Threads aufeinander warten, weil Du ja immer wieder die Daten vom einen Buffer in den nächsten kopieren mußt, damit der andere Thread damit weiterarbeiten kann. Das ganze wird dadurch sogar noch langsamer als wenn es single-threaded wäre.

@ Moderatoren:
Im Übrigen fände ich es ganz gut, wenn man diesen Multithreading-Krempel mal in einen eigenen Thread packen könnte (also im Prinzip ab AND51s erstem Posting). Die Diskussion an sich ist ja ok, und vielleicht findet sich ja irgendwann doch noch die Erleuchtung, aber in meinem Ur-Posting ging es eigentlich um die framerate-unabhängige Spieleprogrammierung und nicht um Multithreading.

Re: meine derzeitige GameLoop

Verfasst: 03.09.2011 11:21
von Thorium
ZeHa hat geschrieben:aber in meinem Ur-Posting ging es eigentlich um die framerate-unabhängige Spieleprogrammierung und nicht um Multithreading.
Das geht aber nicht aus dem Threadtitel hervor: "meine derzeitige GameLoop"
Das läd eher zum allgemeinen diskutieren über die Game Loop ein und wie man sie verbessern/erweitern kann, auf welche Art auch immer.

Re: meine derzeitige GameLoop

Verfasst: 03.09.2011 11:25
von ZeHa
Da hast Du auch wieder Recht, daher werde ich das mal kurzerhand ändern...

Re: framerate-unabhängige GameLoop

Verfasst: 03.09.2011 13:49
von PMV
Öhm, so eindeutig find ich den Titel jetzt erlich gesagt nicht. :wink:
Aber um auf das
Die Diskussion an sich ist ja ok, und vielleicht findet sich ja irgendwann doch noch die Erleuchtung,
einzugehen. Hab den Thread wieder gefunden, den ich meinte. Verlinkt
hab ich mal die resultierende Loop. http://www.purebasic.fr/english/viewtop ... 65#p346465
Wenn man eine Maus mit hohen Abtastraten hat, ist so ein Thread die
einzige Lösung, selbst bei Single-Core CPUs. Und man will seine Spieler
ja nicht verwehren, die teure Maus auch nutzen zu dürfen. :wink: Ich
würd dir im übrrigen empfehlen, den ganzen Thread mal durch zu lesen.



Ach ja ... und dann noch zu dem Timingproblem. Wenn ein Spiel unter eine
bestimmte Framerate fällt, wird es unspielbar. Selbst wenn es nur eine kurze
Zeit von vielleicht 5 Sekunden so ist, verliert der Benutzer die Kontrolle.
Dein Spiel wird zwar keine Kollisionsbugs haben, aber springen wird trotzdem
alles, und der Spieler kann nicht reagieren. Ich geh daher in meiner Gameloop
immer davon aus, das die Framerate über einem bestimmten Mindestwert
bleibt und ignoriere daher Probleme bei der Kollision. Wenn aber das Spiel
doch unter eine vordefinierte Framerate fällt, pausiere ich es einfach.

MFG PMV