#1 04.10.2005 17:24:16

artzuk
GodlikeMember
Ort: Leipzig
Registriert: 24.01.2005
Beiträge: 1164

fps - Berechnungsfehler?

Hi.
Ich hab nach Neos Tutorial mir ne Klasse für nen HighPerformanceCounter geschrieben. Diese Klasse soll gleich die fps ausrechnen.
Dazu hab ich einen array[1..100] (a) wo die ganzen Zeitdifferenzen von jeweils alten zum neuen Frame drin stehen. Im Frame 1 wird a[1] gefüllt, in Frame 2 a[2] usw .. bis es wieder im array bei 1 anfängt.
Mit den Zeiten will ich dann die fps erechnen - ich nehme den Mittelwert von 100 Werten, damit die fps-Anzeige nicht unleserlich stark zwischen mehreren Werten schwankt.

Ich weis nicht, ob ich da einen Fehler drin hab.
Fraps zeigt mir bei einfachen Samples vom SDK 999 fps an, das ist logisch. Ich habe auch nur ein einfaches Sample (5 Tiger, 1 lowpoly 3D-Schrift und noch 1 2D-Schrift) mit Managed DirectX geschrieben, aber Fraps zeigt mir nur ca. 150 an.
Das Komische daran ist, dass sich der Wert nicht ändert, wenn ich mal 5 solche "Head" (aus dem SDK) a 34.000 faces pro mesh rendere.

Meine Klasse gibt mir einen Wert so um die 4000 her. Also gar nichts vergleichbares mit den Fraps-Wert.

Hier der Code

Code: delphi

unit chpcounter;

interface

uses
  system.runtime.interopservices,
  cclasses;

type
  thighperformancecounter = class(tobject,ihighperformancecounter)
  private
   fbquerycounter: boolean;                  // Enabled

   ffelapsed     : single;                   // Elapsed
   fffps         : single;                   // frames per second

   ffscale       : single;                   // Time Scaling
   fatimes       : array[1..100] of int64;   // Time array (TimeNew-TimeOld)
   fiall         : int64;                    // sum of Time[1..100]
   filast        : int64;                    // Last Time

   finew         : cardinal;                 // read/write position for Times
  protected
  public
   // < constructor >
   constructor create;

   // < update Elapsed & fps >
   procedure update;

   property elapsed : single  read ffelapsed;
   property fps     : single  read fffps;
   property enablded: boolean read fbquerycounter;
  end;

  [dllimport('Kernel32.dll')]
  function queryperformancecounter( out lpperformancecount: int64): boolean; external;

  [dllimport('Kernel32.dll')]
  function queryperformancefrequency( out lpfrequency: int64 ): boolean; external;

implementation

constructor thighperformancecounter.create;
var
  freq: int64;
  i   : word;
begin
 inherited create;

 // disable/enable
 fbquerycounter := queryperformancefrequency( freq );

 // time scaling
 ffscale := 1.0 / freq;

 // some vars
 fiall  := 0;
 finew  := 1;
 filast := 0;
 for i := 1 to 100 do
 begin
  fatimes[i] := 0;
 end;
end;

procedure thighperformancecounter.update;
var
  icurrent: int64;
begin
 // Enabled?
 if not fbquerycounter then exit;

 // (DO) update Times-array & FiAll
 // new time
 queryperformancecounter( icurrent );

 // delete old time
 fiall := fiall - fatimes[finew];

 // new pos
 inc( finew );
 if finew >= 101 then finew := 1;

 // add new time to Times-array
 fatimes[finew] := icurrent - filast;

 // add new time to FiAll
 fiall := fiall + (icurrent - filast);

 // FiLast = iCurrent
 filast := icurrent;

 // (DO) Time elapsed
 // time elapsed
 ffelapsed := (icurrent - filast) * ffscale;

 // (DO) fps
 fffps := (1000000 / (fiall/100));
end;

end.



Ich danke für jede Hilfe.  :thx2:


Mein kleiner .NET Blog: http://artzuk-interactive.de/

Offline

 

#2 04.10.2005 18:24:38

DerPeer
GodlikeMember
Ort: Berlin
Registriert: 04.02.2005
Beiträge: 1291

Re: fps - Berechnungsfehler?

Hm... Wenn das erste mal ein Wert reingeschrieben wird, dann wird FaTimes[1]:=iCurrent-0, was wahrscheinlich ziemlich viel ist.
In den folgenden Aufrufen ist diese Differenz natürlich kleiner.
Kanns daran liegen?

Offline

 

#3 05.10.2005 05:16:28

artzuk
GodlikeMember
Ort: Leipzig
Registriert: 24.01.2005
Beiträge: 1164

Re: fps - Berechnungsfehler?

Stimmt - da hast du recht. Das änder ich mal.
Aber ich glaube das wird am Endwert nichts ändern, denn ich habe bei meinen Versuchen immer etwas gewartet, so dass eigentlich der ganze array mit "echten" Werten hätte gefüllt sein dürfen.


Mein kleiner .NET Blog: http://artzuk-interactive.de/

Offline

 

#4 05.10.2005 07:04:19

Back in Time
ProMember
Registriert: 08.04.2005
Beiträge: 130

Re: fps - Berechnungsfehler?

Machst Du Dir das nicht ein wenigh schwer?

(t1,t2,t3,t4..tn) / n <- sollte das nicht reichen?

Ausserdem taugen den Fraps-Werte in etwa genauso viel, wie n Kuhfladen unterm Schreibtisch.


If we would understand it we wouldn't call it code.

Offline

 

#5 05.10.2005 08:09:01

artzuk
GodlikeMember
Ort: Leipzig
Registriert: 24.01.2005
Beiträge: 1164

Re: fps - Berechnungsfehler?

Ich wills noch in ".. pro sekunde" umrechnen - so wären es noch Mikrosekunden.

- Was sucht eigentlich ein Kuhfladen unterm Schreibtisch? :mrgreen: ... aber gut zu wissen, dass Fraps mir wahrscheinlich die falschen Werte anzeigt.


Mein kleiner .NET Blog: http://artzuk-interactive.de/

Offline

 

#6 05.10.2005 12:16:21

Lotipats
UltraMember
Registriert: 17.05.2005
Beiträge: 395

Re: fps - Berechnungsfehler?

Wozu musst du dir die Werte immer merken?
Würde es nicht reichen, wenn du jede Sekunde festlegst, wie viel FPS du hattest, infolge der vergangenen Zeit und der Anzahl an Frames und fertig ist?

LOTIPATS

Offline

 

#7 05.10.2005 12:38:29

artzuk
GodlikeMember
Ort: Leipzig
Registriert: 24.01.2005
Beiträge: 1164

Re: fps - Berechnungsfehler?

Ich möchte einen Durchschnittswert der fps haben, weil sich die fps sonst unleserlich schnell ändern würden.
Wenn ich es jede Sekunde updaten soll, dann bräuchte ich a) nen Timer (mit den kann ich mich aber nicht wirklich anfreunden) und b) wäre das etwas ungenau.

Fällt jemanden was an meinen Code auf, also an meiner Formel. Wenn nicht, dann müsste es ja eigentlich stimmen.


Mein kleiner .NET Blog: http://artzuk-interactive.de/

Offline

 

#8 05.10.2005 13:45:25

Lotipats
UltraMember
Registriert: 17.05.2005
Beiträge: 395

Re: fps - Berechnungsfehler?

Wie unleserlich? Wenn man nur jede Sekunde das verändert wuerde ich das nicht unleserlich finden, weiterhin brauch man keinen Timer. Du vergleichst nur, nach jedem Rendern oder wann auch immer du willst, also in deiner Spielschleife, ob die Zeit seit dem letzten Update >=1 Sekunde beträgt und mit Hilfe der korrekten vergangenen Zeit (z.B: in Microsekunden) kannst du genau ausrechnen, wie wiele Frames es waren.
Beispiel, jedoch mit GetTickCount:

Code: delphi

if( (gettickcount()-timex>=1000) )then
begin
  fps:=frames*1000/(gettickcount()-timex);
  frames:=0;
  timex:=gettickcount();
end;



Wenn du das aber nicht willst, so kann ich dir bei deinem Problem leider nicht helfen.

LOTIPATS

Offline

 

#9 05.10.2005 17:28:43

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: fps - Berechnungsfehler?

GetTickCount ist viel zu ungenau, da nur Millisekunden (1/1000) gemessen werden. Mit QueryPerformanceCounter bist du schon auf dem richtigen Weg. Auf die schnelle würde ich sagen, dass du einfach nur vergessen hast FiAll mit FfScale zu multiplizieren.

Deine Methode mit dem Array finde ich recht sinnlos. Eine "genaue" Messung ist sowieso nicht möglich und die Anzeige dient ja nur für dich zur Orientierung. Ob es nun 90 oder 90.01 fps sind ist wirklich egal....wichtig sind die minimalen FPS!

Hier meine Update-Methode, ist zwar C++, aber ich denke das können ja zumindest alle wenigstens lesen.... wink

Code: delphi

void capplication::updatefps() 
{
  // vergangene Zeit bestimmen
  gettimeofday( &m_timeCur, 0 );
  m_dTimeElapsed =  (double)(m_timeCur.tv_sec  - m_timeLast.tv_sec  ) +
     ((double)(m_timeCur.tv_usec - m_timeLast.tv_usec)) / 1000000.0;
  m_timeLast = m_timeCur;


  // aktuelle Framerate mit Min, Max und Durchschnitt berechnen
  static int iCount = 0;
  static double dAvgTime = 0;
  static double dMinTime = 1.0;
  static double dMaxTime = 0.0;
  iCount++;
  dAvgTime += m_dTimeElapsed;
  dMinTime = dMinTime > m_dTimeElapsed ? m_dTimeElapsed : dMinTime;
  dMaxTime = dMaxTime < m_dTimeElapsed ? m_dTimeElapsed : dMaxTime;

  if (dAvgTime >= 1.0) {
    int iAvg = (int)((double)iCount / dAvgTime + 0.5);
    int iMin = (int)(1.0/dMaxTime + 0.5);
    int iMax = (int)(1.0/dMinTime + 0.5);
    if ((iAvg<0 || iAvg>999) || 
      (iMin<0 || iMin>999) || 
      (iMax<0 || iMax>999)) {
      strcpy(pFPSBufStr, "--- avg --- min --- max");
    }
    else {
                        // Zahlen in einen String schreiben
      sprintf(pFPSBufStr, "%3i avg %3i min %3i max", iAvg, iMin, iMax);
    }
    icount = 0;
    davgtime = 0.0;
    dmintime = 1.0;
    dmaxtime = 0.0;
  }    
}



gettimeofday ist quasi das Äquivalent zum QueryPerformanceCounter.
In m_timeCur.tv_sec sind die Sekunden und in m_timeCur.tv_usec die Mirkosekunden.
iAvg enthält am Ende die Durchschnittlichen FPS in der letzen Sekunde. iMin die minimalen und entsprechend iMax die maximalen. Den wichtigen m_dTimeElapsed - Wert hast du ebenfalls.

Coolcat


My software never has bugs. It just develops random features.

Offline

 

#10 16.10.2005 17:17:04

artzuk
GodlikeMember
Ort: Leipzig
Registriert: 24.01.2005
Beiträge: 1164

Re: fps - Berechnungsfehler?

So - das funktioniert jetzt auch und die fps sind auch "normal"
Meine 3D-Schrift zieht nur massig an Performance - hab da was falsch gemacht  wink


Mein kleiner .NET Blog: http://artzuk-interactive.de/

Offline

 

#11 16.10.2005 21:28:10

DerPeer
GodlikeMember
Ort: Berlin
Registriert: 04.02.2005
Beiträge: 1291

Re: fps - Berechnungsfehler?

Wie was 3D-Schrift? Wie machst Du das???

Offline

 

#12 17.10.2005 05:12:34

artzuk
GodlikeMember
Ort: Leipzig
Registriert: 24.01.2005
Beiträge: 1164

Re: fps - Berechnungsfehler?

Ich machs mit Managed DirectX - da funktioniert das  big_smile
Aber ich kann ja trotzdem mal den Code posten, wenn ich heute Abend zuhause bin.


Mein kleiner .NET Blog: http://artzuk-interactive.de/

Offline

 

#13 17.10.2005 16:49:23

DerPeer
GodlikeMember
Ort: Berlin
Registriert: 04.02.2005
Beiträge: 1291

Re: fps - Berechnungsfehler?

Nee, dann brauch ich ihn nicht. Danke vielmals.

Offline

 

#14 15.01.2006 20:15:02

TheDon
Member
Registriert: 14.01.2006
Beiträge: 32

Re: fps - Berechnungsfehler?

Hm.

Kommt drauf an wie gneau und wie oft man eine aktuelle FPS-Zahl benötigt, ich mach das aber meistens so (und für mich reicht das auch aus).

Code: delphi

// Delphi-Pseudocode

init:
  queryperformancefrequency(frequency);
  framenr := 0;
  counter := 0;
  queryperformancecounter(lastvalue)

update: //für jedes frame 1x aufrufen

  inc(framenr);
  queryperformancecounter(value);
  counter := counter + value - lastvalue;
  lastvalue := value;

  if counter >= frequency then // eine Sekunde ist um
    beign
       counter := counter - frequency;
       fps := framenr;
       framenr := 0;
    end;



Aber noch ne Anmerkung am Rande: Ich weiß von den Borland Newsgroups das QueryPerformanceCounter nicht auf jedem Computer funktioniert und manchmal blödsinn liefert.


TheDon

Offline

 

#15 15.01.2006 20:27:43

Neo
Member
Ort: Erfurt/Thüringen
Registriert: 31.01.2005
Beiträge: 78
Web-Seite

Re: fps - Berechnungsfehler?

Zitat:

Aber noch ne Anmerkung am Rande: Ich weiß von den Borland Newsgroups das QueryPerformanceCounter nicht auf jedem Computer funktioniert und manchmal blödsinn liefert.

Bezüglich des "Blödsinns" gibt es bei Microsoft einen entsprechenden Hinweis:
http://support.microsoft.com/default.as … -us;274323

Daher wenn man auf Nummer sicher gehen möchte stets parallel mit GetTickCount vergleichen und bei zu großen Schritten für ein Frame die Differenz von GetTickCount verwenden.

Neo

Offline

 

#16 15.01.2006 22:31:16

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: fps - Berechnungsfehler?

@TheDon:
Deine Methode hilft aber nicht, wenn du auch nur eine Bewegung zeitlich synchronisieren willst...


My software never has bugs. It just develops random features.

Offline

 

#17 19.01.2006 09:27:30

TheDon
Member
Registriert: 14.01.2006
Beiträge: 32

Re: fps - Berechnungsfehler?

Ja, das war auch nicht Ziel das zu zeigen, aber ich nehme nicht an, das es schwer sein wird, das entsprechend zu erweitern.

Aber ich hab eine ganz andere Frage. QueryPerformanceCounter arbeitet, wenn möglich mit dem Time-Stamp Counter der CPU, dieser wird pro Takt um eins erhöht, wie man ja auch an der Frequency erkennt, die die Taktfrequenz der CPU wiederspiegeln sollte. Aber wie wirken sich Programme ala Intel SpeedStep oder ähnliches aus, die die CPU manchmal langsamer drehen. Ich kann mir zwar nicht vorstellen, dass die CPU in einer 3D Umgebung unterbelastet ist, aber mich interessiert das im allgemeinen. Da ist ja die Frequenz variable, gibts schon jemand mit Erfahrung in diesem Bereich?

Achja, danke für den Link zur MS-Homepage


TheDon

Offline

 

#18 19.01.2006 10:43:37

Coolcat
ProGuru
Ort: Aachen, NRW
Registriert: 24.01.2005
Beiträge: 2780
Web-Seite

Re: fps - Berechnungsfehler?

Ich denke nicht das sich das auswirkt, weil dann wäre der Counter ja sinnlos. Vermutlich wird er dann einfach nur nicht so oft aktualisiert, aber dafür jedes mal korrigiert.
(ist aber nur eine vermutung)


My software never has bugs. It just develops random features.

Offline

 

Brett Fußzeile

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson