Direct3D9 & Fenster verdeckt = PresentationInterval funktioniert nicht?
-
dot schrieb:
(gibts erst in D3D9ex, aber du kannst ja mal schaun, vielleicht gibts S_D3DPRESENTATIONOCCLUDED ja doch auch schon in D3D9).
Hab nach deinem ersten Beitrag schon geguckt ob irgendwas ausser 0 (S_OK) zurückkommt: nope, immer schön 0, auch wenn das Fenster komplett verdeckt ist. Trotzdem danke, war ein guter Tip (wenn auch daneben *g*)
Dabei bin ich auch draufgekommt dass das Problem bei einem "hidden" Fenster selbstgebaut war, denn da ruf' ich Present() gleich gar nicht auf (weil das Destination-Rect "degenerated-or-empty" wird, und das check' ich vor dem Present()).
Das Verhalten bei "occluded" ist allerdings wie beschrieben, und ... naja, ich lass dann man den Frame-Rate-Limiter drinnen.
Aber eigentlich tust du da ja nicht raten ob das PresentationInterval eingehalten wurde sondern du limitierst deine FPS auf einen Maximalwert und gibst für etwaige übrige Zeit die CPU ab, was eine imo vernünftige Sache und afaik gängige Praxis ist...
Naja... kann man so oder so sehen.
Ich limitier das derzeit jetzt mit 8 msec. Was aber irgendwie doof ist, da je nach Bildschirminhalt mehr als 8 msec gebraucht werden. Der Wert ist zugegebenermassen sehr konservativ gewählt, bei ~16.66 msec pro Frame (@60Hz). Ich könnte mal 12 einstellen, aber viel weiter trau ich mich nicht raufgehen, denn ich will nicht riskieren auf Grund von Ungenauigkeiten bei der Zeitmessung (timeGetTime() ist ja nicht wirklich auf die Millisekunde genau) die Software künstlich zum "Stottern" zu bringen.hustbaer schrieb:
Hast du vielleicht eine Vermutung warum der von mir beschriebene Effekt bei Balloon-Help Bubbles auftritt? Das Ruckeln ist dann wirklich extrem, von 60fps runter auf 3-4...und z.T. stockt sogar die Sound-Ausgabe.
Ist zwar auch kein Problem im Produktivbetrieb, aber mich würde einfach interessieren was da so abgeht.Sry da kann ich nur raten, vielleicht liegts an der zu hohen CPU Auslastung!? :p
Klingt jedenfalls komisch.Welche hohe CPU-Auslastung?
Die GUI braucht ca. 20% (40% eines Cores) und dann läuft noch ein Prozess der nochmal ca. 13% (26% eines Cores) braucht.
Wobei mir noch nicht so ganz klar ist warum der 2. Prozess so viel CPU Zeit weglutscht, aber das ist mir erstmal egal.
-
hustbaer schrieb:
[...] denn ich will nicht riskieren auf Grund von Ungenauigkeiten bei der Zeitmessung (timeGetTime() ist ja nicht wirklich auf die Millisekunde genau) die Software künstlich zum "Stottern" zu bringen.
Du kannst ja einen besseren Timer verwenden
-
MSDN geht bei mir grad nicht - vermutlich irgend ein Problem mit den MS Servern für Österreich?
Aber ich schätze der Link wird auf QueryPerformanceCounter verweisen, und davon halte ich mich fern so lange es geht.
p.S.: einen wirklich guten Timer gibt's ja erst ab Windows 7. Obwohl ausprobiert hab' ich den noch nicht, aber was man in der Doku so liest klingt zumindest nicht schlecht...
-
hustbaer schrieb:
MSDN geht bei mir grad nicht - vermutlich irgend ein Problem mit den MS Servern für Österreich?
Also ich sitz im schönen Graz und hab kein Problem mit MSDN
hustbaer schrieb:
Aber ich schätze der Link wird auf QueryPerformanceCounter verweisen, und davon halte ich mich fern so lange es geht.
Richtig geschätzt, warum willst du dich denn unbedingt davon fernhalten!?
hustbaer schrieb:
p.S.: einen wirklich guten Timer gibt's ja erst ab Windows 7. Obwohl ausprobiert hab' ich den noch nicht, aber was man in der Doku so liest klingt zumindest nicht schlecht...
Ich bin ganz Ohr, wie heißt denn das Gute Stück?
Meinst du vielleicht dieses Animation Zeug: http://msdn.microsoft.com/en-us/library/dd756787.aspx!?
Klingt auf jeden Fall interessant, schaut aber auf den ersten Blick irgendwie 1:1 nach dem System aus was WPF verwendet. Wenn dem so ist dann ist das ja wohl eher eine ziemliche Highlevel Geschichte und nicht nur ein einfacher Timer!?
-
@dot
Google-Cache sei Dank: http://msdn.microsoft.com/en-us/library/ee662307(v=vs.85).aspx
Hatte das allerdings falsch in Erinnerung - die Auflösung ist auch nur so gut wie über timeBeginPeriod() eingestellt. Dafür bekommt man endlich mal nen 64 Bit Wert.p.S.: im Kernel gibt's den Timer mit 64 Bit eh schon ewigkeiten, aber MS hat es bisher anscheinend nicht für nötig gehalten den mal im Usermode zugänglich zu machen.
Richtig geschätzt, warum willst du dich denn unbedingt davon fernhalten!?
Weil ich gerne Timer verwende die ich problemlos verwenden kann. Um GetTickCount() oder timeGetTime() kann man sich einen Wrapper schreiben der aus den etwas mageren 32 Bit 64 Bit macht. Ist zwar lästig, und wie gesagt könnte die Auflösung besser sein, aber dafür hat men einen Timer der wirklich sehr stabil läuft.
QPC() dagegen ist ... eigen. Es driftet, und je nach Hardware springt es auch mal - auch mal gerne zurück. Oder bleibt kurz stehen.
(Mit driften meine ich, die Langzeit-Genauigkeit ist schlecht)Mit aktuellen Chipsets/CPUs vermutlich kein schlimmes Problem mehr, aber naja, ich hab einfach irgend wann mal beschlossen dass es besser ist sich davon fernzuhalten, und daran halte ich mich bisher.
Was man machen kann, ist QPC() und timeGetTime() zu kombinieren, aber das ist mir zu viel Aufwand. (Ich hab' noch keine fertige Implementierung, und bisher hat die Auflösung von timeGetTime() noch immer gereicht)
Gibt auch einige Artikel zu dem Thema, u.a. aus der Spiel-Programmierer-Szene, wo mehr oder weniger genau das beschrieben wird. Also mit timeGetTime() + QPC() einen Timer basteln der sozusagen das Beste aus beiden Welten vereint: gute Auflösung ohne Sprünge und mit gleichzeitig guter Langzeit-Genauigkeit.
-
Ok der Timer war mir neu. Von timeBeginPeriod() würd ich mich dagegen wirklich auf jeden Fall fernhalten
hustbaer schrieb:
QPC() dagegen ist ... eigen. Es driftet, und je nach Hardware springt es auch mal - auch mal gerne zurück. Oder bleibt kurz stehen.
(Mit driften meine ich, die Langzeit-Genauigkeit ist schlecht)Natürlich, das sind alles bekannte Verhaltensweisen (die Sprünge hängen afaik normal mit hohem PCI Bus Traffic zusammen, ich hatte noch nie wirklich ein Problem damit und wär mir nicht so sicher ob die Sache im aktuellen Jahrtausend überhaupt noch Relevanz hat). Und nichts davon spielt hier wirklich eine Rolle denn du willst nur kurze Zeitdifferenzen möglichst genau messen, also genau das wofür QPC gedacht ist!? Wer QPC als absolute Uhr verwendet ist selber schuld^^
Hier gibts nen guten Artikel dazu (Google Cache ftw da gamedev.net grad umbaut)
-
dot schrieb:
Ok der Timer war mir neu. Von timeBeginPeriod() würd ich mich dagegen wirklich auf jeden Fall fernhalten
Äh. Hast du mal ausprobiert wie hoch der Impact ist?
Ich würde sagen: im aktuellen Jahrtausend hat das keine Relevanz mehr.
Davon abgesehen macht D3D9 im Windowed Mode mit PRESENTATION_INTERVAL_ONE - laut Doku zumindest - intern sowieso ein timeBeginPeriod(), vermutlich mit period = 1. Von daher ... egalhustbaer schrieb:
QPC() dagegen ist ... eigen. Es driftet, und je nach Hardware springt es auch mal - auch mal gerne zurück. Oder bleibt kurz stehen.
(Mit driften meine ich, die Langzeit-Genauigkeit ist schlecht)Natürlich, das sind alles bekannte Verhaltensweisen (die Sprünge hängen afaik normal mit hohem PCI Bus Traffic zusammen, ich hatte noch nie wirklich ein Problem damit und wär mir nicht so sicher ob die Sache im aktuellen Jahrtausend überhaupt noch Relevanz hat). Und nichts davon spielt hier wirklich eine Rolle denn du willst nur kurze Zeitdifferenzen möglichst genau messen, also genau das wofür QPC gedacht ist!? Wer QPC als absolute Uhr verwendet ist selber schuld^^
Vielleicht hab' ich das noch nicht ausreichend klar rübergebracht: ich verwende ungern Dinge, wo ich mir etwas Gedanken machen muss, was ich für "unnötig" halte. Und bei einem Timer halte ich es für unnötig sich über eventuelle Sprünge Gedanken machen zu müssen, bzw. bei einem "general-purpose" Timer über schlechte Langzeit-Genauigkeit.
Die Langzeit-Genauigkeit wäre im Fall Frame-Zeiten messen zwar egal, aber die Sprünge wären doof. Von daher lieber timeGetTime().
-
hustbaer schrieb:
Äh. Hast du mal ausprobiert wie hoch der Impact ist?
Um ehrlich zu sein nicht weil ich timeGetTime() praktisch nie verwende
Afaik verändert timeBeginPeriod() den Heartbeat des Schedulers, wenn du mich fragst ist es im aktuellen Jahrtausend sehr viel eher relevant wenn ich generell die Anzahl der Context Switches pro Sekunde drastisch erhöhe (wär das vielleicht ein möglicher Grund für dein ruckelndes Tooltip!?) als wenn ich auf einigen wenigen älteren Rechnern vielleicht jumps aufgrund von Hardware bugs habe mit denen man noch dazu relativ leicht umgehen kann (Zeitdifferenz begrenzen).hustbaer schrieb:
Davon abgesehen macht D3D9 im Windowed Mode mit PRESENTATION_INTERVAL_ONE - laut Doku zumindest - intern sowieso ein timeBeginPeriod(), vermutlich mit period = 1. Von daher ... egal
Richtig, dafür gibts D3DPRESENT_INTERVAL_DEFAULT
-
wär das vielleicht ein möglicher Grund für dein ruckelndes Tooltip!?
Wenn du das ernst meinst, dann ... eueueu.
Nein, das ist ganz sicher nicht der Grund.
Glaub mir, ich habe ausreichend Erfahrung mit timeBeginPeriod(), und es spielt überhaupt keinen Walzer.
Ich kann dir keine genauen Zahlen sagen, aber ich weiss aus Erfahrung dass die Systemleistung dadurch nicht wesentlich sinkt.
Mag sein dass Berechnungen in engen Schleifen dadurch um 2-3% langsamer werden, aber für unsere Anwendungen spielt das wirklich keine Rolle.Richtig, dafür gibts D3DPRESENT_INTERVAL_DEFAULT
Weiss ich. Was meinst du warum ich das nicht verwende?
-
hustbaer schrieb:
Wenn du das ernst meinst, dann ... eueueu.
Naja was nur so ein spontaner Gedanke, was besseres ist uns immerhin noch nicht eingefallen...
hustbaer schrieb:
Glaub mir, ich habe ausreichend Erfahrung mit timeBeginPeriod(), und es spielt überhaupt keinen Walzer.
Nachdem ich selber keine Erfahrung damit hab glaub ichs dir, ich versuch ja auch nicht dir QPC() zu verkaufen, ich fand nur die Diskussion interessant weil bei diesen timing Geschichten ist am Ende irgendwie immer ein wenig Schwarze Magie im Spiel hab ich den Eindruck