buffern von opengl states
-
Scorcher24 schrieb:
Trotzdem sollte man "leere" Aufrufe vermeiden wenn es geht.
Inwiefern die OpenGL Implementationen hier eine Optimierung haben, wissen wir ja nicht.Naja. Jeder Hersteller will ne schnelle OpenGL Implementierung haben. Daher gehe ich mal davon aus, dass Dinge die so einfach zu optimieren sind auch optimiert werden.
Vor allem wenn die Optimierung so "billig" ist, dass sie auch Programme die sie nicht benötigen würden (weil sie keine redundanten State-Changes machen) kaum ausbremst. Macht IMO keinen Sinn das in jeder OpenGL Anwendung zu wiederholen, wenn man es auch in der OpenGL Implementierung machen kann.
Man muss auch sagen, dass viele State Changes Client seitig sind und das sind die billigsten die man kriegen kann.
Server Side changes sind entsprechend teurer.
Kommt also drauf an was man ändert.So lange sich alles auf der selben Maschine abspielt sollte das doch keinen Unterschied machen, oder? (Also so lange man mit einem "lokalen" Terminal arbeitet, das direkt auf die Grafikkarte zugreifen kann und wird)
-
Server ist in dem Fall die Grafikkarte. Ein Server Side Change wäre als bsp. glBindProgram oder glBindBuffer etc.
-
OK. Wobei ein teurer Server-Side-Change genauso Client seitig in der OpenGL Implementierung gepuffert werden kann, wie man den OpenGL Call in der eigenen Applikation puffern kann.
-
hustbaer:
Ich meinte in meinem letzten Beitrag deinen ersten Fall. Aber allgemein würde auch der ON ON Fall auftreten.Und ja, ich würde mit eine statische Klasse bauen über die ich alle States setzen würde. Und vor wirklichen Rendervorgängen würde ich dann eine Funktion aufrufen die die echten Veränderungen zu OpenGL überträgt.
Scorcher24:
Erstmal nur Grundlagen wie FBOs, VBOs, PBOs... Diese aber etwas handhabbarer.Also z.b.
gl::fbo myFbo; myFbo.init(256, 256); myFbo.createTexture(0); myFbo.activeSlot(0); myFbo.begin(); //... OpenGL rumkritzeln(TM) myFbo.end(); GLuint texture = myFbo.textureId();
finde ich eleganter und weniger Fehleranfälig als die ganzen OpenGL aufrufe. Vor allem weil auch das aktivieren mehrerer rendertargets und das anschließende Erzeugen von Mipmaps etc... alles von der Klasse übernommen wird.
Bei dem VBO teil bin ich noch am basteln. Deshalb kam auch erst meine Frage wegen den State changes auf.
-
Ich bin kein OpenGL Guru, ich arbeite nur schon ne Weile damit. Und ich habe halt viele Diskussionen dazu gelesen und sehr viele Seiten zu OpenGL gewälzt. Manche davon waren etwas älter leider. Aber ich denke dass sehr vieles davon auch heute noch gültig ist. Wie die Implementationen von ATI und NVIDIA hier arbeiten, das wissen wir halt wirklich nicht 100%. Böse Zungen sagen auch, dass die nur in DirectX Calls umgewandelt werden und OpenGL quasi als solches gar nicht vorhanden ist.
Auch der glDEBugger zählt renundante State Changes auf und rät diese zu minimieren. Ich finde man sollte das einfach mal glauben.
http://www.abload.de/img/gebugao6n.png@Osbios
Jo, so eine Klasse habe ich auch:
http://code.google.com/p/nightlight2d/source/browse/trunk/NightLightDLL/NLRenderToTexture.cppIst auch gut sowas zu machen.
Auf der anderen Seite:
Welche OpenGL Version programmierst du? 3D?
Gut, ich mach nur 2D und komme mit mit relativ wenigen State Changes aus.
Ist halt die Frage des nutzens. Schlecht ist es aber auf keinen Fall.
Ich behaupte mal dass ein if ( m_blend_set ) billiger ist als ein glGet.
-
Das meiste war bis jetzt 2d. Da konnte ich noch ohne Probleme mit begin end arbeiten. Ich benutzt Version 2.x OpenGL. Mehr gibt mein alte Karte auch nicht her.
-
Nur mal so ne Frage: Hast du denn ein Performanceproblem?
-
Wenn ich nicht auf solche Sachen achte bestimmt sehr bald.
Bestimmte Sachen sollte man halt von Anfang an beachten, weil man später sonnst alles wieder umbauen muss.
Außerdem kann ich anschließend mittels dieses zwischengeschalteten Puffers erst Performancetest machen und so sehen wie viel es wirklich ausmacht. (Naja, halt auf meinem System)Hier hat leider noch keiner Zahlen zeigen können.
Und wenn es so sehr auf die Performance gehen sollte ist es sehr viel einfacher dieses ganze Problem mittels einer State-Klasse zu handhaben und in den restlichen Lib-Teilen nicht mehr penibel darauf achten zu müssen.
-
dot schrieb:
Nur mal so ne Frage: Hast du denn ein Performanceproblem?
Das war die wichtigste Frage bisher
Warum mit Optimierungen anfangen (bei denen man noch nicht mal weiss, ob sie überhaupt was bringen), wenn keine Performanceprobleme bestehen. Und falls letztere vorhanden sind sollte man erstmal den code identifizieren, der den Flaschenhals darstellt.P.S.: Es gibt auch noch glIsEnabled - nicht alles muss über glGet laufen.
-
Steht glIsEnabled nicht auf der selben Stufe wie glGet? Ist ja nur nen anderes namens-schema für eine Funktion die einen BOOL zurückgibt. Aber am Ende macht sie das selbe: Sie erzwingt alle Kommandos in der Pipeline bevor der Code ausgeführt wird.
http://www.mesa3d.org/brianp/sig97/perfopt.htm#MiscMan sollte solche Funktionen während des Renderns halt vermeiden wo es nur geht und wenn das alles in der Update Funktion machen.
Im Gegensatz zu euch empfinde ich das auch nicht als unnötige Microoptimierung, sondern finde es gut wenn man sich darüber vorher Gedanken macht und gewissenhaft plant. Denn das nachher wieder alles umzuschreiben ist mehr Arbyte.
-
Also ich glaube nicht dass glGet wirklich bremst, dazu müsste eine OpenGL Implementierung schon recht doof sein. Ich denke viele dieser Tips sind einfach nichtmehr wahr, und halten sich nur weil jeder sie weitererzählt ohne es selbst ausprobiert zu haben.
-
Ich könnte mir vorstellen dass der CPU seitige Overhead unter Umständen relevant werden könnte. Vor allem die glBind*() calls haben einen evtl. nicht zu vernachlässigbaren Overhead (nicht umsonst hat NVIDIA eine Extension entwickelt um ohne glBind*() arbeiten zu können). Was reine State Changes angeht so liest man aber eigentlich überall dass das heutzutage praktisch nichtmehr relevant ist (glGet() sowieso nicht, warum sollte das einen Flush verursachen, damit liest du doch nur CPU seitigen API State aus, natürlich gibts Function call Overhead, aber das ist denk ich mal klar). Lediglich Shader und Texture Switches können kosten, der Rest ist wohl eher vernachlässigbar. Viel wichtiger als redundante State Changes vermeiden ist heute wohl vernünftiges Batching. Wie immer bei solchen Dingen: Die Antwort hängt von deiner Anwendung ab, wenn dus genau wissen willst frag deinen Profiler...
-
treiber guarden state changes eigentlich nicht. Das problem ist auch nicht ein einziger state change mehr oder weniger, sondern wenn es ueberhaupt welche gibt.
Die GPU pipelines sind so aufgebaut, dass sie einen state haben und anhand dessen viele arbeiten vorllbringen koennen, ob dann die informationen in einem oder 10 drawcalls ankommen ist es egal, die pipeline arbeitet sie eh immer in der richtigen reihenfolge ab.
will man aber einen state wechseln, kann es sein, dass es einen pipeline flush gibt (also gewartet wird bis alles vorherige fertig ist), dann ein state umgesetzt wird und dann weiter gearbeitet wird.aus diesem grund, wenn man das letzte rausholen will, sollte man fuer states optimieren, aus ebenfalls diesem grund kann ein treiber programmierer davon ausgehen, dass er nicht selbst noch states guarden muss, weil ein faehiger programmierer auf der anderen seite das eh schon besser geloest hat.
welche states wie teuer sind haengt dabei stark von der hardware ab, bei mancher muss der treiber per hand caches flushen, bei mancher flushen ganz harmlos aussehende states die ganze gpu, etc.