Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
HI,
ich such nach ner Möglichkeit die FPS meines Programmes auf 100 zu beschänken. Das hab ich auch ganz gut gelöst:
Code:
DeltaTime := GetTickCount - StartTime;
if DeltaTime < 1000/MAX_FPS then
begin
sleep(round(1000/MAX_FPS-DeltaTime));
DeltaTime :=round(1000/MAX_FPS);
end;
StartTime := GetTickCount;
Aber da sleep sehr ungenau ist, hab ich anstatt 100FPS immer um die 80. Dann hab ich DAS gefunden. Damit funktionert es 1a, aber es läuft immer mit 100% CPU-Last und das is ja dann auch nich Sinn und Zweck der Sache. Also nun die Frage: gibts ne Funktion oder n Timer der genauer als sleep is, aber trotzdem die CPU nich so stark belastet?
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Einige Leute behelfen sich in dem sie das ganze in eine loop packen und sleep auf 1msec setzen.
Alternativ Zeit/2 oder ähnliches, um performance zu sparen.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
das funzt auch net, solbald ich irgendwo sleep(1) drin hab bricht die Framerate auf kanpp 60FPS ein, das liegt daran, das mien sleep immer vielfaches von 16ms hat. 1000/16 = 62,5. Ichhab das mal durchgemessen:
Code:
sleep(1) = 16ms
sleep(10) = 16ms
sleep(17) = 32ms
sleep(30) = 32ms
usw...
deshalb such ich ja auch ne alternative zu sleep. Oder hat mein PC ne macke weil er das net genau macht?
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2623 Wohnort: Berlin
Programmiersprache: Go, C/C++
Nein das ist korrekt, 12-16 Milisekunden braucht das sleep, Windows halt.
Linux hat ein Microsekunden genaues sleep, also ist es eher was Implementierungstechnisches, vielleicht findest du eine Windows spezifische Alternative im Netzt. Sonnst kannst du nur die Schleife komplexer machen, um unnötige sleeps zu vermeiden.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Di Dez 27, 2005 12:44 Beiträge: 393 Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Hallo,
16ms ist glaub ich die minimale Zeit, die Windows einem Prozess zuordnet.
Wenn du also einen Prozess 'schlafen' legst, dauert es mind. 16 ms bis der Scheduler wieder zu diesem Prozess zurückkehrt.
Warum willst du die Framerate unbedingt auf 100 FPS beschränken?
Eine FPS über der Bildwiederholfrequenz macht doch kaum einen Sinn, es sei denn du hast einen Monitor, der mehr als 100 Hertz hat...
Warum aktivierst du nicht einfach 'vertikale Synchronisation' bei deinem Grafikkartentreiber? ( müsste bei den meisten Treibern voreingestellt sein )
Viele Grüße
dj3hut1
_________________ Wenn Gauß heute lebte, wäre er ein Hacker. Peter Sarnak, Professor an der Princeton University
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
GetTickCount hat eine Auflösung von 16 Millisekunden. Das ist leider vollkommen normal. Ich denke wenn du dein Sleep(1) mal mit dem Performancecounter misst, dann dürftest du Werte zwischen ~1.09 und 1.99 raus bekommen. Falls du das schon machst würde mich mal aus reinem Interesse dein System (cpu, os) interessieren.
Du solltest vor allem auch darauf achten, dass du nicht stumpf Sleep machst. Sleep(0) sorgt dafür, dass andere Prozesse arbeiten können, wenn sie das wollen. Wenn die viel machen wollen, dann können das einige ms werden. Wenn du weißt, dass du 4 ms warten müsstest dann warte auch 4. Mehr könnten es eventuell trotzdem werden. Denn wenn das Zeichnen deines Frames bereits fast vollkommen die Zeit beansprucht hat und du dann stumpf 1 ms wartest, dann würde du weiter bremsen als notwendig/beabsichtigt. Die ZielFPS sollte die FPS sein auf die du maximal bremmst. Es wird sich niemand beschweren wenn das Programm 2-3 fps schneller ist.
Oben drauf kommt noch, dass du auf 100 fps bremsen willst. Bei 100fps wirken sich Schwankungen deutlich stärker aus als bei 30-50. Und Filme kommen bereits locker mit < 30 Bildern in der Sekunde aus.
PS: Vergiss alternative Implementationen von Sleep. Sleep weißt den TaskSheduler von deinem Windows an anderen Thread zeit zu geben. Im Zweifel wäre das der Leerlaufprozess der dann deine CPU schlafen lägt. Alles was du im Netz finden kannst wird mit BusyWaiting arbeiten und verbrät nahezu immer 100% CPU last oder arbeitet mit sleep etc. Falls sie die CPU schlafen legen, dann aber auch für alle anderen Threads. Durch all diese Sachen hast du meiner Meinung nach rein gar nicht gewonnen. Zu mal ich das Problem sowieso in den 100fps und dem GetTickCount sehe.
[edit] Vertikale Synchronisation arbeitet meines wissens nach aber auch wieder nach dem Busy Waiting Prinzip. Wodurch man zwar die FPS beschränken kann aber wohl keine Leistung einsparrt.
[edit] Vertikale Synchronisation arbeitet meines wissens nach aber auch wieder nach dem Busy Waiting Prinzip. Wodurch man zwar die FPS beschränken kann aber wohl keine Leistung einsparrt.
Meiner Erfahrungen nach ist das nicht zutreffend. Denn wenn ich VSync (WGL_EXT_swap_control) aktiviere fällt die Prozessorauslastung von ca. 50% auf knapp unter 10%.
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,
mit VSync gehts, daran hatte ich gar nich mehr gedacht. Damit ist das Problem gelöst. (CPU-Last geht auch fast auf 0%).
Noch ne andere Frage: wenn GetTickCount auch in 16ms Intervallen arbeitet, ist es dann überhaupt ratsam das ganze für TimeBasedMovement zu verwenden? Wie macht ihr das bei euren Programmen?
Ich glaube man kann mit einem Befehl (jedenfalls unter windows) das Intervall auch selber einstellen.
Bzw. es gibt auch einen genaueren counter unter Windows. Wieß aber nicht mehr wie der heißt.
Aber 16 ms reichen eigentlich vollkommen aus. Würde eine Frequenz von 62,5 hz ergeben.
Wenn du dann noch die fps auf >62,5 reduzieren kannst ist es optimal. Wenn nicht is es auch egal,
nur wird dann die selbe Position öfters gezeichnet. Das sieht aber so oder so kein Mensch. ^^
Auf meinem System ist das Intervall sogar nur 1 ms groß, ohne dass ich irgendetwas eingestellt hab.
Kann sein dass das von der CPU Power abhängt.
Under Windows platforms, Microsoft strongly discourages using the TSC for high-resolution timing for exactly these reasons, providing instead the Windows APIs QueryPerformanceCounter and QueryPerformanceFrequency. [2] Even when using these functions, Microsoft recommends the code to be locked to a single CPU. Under Linux, similar functionality is provided by reading the value of CLOCK_MONOTONIC clock using POSIX clock_gettime function.
Registriert: Di Dez 27, 2005 12:44 Beiträge: 393 Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Für TimeBasedMovement mache ich die Bewegung direkt von der aktuellen Framerate abhängig.
Für die genaue Berechnung der Framerate zähle ich immer die Anzahl der Frames der letzten Sekunde ( dazu packe ich die timestamps der Frames in eine Queue )
Mein FPSCounter würde so aussehen ( in C++ ) :
Code:
//fpscounter.h
class FPSCounter
{
protected :
static queue<clock_t> timeQ;
public :
static void update();
static int getFps();
};
//fpscounter.cpp
queue<clock_t> FPSCounter::timeQ;
void FPSCounter::update()
{
clock_t t1 = clock();
while ( ( t1 - timeQ.front() ) > 1000 )
{
timeQ.pop();
}
timeQ.push(t1);
}
int FPSCounter::getFps()
{
//Startframerate
if ( timeQ.empty() || timeQ.back() == timeQ.front() ) return 100;
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
VSync. Okay. Überredet. Ich kenne es zwar anders aber das ist auch schon eine Weile her. Wobei man das auch immer noch im Treiber einstellen kann und das zählt mehr als eine Anwendung. Bzw je nachdem was man macht können 60 fps auch schon recht viel sein. Hatte mal ein online rollenspiel welches selber auf ca. 30 fps gebremmst hat und da gabs überhaupt keine Probleme. Bei einem ego shooter sind 30 aber schon gut belastend für die Augen.
Zum Auslesen der Zeit. Da kommt es meiner Meinung nach auch wieder darauf an was du machst. Bei Frameraten < 60 ist GetTickCount wohl ausreichend. Es sei denn du hast eine extrem konstante Bewegung. Bei extrem konstanten bewegungen bzw fps > 60 dürften sich die ungenauigkeiten schon deutlicher äußern. Alternativ dazu wie andreas schon gesagt hat. QueryPerformanceFrequency und QueryPerformanceCounter. Wobei diese Funktionen auf Mehrkernsystemen nicht zuverlässig sind. Da jeder Kern einen eigenen Counter hat. Und die Werte können sich durchaus unterscheiden. Von/Für amd gibts aber ein tool was das behebt. Bei Intel weiß ich das nicht.
dj3hut1: Wenn du die Anzahl der Frames der letzten Sekunde für deine Berechnungen benutzt, ist es dann nicht so, dass sich große Veränderungen nur "schleichend" im Laufe einer Sekunde auswirken. Also sagen wird mal auf einen Schlag verdoppelt sich die Anzahl der Objekte bzw Effekte. Die jetzt gerenderten Bilder bräuchten dann doppelt so lang. Allerdings wird der Durchschnitt noch durch die schnellen Bilder positiv beeinflusst. Also mit anderen Worten. Diese Methode ist zwar nicht so anfällig was Ungenauigkeiten beim Messen angeht aber dafür auch etwas träge bei Inhaltsschwankungen?
Registriert: Di Apr 29, 2008 18:56 Beiträge: 1213
Programmiersprache: Delphi/FPC
Gut, dann bleib ich bei meinem GetTickCount, da es bis jetzt eig. keine Schwierigkeiten gibt. Das komische ist nur, dass wenn ich das vSync aus mach und das Game mit 100% läuft meine DeltaTime manchmal 0 ist, aber das Spiel läuft trotzdem normal weiter, obwohl ich alle Bewegungen von der DeltaTime abhängig gemacht hab. oO
Registriert: Di Dez 27, 2005 12:44 Beiträge: 393 Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Hallo Lossy,
ja stimmt.
Falls die Framerate rapide einbricht, wird die Geschwindigkeit nicht sofort angepasst, sondern es gibt dann innerhalb einer Sekunde einen 'weichen' Übergang.
Falls sich die Framerate ständig schnell ändern würde, wäre die Methode wahrscheinlich nicht gut geeignet...
Man kann die 'Trägheit' allerdings anpassen, indem man das Zeitintervall in der update-Methode und unten in der Berechnung ( in diesem Fall 1000 ) runtersetzt, allerdings würde die Genauigkeit des Counters dann schlechter werden.
Mitglieder in diesem Forum: 0 Mitglieder und 8 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.