PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : API-Calls, Flaschenhals der Zukunft?


Asmodeus
2005-10-22, 13:13:01
Auf absehbare Zeit wird in der 3D-Computergrafik der Trend weiter anhalten nach "Photorealismus" zu streben. Dafür müssen die 3D-Szenarien immer detailreicher und vor allem variantenreicher werden. Und gerade da liegt in Zukunft meiner Meinung nach das Problem. Um eine möglichst hohe Performance beim Darstellen einer Szene zu erreichen sollte möglichst viel Geometrie mit möglichst wenigen API-Calls gerendert werden. Je variantenreicher eine Szene jedoch wird, umso mehr API-Calls werden benötigt. Und da liegt wohl das Problem. Die Verarbeitung von API-Calls ist immer auch Aufgabe der CPU. Und wie schon in einem früheren Thread im Programmierforum besprochen wurde, können API-Calls nicht auf mehrere CPU-Kerne verteilt werden. Nun geht der Fortschritt bei der Weiterentwicklung der CPUs in den nächsten Jahren aber wohl vor allem über die Steigerung der Anzahl der CPU-Cores. Nur davon dürfte der Durchsatz an maximalen API-Calls so gut wie nicht profitieren. D.h. auf diesem Gebiet wird sich in nächster Zeit kaum etwas tun. Oder sehe ich die ganze Sache zu pessimistisch und es zeichnen sich doch Lösungen für die nächste Zeit ab?

Gruss, Carsten.

Demirug
2005-10-22, 13:35:40
Gerade bei D3D10 ist eines der Ziele die Anzahl der Calls zu reduzieren.

Als Beispiel wird aufgeführt das man für das "Render To Cube" alle 6 Seiten auf einen Schlag rendern kann.

Asmodeus
2005-10-22, 13:41:08
Gerade bei D3D10 ist eines der Ziele die Anzahl der Calls zu reduzieren.

Als Beispiel wird aufgeführt das man für das "Render To Cube" alle 6 Seiten auf einen Schlag rendern kann.

Wie viele wissen beschäftige ich mich ja mit der Visualisierung von Landschaften, und gerade auf diesem Gebiet muss noch viel vorangebracht werden was Komplexität und Variantenreichtum anbelangt um dem "Photorealismus" nahe zu kommen. Und da muss ich leider sagen, beim Rendern von natürlich wirkenden Pflanzen nützt mir ein "Render To Cube" einfach gar nichts.

Gruss, Carsten.

Coda
2005-10-22, 13:48:40
Es wurden auch andere Sachen verbessert, es gibt z.B. constant-arrays in D3D10 wenn mich nicht alles täuscht.

Demirug
2005-10-22, 13:55:17
Es wurden auch andere Sachen verbessert, es gibt z.B. constant-arrays in D3D10 wenn mich nicht alles täuscht.

Ja, die gibt es. Wobei man dadurch die Calls nicht unbedingt reduzieren kann.

Das Prinzip der Stateblocks soll aber angeblich auch verbessert worden sein. Damit kann man dann schon Calls sparen.

Wie viele wissen beschäftige ich mich ja mit der Visualisierung von Landschaften, und gerade auf diesem Gebiet muss noch viel vorangebracht werden was Komplexität und Variantenreichtum anbelangt um dem "Photorealismus" nahe zu kommen. Und da muss ich leider sagen, beim Rendern von natürlich wirkenden Pflanzen nützt mir ein "Render To Cube" einfach gar nichts.

Das war ja nur ein Beispiel. In Verbindung mit Instancing, dynamic Branching und nahezu unlimitierten Shaderresourcen (wobei das wohl noch nicht ganz sicher ist) kann man mit einem Call einen ganzen Wald unterschiedlicher Bäume auf den Bildschirm bringen.

Asmodeus
2005-10-22, 14:09:50
Ja, die gibt es. Wobei man dadurch die Calls nicht unbedingt reduzieren kann.

Das Prinzip der Stateblocks soll aber angeblich auch verbessert worden sein. Damit kann man dann schon Calls sparen.



Das war ja nur ein Beispiel. In Verbindung mit Instancing, dynamic Branching und nahezu unlimitierten Shaderresourcen (wobei das wohl noch nicht ganz sicher ist) kann man mit einem Call einen ganzen Wald unterschiedlicher Bäume auf den Bildschirm bringen.

Nein, genau das kann man eben leider nicht. Machen wir es doch einfach an einem aktuellen Beispiel meiner Arbeit fest. Wie genau willst Du denn einen Wald mit über einer Milliarde Einzelpositionen bestehend aus gut 100 verschiedenen Pflanzenmodellen (vom kleinen Gänseblümchen bis zur großen Buche) wobei jedes Pflanzenmodell zwischen 500 und 130.000 Dreiecke besitzt selbst mit all Deinen aufgezählten Features in einem Call rendern? Wobei dann auch noch die Frage ist, wieso willst Du, verursacht durch nur einen Call der GPU die ganze Cullingarbeit überlassen?

EDIT: Weiterhin besteht dann auch noch die Frage des LOD? Wie soll mit einem Call realisiert werden, dass im Nahbereich die volle Komplexität der Pflanzen angezeigt wird und im Fernbereich z.B. nur noch eine Billboard- oder Point-Approximation?

Gruss, Carsten.

Demirug
2005-10-22, 14:23:42
Nein, genau das kann man eben leider nicht. Machen wir es doch einfach an einem aktuellen Beispiel meiner Arbeit fest. Wie genau willst Du denn einen Wald mit über einer Milliarde Einzelpositionen bestehend aus gut 100 verschiedenen Pflanzenmodellen (vom kleinen Gänseblümchen bis zur großen Buche) wobei jedes Pflanzenmodell zwischen 500 und 130.000 Dreiecke besitzt selbst mit all Deinen aufgezählten Features in einem Call rendern? Wobei dann auch noch die Frage ist, wieso willst Du, verursacht durch nur einen Call der GPU die ganze Cullingarbeit überlassen?

EDIT: Weiterhin besteht dann auch noch die Frage des LOD? Wie soll mit einem Call realisiert werden, dass im Nahbereich die volle Komplexität der Pflanzen angezeigt wird und im Fernbereich z.B. nur noch eine Billboard- oder Point-Approximation?

Gruss, Carsten.

Es gibt ja auch noch den Geometrieprozessor. Was die Details angeht muss man noch warten bis MS die Spec öffentlich macht.

Was das Culling angeht da wird eine D3D10 GPU wesentlich mehr machen als das heute üblich ist. Conditional Rendering wird nämlich endlich unterstützt.

Coda
2005-10-22, 14:37:36
Und überhaupt. Der Draw-Call Overhead wird mit D3D 10 eh auf OpenGL-Niveau geschrumpft.

Asmodeus
2005-10-22, 14:39:39
Es gibt ja auch noch den Geometrieprozessor. Was die Details angeht muss man noch warten bis MS die Spec öffentlich macht.

Was das Culling angeht da wird eine D3D10 GPU wesentlich mehr machen als das heute üblich ist. Conditional Rendering wird nämlich endlich unterstützt.

Gut, Conditional Rendering wird dann wirklich einiges bringen, aber ich bin halt trotzdem der Meinung, die Anzahl der API-Calls müsste sich durch neue Methoden mindestens auf ein Zehntel reduzieren lassen, damit die Sache sich wirklich lohnt. Momentan ist es bei oben angesprochenem Szenario so, dass ich im schlimmsten Fall beim Zeichnen von gerade mal etwa 2,5 Mill. Vertices nur etwa 3 FPS habe, wo ich an anderer Stelle auch 20 Mill. Vertices mit 3 FPS rendern kann, wenn die Anzahl der API-Calls dort viel geringer ist.

Gruss, Carsten.

Asmodeus
2005-10-22, 14:40:32
Und überhaupt. Der Draw-Call Overhead wird mit D3D 10 eh auf OpenGL-Niveau geschrumpft.

Ja, und ich bin ja schon auf OpenGL-Niveau.

Gruss, Carsten.

Coda
2005-10-22, 15:44:18
Und da bist du Drawcall-limitiert? WTF?

marco42
2005-10-22, 16:39:22
Und da bist du Drawcall-limitiert? WTF?

kommt das nicht auf den treiber an? soweit ich weiss liegt das problem darin, dass bei D3D bei jedem draw call ein kernel call(was ziemlch teuer ist) erfolgt(wieso haben die es eigentlich so implementiert?). bei OpenGL bleibt es dem treiber ueberlassen die calls zusammenzufassen bis sie einen kernel call durchfuehren. wenn die opengl library (und der kernel) also gut gethreaded sind dann konnen mehrere cpus was bringen.

Asmodeus
2005-10-22, 16:41:40
Und da bist du Drawcall-limitiert? WTF?

Ja, so sieht es leider aus. Ich hab in dem Zusammenhang mal mit einer einfachen, synthetischen Testszene herumexperimentiert.

dargestellte Vertices: Framerate:

3.364.574 10.36 fps

3.595.806 4.10 fps

4.035.662 2.04 fps


Die Screenshots dazu sind hier:

Api Calls 01 (http://www.cgmi.inf.uni-konstanz.de/~colditz/Api-Calls01.jpg)

Api Calls 02 (http://www.cgmi.inf.uni-konstanz.de/~colditz/Api-Calls02.jpg)

Api Calls 03 (http://www.cgmi.inf.uni-konstanz.de/~colditz/Api-Calls03.jpg)

EDIT: Ich habe die ganze Sache natürlich auch mit supereinfachen Fragmentshadern getestet, um da eine Limitierung ausschließen zu können.

Gruss, Carsten.

RLZ
2005-10-22, 17:25:53
Die Anzahl der Batches in den Szenen wäre noch ganz interessant.

Asmodeus
2005-10-22, 17:44:57
Die Anzahl der Batches in den Szenen wäre noch ganz interessant.

Bei der gezeigten Szene sind es im Nahbereich pro Pflanze mehrere hundert Vertices pro Batch. Im mittleren Bereich, wo simple Billboards zum Einsatz kommen sind es dann natürlich leider nur noch 8 Vertices die pro Pflanze in einem Batch zusammenkommen. Damit ist das Verhältnis zwischen Aufwand für den API-Call und übertragener Geometrie natürlich denkbar schlecht. Aber genau darum ging es mir ja, zu zeigen, dass, wenn es auf Grund einer enormen Variabilität keine Möglichkeit gibt Geometrien in großen Batches zusammenzufassen, die Anzahl der notwendigen Api-Calls zum Flaschenhals wird.

Edit: Die Anzahl der Batches beträgt etwa: 10.000 / 50.000 / 120.000 bei den drei gezeigten Bildern.

Gruss, Carsten.

Neomi
2005-10-22, 17:50:47
Die Zahl der manchmal nötigen DrawCalls stört mich ebenfalls sehr. Es gibt da ein paar Dinge, die ich mir durchaus wünsche. Ich spreche dabei nur für Direct3D, in OpenGL habe ich nicht wirklich mehr als Basiswissen.

1. Programmierbare ROPs. Alphablending, Alphatesting, Nebel und noch einige andere Renderstates könnten per ROP-Shader gut zusammengefaßt werden, ähnlich wie ein Pixelshader den Großteil des Texturestage-Setups zusammenfaßt. Mit dem aktuellen Framebufferinhalt als Input gäbe es so viel mehr Möglichkeiten...

2. Eine Art Batchbuffer. Was jetzt ein DrawCall ist, entspricht dann einem Batch im Batchbuffer. Ähnlich der jetzigen Vertexdeclaration müßte man per Batchdeclaration den Inhalt eines Batches festlegen können. Also der zu verwendende Vertexbuffer, Indexbuffer, Startindex, Primitivecount. Dazu noch Vertexshader, Pixelshader und Texturen. Mit den Renderstates wird es schwieriger, aber dafür gibt es dann ja die ROP-Shader. Sachen, die nicht in der Batchdeclaration enthalten sind, werden dann eben vorher gesetzt und gelten für alle Batches eines "MultiBatchCalls". Das wäre ideal für komplexe Objekte, deren Oberfläche aus vielen verschiedenen Materialien besteht. Da pro Batch nur immer die gleichen Werte gesetzt und ein DrawCall angestoßen werden müssen, könnte der MultiBatchCall schon als Fixed Function Variante ausreichen.

3. Ein Objectbuffer ähnlich dem Batchbuffer. Der dazugehörige Objectshader (mehrmals aufgeführt durch einen "MultiObjectCall") müßte alles setzen kann, was ein Batchbuffer setzen kann (als Vorgabewerte für die Dinge, die der MultiBatchCall selbst nicht setzt), dazu mit einem spezifizierten (im ObjectBuffer) oder vorher gesetzten Batchbuffer beliebig einzelne Batches ausführen kann. Natürlich mit voller Flußkontrolle. Der ObjectShader muß natürlich Vertex- und Pixelshaderkonstanten (und Konstanten für die ROP-Shader natürlich auch) setzen können. Damit wäre dann das Rendering vieler Einzelobjekte kein Problem mehr, Geometry Instancing sieht dagegen reichlich blaß aus.

4. Um die Sache noch deutlich flexibler und einfacher zu machen, will ich all das nicht. Ich will nur Shader, die aus Buffern lesen und in Buffer schreiben können und dazu noch fähig sind, andere Shader aufzurufen.

RLZ
2005-10-22, 17:59:38
Die Arbeit zusammenfassbare Daten wirklich in ein Batch zu vereinigen wird dir die API aber nie abholen (ausser du könntest der API eine Szene übergeben und nur die Änderungen jedes mal neu übertragen).
Dir bleibt momentan nichts anderes übrig als es selber zu tun.
Wir haben bei uns extra einen Layer in die Engine eingebaut, der das Batching zur Laufzeit übernimmt.

Asmodeus
2005-10-22, 18:04:43
Die Arbeit zusammenfassbare Daten wirklich in ein Batch zu vereinigen wird dir die API aber nie abholen (ausser du könntest der API eine Szene übergeben und nur die Änderungen jedes mal neu übertragen).
Dir bleibt momentan nichts anderes übrig als es selber zu tun.
Wir haben bei uns extra einen Layer in die Engine eingebaut, der das Batching zur Laufzeit übernimmt.

Auch damit habe ich schon experimentiert. Nur bin ich da zu dem Ergebnis gekommen, dass ab einer gewissen Szenenkomplexität und Szenenvariabilität das Zusammenfassen von kleinen Batches zu einem großen Batch genauso viele Ressourcen zur Laufzeit verschlingt wie das simple Abarbeiten der vielen kleinen Batches.

Gruss, Carsten.

RLZ
2005-10-22, 18:30:02
Auch damit habe ich schon experimentiert. Nur bin ich da zu dem Ergebnis gekommen, dass ab einer gewissen Szenenkomplexität und Szenenvariabilität das Zusammenfassen von kleinen Batches zu einem großen Batch genauso viele Ressourcen zur Laufzeit verschlingt wie das simple Abarbeiten der vielen kleinen Batches.
Deine Szene ist doch zum größten Teil statisch und einzelne Änderungen in einem KD-Tree sind ja nicht so teuer.
Wie genau hast du versucht die Objekte zusammenzufassen?
Das Batchingproblem lässt sich auch wunderbar in Minijobs umwandeln und legt auf Multicoresystemen dann auch einiges zu. :)

Asmodeus
2005-10-22, 18:43:56
Deine Szene ist doch zum größten Teil statisch und einzelne Änderungen in einem KD-Tree sind ja nicht so teuer.
Wie genau hast du versucht die Objekte zusammenzufassen?
Das Batchingproblem lässt sich auch wunderbar in Minijobs umwandeln und legt auf Multicoresystemen dann auch einiges zu. :)

Der Bodenbewuchs ist auf Patches aufgeteilt (1m x 1m Größe). Pro Patch stehen maximal 1024 Einzelpflanzen. Bei sagen wir mal 10 unterschiedlichen Modellen auf einem Patch haben wir bei Gleichverteilung also etwa immer 100 Pflanzen des gleichen Modells, die zusammengefasst werden können. Jede Pflanze besitzt eine andere Transformationsmatrix. Diese verrechne ich mit den Vertices des Pflanzenmodells und speichere sie in einen großen VertexBuffer (würde unter OpenGL Instancing angeboten, wäre das auch nochmal viel einfacher).Wenn dann die Vertices aller 100 Instanzen des Pflanzenmodells im VertexBuffer liegen wird mit einem Call die Sache aufgerufen. Das Hauptproblem dabei ist die Verrechnung der Vertices mit den Transformationsmatrizen, da ich diese Sache ja mit der CPU machen muss, obwohl die GPU dafür wohl viel besser geeignet wäre. Und da wie gesagt ab einer gewissen Komplexität diese Sache nicht schneller ist, als hundert mal das Modell mitsamt seiner Transformationsmatrix aufzurufen, bin ich wieder davon abgekommen.

Gruss, Carsten.

RLZ
2005-10-22, 18:59:40
Falls diese Objekte nicht geskinned sind könntest du die Transformation mit Vertex Constants Instancing auf die GPU schieben.

Demirug
2005-10-22, 19:25:18
Die Zahl der manchmal nötigen DrawCalls stört mich ebenfalls sehr. Es gibt da ein paar Dinge, die ich mir durchaus wünsche. Ich spreche dabei nur für Direct3D, in OpenGL habe ich nicht wirklich mehr als Basiswissen.

1. Programmierbare ROPs. Alphablending, Alphatesting, Nebel und noch einige andere Renderstates könnten per ROP-Shader gut zusammengefaßt werden, ähnlich wie ein Pixelshader den Großteil des Texturestage-Setups zusammenfaßt. Mit dem aktuellen Framebufferinhalt als Input gäbe es so viel mehr Möglichkeiten...

2. Eine Art Batchbuffer. Was jetzt ein DrawCall ist, entspricht dann einem Batch im Batchbuffer. Ähnlich der jetzigen Vertexdeclaration müßte man per Batchdeclaration den Inhalt eines Batches festlegen können. Also der zu verwendende Vertexbuffer, Indexbuffer, Startindex, Primitivecount. Dazu noch Vertexshader, Pixelshader und Texturen. Mit den Renderstates wird es schwieriger, aber dafür gibt es dann ja die ROP-Shader. Sachen, die nicht in der Batchdeclaration enthalten sind, werden dann eben vorher gesetzt und gelten für alle Batches eines "MultiBatchCalls". Das wäre ideal für komplexe Objekte, deren Oberfläche aus vielen verschiedenen Materialien besteht. Da pro Batch nur immer die gleichen Werte gesetzt und ein DrawCall angestoßen werden müssen, könnte der MultiBatchCall schon als Fixed Function Variante ausreichen.

3. Ein Objectbuffer ähnlich dem Batchbuffer. Der dazugehörige Objectshader (mehrmals aufgeführt durch einen "MultiObjectCall") müßte alles setzen kann, was ein Batchbuffer setzen kann (als Vorgabewerte für die Dinge, die der MultiBatchCall selbst nicht setzt), dazu mit einem spezifizierten (im ObjectBuffer) oder vorher gesetzten Batchbuffer beliebig einzelne Batches ausführen kann. Natürlich mit voller Flußkontrolle. Der ObjectShader muß natürlich Vertex- und Pixelshaderkonstanten (und Konstanten für die ROP-Shader natürlich auch) setzen können. Damit wäre dann das Rendering vieler Einzelobjekte kein Problem mehr, Geometry Instancing sieht dagegen reichlich blaß aus.

:D Genau nach einem solchen Model ist das Interface des 3D Renderes für die Engine an der ich arbeite aufgebaut. Die Teile haben allerdings andere Namen.

Bezüglich des ersten Punktes. Hast du dir schon mal die Stateblocks angeschaut?

Neomi
2005-10-22, 19:59:49
:D Genau nach einem solchen Model ist das Interface des 3D Renderes für die Engine an der ich arbeite aufgebaut. Die Teile haben allerdings andere Namen.

Dann kann das Modell ja gar nicht so verkehrt sein. :D
Ich freue mich jedenfalls schon auf den Tag, ab dem dieses Modell dank nahezu freier Programmierbarkeit auf der GPU läuft.

Bezüglich des ersten Punktes. Hast du dir schon mal die Stateblocks angeschaut?

Die Zusammenfassung war eher ein sekundärer Effekt. Hauptsächlich geht es mir bei den ROP-Shadern um Effekte wie z.B. Farbverschiebung, die man auf den existierenden Framebufferinhalt anwenden kann, ohne den Umweg über eine Textur gehen zu müssen. Dann wäre zwar nur der Zugriff auf den jeweils zu überschreibenden (Sub-)Pixel möglich, aber für manche Effekte reicht das ja.

Stateblocks kenne ich, habe ich aber bisher nicht wirklich eingesetzt (leider zu wenig Zeit für große Experimente). Das, was sie laut Doku alles capturen, ist mir doch ein wenig viel. Die Trennung in Pixel- und Vertexstates ist schon sehr grob. Es sind viel zu viele Kombinationen, die ich so brauche, um für jede einen einzelnen Stateblock abzulegen. Klein können die auch nicht gerade sein, wenn sämtliche Konstanten mit eingeschlossen werden, von denen ich einige dann eh pro Objekt wieder mit neuen Werten überschreiben muß. Bei den Texturen sieht es ähnlich aus, die muß ich auch manuell neu setzen.

Was sind denn deine Erfahrungswerte für Stateblöcke? Ab wievielen zu setzenden States lohnen sie sich? Was kostet es extra, wenn nicht benötigte States und Konstanten dadurch gesetzt werden? Wie viel Speicher braucht ein normaler Block (einmal Vertex-, einmal Pixelstates)? Kennst du Stolpersteine, auf die man dabei achten sollte?

Demirug
2005-10-22, 20:22:58
Dann kann das Modell ja gar nicht so verkehrt sein. :D
Ich freue mich jedenfalls schon auf den Tag, ab dem dieses Modell dank nahezu freier Programmierbarkeit auf der GPU läuft.

Komplett wird es wohl nie laufen. Mir ging es dabei im wesentlichen nur darum API Unterschiede zu verdecken und gleichzeitig API spezifische Optimierungen nutzen zu können. Habe mir allerdings auch ein paar Stolperfallen eingebaut weil das Teil manchmal zu viel automatisch macht.

Die Zusammenfassung war eher ein sekundärer Effekt. Hauptsächlich geht es mir bei den ROP-Shadern um Effekte wie z.B. Farbverschiebung, die man auf den existierenden Framebufferinhalt anwenden kann, ohne den Umweg über eine Textur gehen zu müssen. Dann wäre zwar nur der Zugriff auf den jeweils zu überschreibenden (Sub-)Pixel möglich, aber für manche Effekte reicht das ja.

Stateblocks kenne ich, habe ich aber bisher nicht wirklich eingesetzt (leider zu wenig Zeit für große Experimente). Das, was sie laut Doku alles capturen, ist mir doch ein wenig viel. Die Trennung in Pixel- und Vertexstates ist schon sehr grob. Es sind viel zu viele Kombinationen, die ich so brauche, um für jede einen einzelnen Stateblock abzulegen. Klein können die auch nicht gerade sein, wenn sämtliche Konstanten mit eingeschlossen werden, von denen ich einige dann eh pro Objekt wieder mit neuen Werten überschreiben muß. Bei den Texturen sieht es ähnlich aus, die muß ich auch manuell neu setzen.

Was sind denn deine Erfahrungswerte für Stateblöcke? Ab wievielen zu setzenden States lohnen sie sich? Was kostet es extra, wenn nicht benötigte States und Konstanten dadurch gesetzt werden? Wie viel Speicher braucht ein normaler Block (einmal Vertex-, einmal Pixelstates)? Kennst du Stolpersteine, auf die man dabei achten sollte?

Ich glaube du hast dir nur "CreateStateBlock" angeschaut. Mit BeginStateBlock und EndStateBlock kann man Stateblocks bauen die nur genau die States enthalten die man braucht.

Benutzt habe ich sie bisher nur für den Tweaker (für die Engine ist das noch eine Optimierung). Da brauche ich sie vorallem um den aktuellen Inhalt von States zu sichern und wieder zurück zu setzten. Bei einem Pure Device geht das nämlich nicht anders.

Neomi
2005-10-22, 21:20:54
Komplett wird es wohl nie laufen. Mir ging es dabei im wesentlichen nur darum API Unterschiede zu verdecken und gleichzeitig API spezifische Optimierungen nutzen zu können. Habe mir allerdings auch ein paar Stolperfallen eingebaut weil das Teil manchmal zu viel automatisch macht.

Komplett ist wohl wirklich zu optimistisch, aber die Sache mit dem Batchbuffer sollte schon drin sein. Nach deinem Hinweis mit den Stateblöcken würde es da vollkommen reichen, Wenn pro Batch ein Stateblock und die Parameter eines DrawCalls angegeben werden. Das wäre sogar schon per Software locker machbar, die Batches könnte der Treiber ohne ständige Kontextwechsel nacheinander abarbeiten. Fehlt bloß noch die passende API-Funktion.

Ich glaube du hast dir nur "CreateStateBlock" angeschaut. Mit BeginStateBlock und EndStateBlock kann man Stateblocks bauen die nur genau die States enthalten die man braucht.

:) Danke!!! :)

Genau so war es. Wieso ich die bisher übersehen habe, weiß ich nicht, ich suche noch nach einer guten Ausrede. Dich kann man glatt in Gold aufwiegen (sofern du nicht übergewichtig bist :D). Nein, Gold ist noch zu billig. Dich kann man glatt in Druckertinte aufwiegen. ;)

Demirug
2005-10-23, 19:12:00
Komplett ist wohl wirklich zu optimistisch, aber die Sache mit dem Batchbuffer sollte schon drin sein. Nach deinem Hinweis mit den Stateblöcken würde es da vollkommen reichen, Wenn pro Batch ein Stateblock und die Parameter eines DrawCalls angegeben werden. Das wäre sogar schon per Software locker machbar, die Batches könnte der Treiber ohne ständige Kontextwechsel nacheinander abarbeiten. Fehlt bloß noch die passende API-Funktion.

Das Problem ist ja auch das sich gerade bei den Shaderkonstanten auch schon mal was von Frame zu Frame ändert. Dafür bräuchte man dann einen Puffer welcher im Hauptspeicher liegt und direkt von der GPU ausgelsen und interpretiert werden kann. Also so wie die dynamischen Vertexbuffer fürs Instancing. Es könnte allerdings sein das wir das bei D3D10 zu sehen bekommen.

Ich hätte allerdings noch gerne einen Programmierbaren AA-Sample Shader.

:) Danke!!! :)

Genau so war es. Wieso ich die bisher übersehen habe, weiß ich nicht, ich suche noch nach einer guten Ausrede. Dich kann man glatt in Gold aufwiegen (sofern du nicht übergewichtig bist :D). Nein, Gold ist noch zu billig. Dich kann man glatt in Druckertinte aufwiegen. ;)

Was soll ich mit Druckertinte ich habe nicht mal einen Drucker?

Sieh es als Werbegeschenk an.

Asmodeus
2005-10-24, 08:03:16
Falls diese Objekte nicht geskinned sind könntest du die Transformation mit Vertex Constants Instancing auf die GPU schieben.

Ja, es gab da ja auch mal von Nvidia dieses GLSL-pseudo-Instancing Demo, wo mit Hilfe von glMultiTexCoord...( ) anstatt mit glUniform...( ) Parameter an den VertexShader übergeben werden. Habe ich auch schon mal ansatzweise getestet, leider habe ich zu viele Parameter, die ich übergeben muss, somit reicht mir glMultiTexCoord...( ) nicht aus.

Das Hauptproblem ist einfach, dass ich die feine Granularität des Aufrufs pro Einzelpflanze benötige um nicht vertex-limitiert zu sein. Pro Einzelpflanze wird in Abhängigkeit von der Entfernung zum Betrachter und der Größe der Pflanze im Bildraum entschieden ob sie komplett als Geometrie, teilweise als Geometrie und teilweise als Billboard, oder nur noch als Billboard gezeichnet wird. Und diese Entscheidung muss vor dem Zeichnen jeder einzelnen Pflanze getroffen werden. Somit ist ein Zusammenfassen mehrerer Pflanzen sehr schwierig, da selbst bei dem gleichen Modell je nach Entfernung und Größe im Bildraum unterschiedliche viele Vertices von diesem Modell gezeichnet werden müssen.

Gruss, Carsten.

Demirug
2005-10-24, 09:50:54
Zumindestens die Billboards sollte sich aber schon mal zusammenfassen lassen.

Haben den mehrer Pflanze bis auf die Geometrie identische Renderstates? Oder anders gefragt was ändert sich wie häufig?

Asmodeus
2005-10-24, 10:10:50
Zumindestens die Billboards sollte sich aber schon mal zusammenfassen lassen.

Haben den mehrer Pflanze bis auf die Geometrie identische Renderstates? Oder anders gefragt was ändert sich wie häufig?

Wie schon gesagt, im idealen Fall weiß ich: jetzt kommen von einem Pflanzenmodell 100 Instanzen, wobei alle als Billboards gerendert werden. Der Unterschied zwischen allen ist dann die jeweils unterschiedliche Transformationsmatrix. Zusammenfassen würde also dann bedeuten, wie schon erklärt, die Vertices mit der jeweiligen Matrix verrechnen und dann alles in einem großen VertexBuffer speichern, um die Sache dann über einen Aufruf zu realisieren. Aber wie gesagt, da bei diesem Weg die CPU die ganzen Matrixoperationen ausführen muss, ist die Sache ab einer gewissen Komplexität alles andere als performant. Oder meinst Du mit Billboards zusammenfassen, sie schon vorher zusammengefasst im Speicher abzulegen?

Gruss, Carsten.

Demirug
2005-10-24, 10:24:58
Ich meinte mit Zusammenfassen alle Billboards in einen großen dynamischen Vertexspeicher zu legen und dann mit einem Drawcall zu rendern. Mit Texturatlasen kann man dabei sogar noch die Billboards von unterschiedlichen Pflanzen zusammen fassen.

Ich nehme mal an deine Billboards sind die üblichen 4 Eckpunkte Billboards. Wenn du nur die Eckpunkte und Texturekoordinaten hast kannst du die Transformationsmatrix doch leicht via pseudo-Instancing oder einfaches Mehrfach kopieren der Matrix in den Vertexbuffer übergeben.

Das du hoffnungsloss Drawlimitiert bist wenn du jedes Billboard einzeln renderst ist nun wirklich kein Wunder.

Asmodeus
2005-10-24, 10:28:21
Ich meinte mit Zusammenfassen alle Billboards in einen großen dynamischen Vertexspeicher zu legen und dann mit einem Drawcall zu rendern. ...

Und genau darauf zielte meine Frage doch ab, meinst Du damit, die Billboards zur Laufzeit in einem großen dynamischen Vertexspeicher zusammenzufassen. Oder sie schon vorher zusammengefasst abzuspeichern?

Gruss, Carsten.

Demirug
2005-10-24, 10:36:20
Und genau darauf zielte meine Frage doch ab, meinst Du damit, die Billboards zur Laufzeit in einem großen dynamischen Vertexspeicher zusammenzufassen. Oder sie schon vorher zusammengefasst abzuspeichern?

Gruss, Carsten.

Da du die Billboards die zusammen gehören ja wohl erst zur Laufzeit kennst musst sie auch dynamisch in den Buffer kopieren. Ist das gleiche Prinzip wie man es auch in einer Partikelengine nutzt.

Asmodeus
2005-10-24, 10:43:58
Da du die Billboards die zusammen gehören ja wohl erst zur Laufzeit kennst musst sie auch dynamisch in den Buffer kopieren. Ist das gleiche Prinzip wie man es auch in einer Partikelengine nutzt.

Gut, aber ich habe ja schon geschrieben, dass dabei dann pseudo-Instancing (in der Form wie sie NV in der Demo umgesetzt hat) bei mir nicht funktioniert. Und was Du mit "oder einfaches Mehrfach kopieren der Matrix in den Vertexbuffer übergeben" meinst ist mir noch nicht so ganz klar.

Gruss, Carsten.

Demirug
2005-10-24, 10:46:36
Gut, aber ich habe ja schon geschrieben, dass dabei dann pseudo-Instancing (in der Form wie sie NV in der Demo umgesetzt hat) bei mir nicht funktioniert. Und was Du mit "oder einfaches Mehrfach kopieren der Matrix in den Vertexbuffer übergeben" meinst ist mir noch nicht so ganz klar.

Gruss, Carsten.

OK anders herum. Welche Daten brauchst du derzeit in deinen Verticen für die Billboards? Eine Position und eine Texturekoordinate, oder noch mehr?

Asmodeus
2005-10-24, 10:47:53
OK anders herum. Welche Daten brauchst du derzeit in deinen Verticen für die Billboards? Eine Position und eine Texturekoordinate, oder noch mehr?

Ja, wenn es sein muss kann ich es auf diese beiden Sachen reduzieren.

Gruss, Carsten.

Demirug
2005-10-24, 10:55:43
Ja, wenn es sein muss kann ich es auf diese beiden Sachen reduzieren.

Gruss, Carsten.

Das hört sich jetzt aber so an als würdest du das nicht gerne machen. Also was bräuchtest du optional noch?

Ich denke jetzt aber mal das du dann auch noch 4 Inputs für die Matrix frei hast, oder?

Ich gehe jetzt davon aus das du die Matrix auf der CPU berechnest. Für den Fall das du das nicht tuts müsste wir die Berechnung auch noch in den VertexShader legen. Dafür wäre es dann wichtig welche Parameter du für die Berechnung der Matrix verwendets.

Asmodeus
2005-10-24, 11:01:11
Das hört sich jetzt aber so an als würdest du das nicht gerne machen. Also was bräuchtest du optional noch?

Ich denke jetzt aber mal das du dann auch noch 4 Inputs für die Matrix frei hast, oder?

Ich gehe jetzt davon aus das du die Matrix auf der CPU berechnest. Für den Fall das du das nicht tuts müsste wir die Berechnung auch noch in den VertexShader legen. Dafür wäre es dann wichtig welche Parameter du für die Berechnung der Matrix verwendets.

Ich hatte bisher noch von der Möglichkeit gebrauch gemacht, in den Normalenkoordinaten pro Vertex noch einige andere Werte zu "verstecken."
Aber egal, wie gesagt, dass kann ich auch anders lösen, ist auch nicht das Problem. Und ja, die Werte der Matrix werden durch die CPU berechnet (ist bei mir schneller, als wenn ich die Ausgangswerte an einen Shader übergebe und die Matrix dort berechne).

EDIT: Ja, somit wären dann noch 4 Inputs frei. Ich habe aber 3 Werte für die Translation, einen Wert für die Skalierung und einen Wert für die Rotation.

EDIT2: Und meine Matrix ist wie folgt belegt:

xx0x
xx0x
00xx
0001

Gruss, Carsten.

Demirug
2005-10-24, 11:15:19
Ich hatte bisher noch von der Möglichkeit gebrauch gemacht, in den Normalenkoordinaten pro Vertex noch einige andere Werte zu "verstecken."
Aber egal, wie gesagt, dass kann ich auch anders lösen, ist auch nicht das Problem. Und ja, die Werte der Matrix werden durch die CPU berechnet (ist bei mir schneller, als wenn ich die Ausgangswerte an einen Shader übergebe und die Matrix dort berechne).

EDIT: Ja, somit wären dann noch 4 Inputs frei. Ich habe aber 3 Werte für die Translation, einen Wert für die Skalierung und einen Wert für die Rotation.

Gruss, Carsten.

Das verstehe ich jetzt nicht ganz.

Wenn du die Matrix auf der CPU berechnest solltest du doch 4*4 Fliesskomma werte haben. Das passt in 4 Inputs rein.

Wenn du das dann über einen dynamischen Vertexbuffer realisierst kopierst du diese Matrix einfach zu jedem Eckpunkt des Billboards dazu. Bei 4 Eckpunkten pro Billboard sollte das auf jeden Fall noch schneller sein als jeweils einen Drawcall pro Billboard zu verwenden.

EDIT: Wenn du nur 8 dynamische Werte hast kannst du das auch in 2 Inputs pressen und dann im Vertexshader "entpacken".

Asmodeus
2005-10-24, 12:02:35
Das verstehe ich jetzt nicht ganz.

Wenn du die Matrix auf der CPU berechnest solltest du doch 4*4 Fliesskomma werte haben. Das passt in 4 Inputs rein.

Wenn du das dann über einen dynamischen Vertexbuffer realisierst kopierst du diese Matrix einfach zu jedem Eckpunkt des Billboards dazu. Bei 4 Eckpunkten pro Billboard sollte das auf jeden Fall noch schneller sein als jeweils einen Drawcall pro Billboard zu verwenden.

EDIT: Wenn du nur 8 dynamische Werte hast kannst du das auch in 2 Inputs pressen und dann im Vertexshader "entpacken".

Stimmt, pro Input kann ich ja bis zu vier Komponenten belegen. Ich werd es also mal mit 2 Inputs versuchen.

Gruss, Carsten.

Asmodeus
2005-10-24, 15:10:35
Ok, die Sache ist jetzt genauso schnell/langsam wie vorher. Ich habe etwas herumexperimentiert:


Ich habe genau genommen zwei 4x4 Matrizen die ich pro Billboard übertragen muss. Von der einen benötige ich nur die ersten 3 Zeilen, von der zweiten alle 4 Zeilen. Insgesamt habe ich also 7 x 4 Float-Werte. Nun habe ich zuerst versucht diese 28 Werte einfach als 7 Attribute mit je 4 Werten zu übertragen (an jetzt nur noch einen großen VertexBuffer). Der Datenoverhead ist da natürlich schon ziemlich groß (pro Vertex 5 Ausgangswerte und zusätzlich jetzt 28 Attributewerte). Und somit gab es keinen Geschwindigkeitszuwachs.

Also habe ich versucht, die Anzahl der Attributewerte auf ein Minimum zu verringern und die Matrizen im Shader aus diesen Werten auszurechnen. Bei den Daten der Transformationsmatrix geht das noch, bei den Daten der Shadowmatrix ist das schon schwieriger. Aber durch den dann zusätzlichen Aufwand im Vertex-Shader steigt die Gesamtperformance aber auch nicht an.

EDIT: Die maximale Steigerung der Performance liegt etwa zwischen 5 und 7 Prozent.

Gruss, Carsten.