PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Early Object Culling


Demirug
2003-03-21, 18:34:14
Early Object Culling

Early Object Culling ist ein derzeit noch theoretisches Verfahren an dem ich schon länger arbeite und hiermit zur Diskussin stellen möchte. Es handelt sich dabei um eine Weiterentwicklung des Early-Z Verfahrens welches ja bei moderen Grafikchips inzwischen weit verbreitet ist.

Das Early-Z Verfahren ist nur in der Lage die Pixelpipelines zu entlasten. Das Trisetup und sowie die Vertexshader und eine eventuel vorhandenen HOS-Einheit (z.b. Truform) müssen denoch die gesamte Arbeit auch für verdeckte Objekte durchführen. Dabei wird Rechenleistung und Bandbreite verbraucht. Ein TBDR (z.B. Kyro) kann dieses Problem leider auch nicht lösen da die die Verfahren ja erst greifen können wenn die Gemetrie vollständig vorliegt.

Nun aber zu dem Verfahren

Das Early Object Culling Verfahren benutzt zwei zusätzliche Buffer in der Grafikkarte.

1. Object-ID Buffer: Für jedes AA-Sample wird zusätzlich Speicher zum ablegen einer Object ID angelegt. Die grösse einer Zelle und damit des gesamten Buffers hängt davon ab wie der Programmier den Buffer anlegt (s. unten)

2. Object Sample Count Buffer: Für jede verfügbare Object ID wird ein 32 Bit wert gespeichert der die Anzahl der AA-Samples welches das

Objekt mit dieser ID bedeckt speichert.

Bevor mit dem Rendern begonnen wird muss ein Object Buffer erzeugt werden. Dieses sollte nur einmal direkt nach dem erzeugen des Renderkontext durchgeführt werden. Dabei wird die grösste ObjecktID die man benötigt angegeben. Mit dieser Angabe läst sich dann auch die grösse der Buffer berechnen.

Max Object ID <= 255:
Object-ID Buffer = X*Y*AA-Samples Byte
Object Sample Count Buffer = Max Object ID * 4 Byte

Max Object ID <= 65535:
Object-ID Buffer X*Y*AA-Samples*2 Byte
Object Sample Count Buffer = Max Object ID * 4 Byte

Max Object ID > 65535:
Object-ID Buffer X*Y*AA-Samples*4 Byte
Object Sample Count Buffer = Max Object ID * 4 Byte

Herstellerabhängig sind aber auch andere grössen möglich es handelt sich also nur um Richtzahlen.

Damit das verfahren optimal funktioniert ist ein First Z-Only Pass von Vorteil. Bei diesem Pass wird neben dem Z-Buffer auch die beiden Object Buffer gefüllt. Dazu wird vor dem Draw-call eine Object-ID Write aktiviert.

Bei aktiviertem Object-ID Write muss der Chip folgeden Code in der Hardware implementieren.


if (zpass (x,y,aa))
{
current_object_id = Get_Object_ID (x,y,aa);

objectidcount[current_object_id]--;
objectidcount[active_object_id]++;

Set_object_ID (x,y,aa, active_object_id);
}


Hat man nun alle objekte einmal gerendert befindet sich im Object Sample Count Buffer für jede Objekt ID die Anzahl der Sampels die von diesem Objekt bededeckt werden.

Diese Information kann nun bei folgenden Renderpasses dahin gehend genutzt werden das man vor jedem Draw-Call ein Object ID Test Call einfügt. Schlägt dieser Test fehl wird der folgende DrawCall von der Grafikkarte nicht aus geführt. Bei diesem Test wird angegben welche ID gebrüpt werden soll und wie viele Samples (bzw Pixel) bedeckt sein müssen damit der Draw auch ausgeführt wird. In der Karte müsste der Kommando stream also wie folgt verarbeitet werden.


while (commandos in stream)
{
if (Object test active)
{
if (objectidcount[object_id] < min_sample_count)
continue
}

render next primitive
}


Bei Geometrie welche mit einfachen Vertexshadern/Pixelshadern arbeitet lohnt sich das Verfahren natürlich nur wenn man aus Technischen gründen (Schatten ala DOOM III) sowieso einen First Z-Only Pass braucht. Bei komplexen Shadern kann man aber IMO einiges Sparen. Zudem gibt es noch die Möglichkeit den ObjectID Buffer mit vereinfachter Gemetrie (Umgebungswürfel) zu füllen.

Ich bitte um Fragen, Anregungen und Kommentare

Kant
2003-03-22, 20:15:35
Im Prinzip wäre das eine feine Sache. Hatte mir mal nen 3dmap precompiler gebaut, der objecte mit verschiedenen Farben in eine Texture renderte. Dann einige hundert Durchläufe mit leicht versetzter Kamera, und dann auf der CPU testen, weclhe Objecte von diesem "Sektor" aus zu sehen sind. Bin damit um ne Menge fiese Mathe rumgekommen ;)

Optimal wäre natürlich den "Object Sample Count Puffer" direkt in interne Chip-Register zu mappen. Damit würde man 2xSample Count read/write im Memory umgehen. Ist aber aufrgrund der limitierten Anzahl der Register wohl nur begrenzt möglich.

Allerdings wünsche ich mir schon seit ewigen Zeiten zusätzliche Render-Puffer. Aber da sind die HW-Hersteller konservativ. Noch nicht mal der Accumulation-Puffer aus OGL (1.1?) wird mit derzeitiger HW unterstützt. Die Ausnahme ist der F-Puffer der neuen Radeons, aber wenn ich das richtig verstehe arbeitet der nur auf vertex-ebene.

Ein weiteres "Problem" ist, das diese Funktion schlechten Code "bevorzugt". Also, den größten Vorteil würde eine schlecht gecullte/visibility getestete Szene ziehen. Hingegen würde eine Szene, die schon fast optimal ist, vermutlich keinen Gewinn erzielen.

Finde die Idee aber trotzdem gut, und würde mich freuen, wenn sowas umgesetzt würde.

zeckensack
2003-03-22, 20:56:52
Demirug, habe ich das richtig verstanden:
der Gewinn entstünde allein durch eingesparte Vertex-Leistung???

Kant
2003-03-22, 21:15:55
Der Gewinn entsteht dadurch, das in den Folge-Passes "irrelevante" Objecte gar nicht mehr zur GraKa übertragen/gerendert werden. Würde also auch CPU-Leistung sparen.

Demirug
2003-03-22, 21:41:39
Originally posted by zeckensack
Demirug, habe ich das richtig verstanden:
der Gewinn entstünde allein durch eingesparte Vertex-Leistung???

Nicht nur die Vertex-Leistung wird gespart sonder alles was danach noch kommt.

Stell dir ganze wie folgt vor.

1. Pass für alle Objekte:
- Vertexshader: nur die Position berechnen (keine Texturkoordinaten, Normalen, Farben, ...)
- Pixelshader: keine arbeit
- AA-Sampler: Z und Object ID Buffer updaten

2. Pass wieder für alle Objekte
- Vertexshader vollständig
- Pixelshader vollständig
- AA-Sampler vollständig

Der Trick ist jetzt aber das bevor der Grafikchip anfängt auch nur eine Vertice aus dem zweiten Pass überhaupt zu laden vorher schnell gebrüpft wird ob dieses Objekt überhaupt sichtbar ist. Das ist trivial mit nur einem einzige Zahlenvergleich möglich. Aus diese Weise werden dann viele Verticens und noch mehr Pixel auf einen Schlag gecullt.

@Kant: CPU Leistung kann man damit leider direkt nicht sparen den die ganzen Calls müssen ja wieterhin auf Verdacht ausgeführt werden. Der Vorteil liegt also nur auf der GPU Seite die entscheiden kann ob sie einen Drawcall überhaupt ausführt.

Bezahlen muss man das ganze mit zusatzlichen Bedarf an Bandbreite für das verwalten der ObjectID Buffer. Der ObjectID Buffer sollte sich aber in der Regel sehr gut komprimieren lassen udn in Verbidnung mit einem komprimierten Z-Buffer dürfte der zusätzliche Bedarf während des Z-Passes noch zur verfügung stehen. Später wird ja nur noch selten der Count Buffer benötigt was nicht ins gewicht fällt.

zeckensack
2003-03-22, 21:48:31
Aber du verbrauchst für den ersten Pass Füllrate - im Fall von 'convex hulls' sogar mehr als für die umschlossenen Objekte. Zumindest Z-Interpolator/Z-Test/Z-Write muß laufen, inwieweit die Performance dieses Teils mit der Füllrate zusammenhängen muß weiß ich nicht - bei 'klassischen' Chips ist das Verhältnis jedoch exakt 1:1 :)

Ich sehe da bisher keine offensichtliche Überlegenheit dieses Verfahrens. Educate me :)

Kant
2003-03-22, 21:53:34
Originally posted by Demirug
CPU Leistung kann man damit leider direkt nicht sparen den die ganzen Calls müssen ja wieterhin auf Verdacht ausgeführt werden. Der Vorteil liegt also nur auf der GPU Seite die entscheiden kann ob sie einen Drawcall überhaupt ausführt.


Wäre es nicht besser, die Abfrage ob ein Object in Pass1 sichtbar war, als eigenen Call zu interpretieren. Die Abfrage
"if (objectidcount[object_id] < min_sample_count)"
also praktisch auf CPU-Seite durchführen, mit objectidcount als neuen API-Call. Dadurch entfällt dann wirklich der komplette Transfer CPU=>GPU für "irrelavante" Objekte. Und das ohne das Mehraufwand anfällt.

Demirug
2003-03-22, 21:59:13
Originally posted by zeckensack
Aber du verbrauchst für den ersten Pass Füllrate - im Fall von 'convex hulls' sogar mehr als für die umschlossenen Objekte. Zumindest Z-Interpolator/Z-Test/Z-Write muß laufen, inwieweit die Performance dieses Teils mit der Füllrate zusammenhängen muß weiß ich nicht - bei 'klassischen' Chips ist das Verhältnis jedoch exakt 1:1 :)

Ich sehe da bisher keine offensichtliche Überlegenheit dieses Verfahrens. Educate me :)

Klar verbraucht es füllrate. Deswegen habe ich ja auch extra geschrieben das dieses Verfahren besonders interesant ist wenn man auch technischen Gründen (Stencil Schatten ala DOOM III) sowieso einen Z-Pass braucht. Zudem wird dieser Z-Pass auch in fällen verstärkt kommen in denen er technisch nicht unbedingt notwendig ist denn je komplexer und länger die Shader werden desto grösser ist der Gewinn durch den Z-Pass.

Demirug
2003-03-22, 22:05:28
Originally posted by Kant


Wäre es nicht besser, die Abfrage ob ein Object in Pass1 sichtbar war, als eigenen Call zu interpretieren. Die Abfrage
"if (objectidcount[object_id] < min_sample_count)"
also praktisch auf CPU-Seite durchführen, mit objectidcount als neuen API-Call. Dadurch entfällt dann wirklich der komplette Transfer CPU=>GPU für "irrelavante" Objekte. Und das ohne das Mehraufwand anfällt.

Kant, du vergiesst etwas. CPU und GPU arbeiten zwar parralel aber zeirversetzt. Wenn man also den Z-Pass komplett übertragen hat und nun den Wert für die Abfrage bräuchte kann es durchaus sein das der Chip mit dem Frame noch nicht mal angefangen hat sondern noch an dem den vorherigen arbeitet um nun den Wert zu bekommen müsste man warten bis die GPU auch so weit ist. Aus diesem Grund sollte alle Kommunikation mit einer Grafikkarte immer nur einseitig sein.

PS: In DX9 (bei OpenGL Herstellerabhängig schon länger) gibt es eine entsprechende Funktion die zählen kann wie viele Pixel sich verändert haben. Aber aus obengenannten Gründen ist sie nicht unbedingt immer praktikabel.

micki
2003-03-24, 12:27:30
ati und nvidia sagen, dass man beim rendern ein delay von 2-3 frames durchaus als normal gesehen werden kann.

das bedeutet doch, dass erst nach 3 frames die informationen da sind, ob man objekte weglassen kann, aber falls sich irgendwas geändert hat, müßte man da wieder 3 frames warten bis man etwas weglassen kann...

klar man kann immer schätzungen machen
aber genau dafür nutzt doom3 doch portale, was hinter einer wand ist, das wird sowieso nicht gerendert, denn es gibt kein portal durch das man das sehen würde...

wobei occlusion culling schon lang existent ist und in software auch durchaus performance bringen kann, weil vereinfachte buffer (nur 128*128 mit 8bit) schon enorme performance bringen können, dazu sparrt man das hochladen von geometrie, denn ein paar boxen zu testen ob sie von einer wand verdeckt werden ist beim occlusion culling von cpu durchaus schnell genug um vorteile gegenüber bufferlocks und hochladen von ein paar (hundert)tausend polys zu bringen


*in eile*
MfG
micki

Demirug
2003-03-24, 12:51:24
Originally posted by micki
ati und nvidia sagen, dass man beim rendern ein delay von 2-3 frames durchaus als normal gesehen werden kann.

das bedeutet doch, dass erst nach 3 frames die informationen da sind, ob man objekte weglassen kann, aber falls sich irgendwas geändert hat, müßte man da wieder 3 frames warten bis man etwas weglassen kann...

Ja genau das ist das Problem wenn man auf Rückantworten von der GPU warten muss.

klar man kann immer schätzungen machen
aber genau dafür nutzt doom3 doch portale, was hinter einer wand ist, das wird sowieso nicht gerendert, denn es gibt kein portal durch das man das sehen würde...

Ja im Indoor Bereich sind Portale ganz brauchbar. Abgesehen davon das sie immer noch von Hand gesetzt werden müssen weil die automatischen Verfahren noch nicht so gut sind. Sobald man aber in den Outdoor bereich geht sind Portale absolute Unbrauchbar und Anti-Portale stellen eine vergleichsweise schlechte Lösung dar.

wobei occlusion culling schon lang existent ist und in software auch durchaus performance bringen kann, weil vereinfachte buffer (nur 128*128 mit 8bit) schon enorme performance bringen können, dazu sparrt man das hochladen von geometrie, denn ein paar boxen zu testen ob sie von einer wand verdeckt werden ist beim occlusion culling von cpu durchaus schnell genug um vorteile gegenüber bufferlocks und hochladen von ein paar (hundert)tausend polys zu bringen

Natürlich gibt es occlusion culling schon ewig den ohne ein solches könnte man ja gar keine 3d Bilder rendern. Es gibt aber dafür sehr viele Verfahren. Ob bei aktuellen CPU/GPU Kombinationen das verwalten eines vereinfachten Z-Buffers wirklich noch etwas bringt bezweifle ich jetzt aber mal. Eine CPU hat einfach zuwenig "Fillrate" und Bandbreite für solche Dinge.

Bei statischer Geometrie wird ja nichts mehr hochgeladen. Die liegt entweder schon in der Grafikkarte oder im AGP Bereich. Der Draw-Befehl braucht nur ein paar Bytes.

Es geht mir ja auch nicht darum die Verfahren (z.b Portale) die sich einfach und schnell (Performance) auf der CPU verwirklichen lassen zu ersetzen. Ein Drawcall der nicht gemacht wird ist immer noch besser als ein Drawcall der dann von GPU nicht ausgeführt wird. Aber es gibt Fälle die sich auf einer CPU nicht mit vernünpftigem Aufwand prüfen lassen. So ist zum Beispiel ein gegenseitiges Verdecken von mehrern Dynamischen Objekten nicht ganz trivial festzustellen. Oder auch bei statischen Objekten im Outdoor bereich gibt es solche Fälle. Wenn zum Beispiel ein Object von 2 anderen jeweils nur teilweise verdeckt aber in Summe kommplett verdeckt wird bedarf es einiges an Rechenaufwand um so etwas zu erkennen. Ein Object Culling mit einem Object ID Buffer könnte solche Dinge leicht feststellen und damit Vertex und Pixel shader leistung einsparen.

micki
2003-03-24, 15:26:18
also mein occlusion culler (amd1700+ mit gf4ti) bringt ziemlich viel performance. es ist echt nicht das große problem in einem buffer zu pinseln der klein ist, ich hab da dazu (weil die cpu ja schön flexibel ist) soviele optimierungen, dass ich recht zufrieden sein kann und es schneller läuft...

notfalls arbeit einfach mit 3frames delay, so schlimm wird es vielleicht ja garnicht wenn's dafür fix läuft.

man kann außer portalen auch antiportale nutzen, dafür gibt es bei gamasutra.com einen netten artikel.

ich rede auch nicht davon, dass static buffer geändert werden, sondern angenommen du hast ne wand und hinter ihr einen raum, damit du weißt, dass nichts von dem raum gezeichnet werden muss, mußt du erstmal alle objekte aus diesem raum in die buffer stopfen (das können ja mehrere MB sein) und dann gammeln die da enventuell rum, weil man sie nie sehen würde.

ich sage auch nicht, dass ein occlusion culler perfekte ergäbnisse liefert, aber man kann in dem gerade genannten beispiel einfach boxen um die objekte machen, wenn nun die wand gezeichnet wurde und man dann nur jeweils ne box testet, dann ist das doch sehr performant.

es gibt in levels ja meißt zwei arten von objekten, die die andere verdecken und die, die klein sind und nur verdeckt werden, aber nie verdecken.

wenn ich einen wald rendern würde, würde ich mir z.B. nicht viel performance dadurch versprechen, dass bäume andere bäume verdecken, sicherlich kann das sein wenn man genau vor einem stamm steht, aber wenn, dann würde sowas eher davon verdeckt werden, dass man in einer hütte drinne steht.
dafür kann man sich occluder definieren (sozusagen in und outcluder) die dinge die verdeckten haben dann occluder die kleiner sind als ihr volumen und die, die verdeckt werden haben größere occluder als ihr volumen.
alleine dadurch bekommst du ungemein performance.



in VS3.0+ oder so, da kann man aus buffern auslesen, damit könnte man das vielleicht pure GPU alles durchrechnen.


aber wie gesagt, 3frames delay ist doch echt net die welt...


MfG
micki

Demirug
2003-03-24, 16:01:27
Das mit dem Delay habe ich schon mal ausprobiert. Gerade wenn Objeckte aus dem veredeckten Bereich auftauchen führt das gerne mal zu unschönem Object Flimmern.

Anti-Portale habe ich doch erwähnt. Sie sind nur leider nicht ganz so effektiv wie Portale. Und wie gesagt soll man ja Tests die man trivial mit der CPU machen kann auch weiterhin machen.

Dein Beispiel mit den Objektem im Raum die ich erst in einem Buffer stopfen soll verstehe ich nicht ganz. Die Geometriedaten für diese Objekte sind doch sowieso schon längst in einem statischen Vertexbuffer umkopieren muss man da also nichts mehr.

Natürlich gibt es Fälle wo das ganze nichts mehr zusätzlich bringt weil kein Object das nicht schon trivial von der CPU rausgeworfen wird vollständig von einem anderen Object veredeckt wird. In diesem Fall hat man dann eben Pech gehabt. Aber da ein Z Pass bei komplexen Pixelshader ja fast immer von Vorteil ist und man die ObjectID Buffer aus Fillratesicht umsonst bekommen könnte halte ich das ganze nach wie vor für eine gute Idee.

PS: Man könnte mit diesem Verfahren durchaus auch nur mit occluder Boxen arbeiten. Dann den Z-Buffer löschen und die Szene ganz normal rendern und dafür auf den Object ID Count zurückgreifen.

micki
2003-03-24, 17:36:34
hmm... also in meiner engine ist kein objekt in statischen buffer(n) wenn es nicht zu sehen ist (natürlich mit delay, ich lösche nicht jedes zweite frame um dann die dinger nachzuladen).
gerade wenn man riesige welten hat und nur nen bruchteil sehen kann, wäre es leicht verschwenderisch zig MB in die static buffer zu schieben um zu merken dass sie nicht zu sehen sind (die meshes). deswegen hab ich lowpoly modelle von den objekten mit denen ich arbeite.

objeckte die verdeckt werden haben ein lowpoly occluder der sie umschließt ("outcludder"). (wenn also auch nur ein bruchteil des objektes zu sehen sein würde, sieht man 100%ig auch den occluder!)
objekte die verdecken haben ein lowpoly occluder das sie umschließen("includder").(wenn man also z.B. eine zylindrische säule hat aus 1mio pollys, dann steckt da eine box drinne als occluder)

ich hab also ne klassifikation der meshes. es ist nicht möglich dass eine tasse auf dem tisch eine wand verdeckt, aber umgekehrt. darauf teste ich nur, es wäre wirklich extrem unwahrscheinlich dass eine tasse die wand verdeckt, aber falls die das tun könnte, dann würde die tasse zusätzlich einen "includder" bekommen.

durch diese klassifikation hab ich folgende vorteile:

-es kann nicht passieren dass mal ein mesh als verdeckt berechnet wird obwohl es zu sehen ist, weil nur innere teile(includder) von anderen meshes verdecken können und es wird immer das umhüllender occluder vom mesh genommen zum testen ob es sichtbar ist also kann man das richtige mesh garnicht sehen ohne auch den äußeren occluder (outcludder) zu sehen. (schwer zu beschreiben)
-dadurch kann ich auf 128*128pixel testen ohne probleme zu haben, da die lowpoly occluder sowieso ungenau sind und das berechnet wurde.
-die lowpoly dinger verbrauchen kaum zeit zum nachladen, sind zusätzlich nur vertexpositionen die auch noch auf short komprimiert werden können.
-wenn ich eine scene rendern möchte, kann ich im vorraus wissen wieviel texturen und meshdaten ich laden muss (im gegensatz dazu müßte bei 3frames delay erstmal eventuell 3mal mehr texturen geschaufelt werden, also man schlussnedlich wirklich gebraucht hätte was gerade bei überfüllung der graka die fps bei mir früher von >30 auf 2fps brachte)
-keine framedelays, also auch unmöglich probleme mit aufpoppenden objekten


das was ich durch die cpu berechnungen verschwende, das holle ich locker wieder durch die erreichte optimierung rein.


ich kann übrigens 600k polys/s in meinen software z-buffer culler testen (p4 2ghz), wenn ich da 10k wirklich zeichnen muss macht das nicht die welt aus, besonders wie du gesagt hast, wenn eigentlich die graka schwitzt bei multipass pixelshadern mit wat weiß ich was für vector-rechner-brechern :)



also wenn das in hardware ginge, dann würde ich das sofort machen! das einzige was man vielleicht machen könnte wäre dass man irgendwie in seine pixelshader berechnungen die informationen aus dem ID-buffer benutzt und so früh wie möglich abbricht... da wärst du meiner methode vielleicht vorraus...


MfG
micki

Demirug
2003-03-24, 17:58:15
Du benutzt OpenGL, oder?

Ich frage nur weil sich dein Resourcenmanagement danach anhört. Bei D3D läst man solche Scherze bleiben. Alles was statisch ist kommt in Statische Vertexbuffer und für das was sich von Frame zu Frame ändert überträgt man mit einem dynamischen.

Das Verfahren das du beschreibst kenne ich. Mit einem Object ID Buffer könnte man das fast genauso in der Hardware realisieren. Das es mit dem Buffer aleine nicht getan ist dürfte ja klar sein. Auch das Resourcenmangement müsste etwas verbesssert werden.

Noch eine Frage: Setzte du vor deinem Z-Buffer noch andere Verfahren zu aussortieren von unsichtbaren Objekte ein?

micki
2003-03-24, 18:14:20
meine engine nutzt opengl und d3d und ich finde dass scenen mit 500kpolys (32byte/vertex also ca 16MB trotz indices) unnötig sind, ich behalte soviel nicht im buffer, nvidia und ati schreiben in deren papern auch, dass man sowas nicht machen sollte, die sagen in etwa man sollte soviel speicher für buffer benutzen wie nnötig, weil zuviel einfach nur verschwendung sind. ich brauche nur einen drittel des buffers.
john carmack und nvdia haben mal irgendwo gesagt, dass das opengl interface diesbezüglich dem programmierer besser veranschaulicht was intern abläuft und so eher erlaubt vernünftig selbst zu managen. In den neuen Ati papern steht glaube ich, dass man sich ruhig einen static buffer besorgen soll und dort alle daten reinstecken kann und sie managen kann. ab dx9 ist es ja möglich verschiedene formate im selben buffer zu haben.

ich glaube bei grakas ist speicehr genauso wichtig geworden wie woanders auch.. also unnötig würde ich nicht dinge drauf packen (unnötig=nicht sichtbar auf lange zeit hin)

ich nutze noch antiportale, natürlich frustum-culling, coherenz und ein paar speziele ausgedachte pvs.

:)

MfG
micki

Demirug
2003-03-24, 18:33:29
naja polys kann man nie genug haben. Man sollte allerdings schon ein LOD haben.

Ich meinte auch nicht das man einen riesigen Buffer haben soll in den man alles reinhaut (OK bei DX7 war das schon besser). Sondern das man Vertexdaten die man nur für die Grafikkarte braucht schon mal in einen Vertexbuffer hat und diesen dann bei Bedarf aktiviert. Das umkopieren des Inhalts eines Vertexbuffer wird von MS und NVIDIA als suboptimal gesehen weil es die Grafikkarte stallen kann. Eine Aussnahme sind natürlich die extra für diesen Zweg gedachten dynamischen Buffer aber die muss man dann ja für jeden Frame neu beschreiben.

Das mit den unterschiedlichen Formate in einem Buffer geht auch schon bei DX8. Dort ist es nur etwas kompliziert zu handhaben. Der Vorteil von DX9 ist aber das es jetzt viel einfacher ist Vertexshader und Vertexdaten aus unterschiedlichen Buffer zu kombinieren. Früher musste man dafür dengleichen Vertexshader mehrfach haben.

Und ja Speicher ist immer wichtig und man wird nie genug haben ;)

micki
2003-03-24, 18:45:46
das erste mal sind wir in einem thread gleicher meinung :)

MfG
micki

Crazytype
2003-03-28, 19:42:07
an was für projekten arbeitet ihr denn? Micki du entwickelst schon eine eigene Engine, was machst du? Das selbe geht natürlich auch an Demi.

Demirug
2003-03-28, 20:18:48
Originally posted by Crazytype
an was für projekten arbeitet ihr denn? Micki du entwickelst schon eine eigene Engine, was machst du? Das selbe geht natürlich auch an Demi.

Genau wie Micki arbeite ich auch an einer Engine. Über die Projekte die darauf aufbauen darf ich aber nichts sagen sonst bekomme ich Ärger.

loewe
2003-03-29, 10:12:31
Mal in diesem Zusammenhang lesen:

http://l2.espacenet.com/espacenet/bnsviewer?CY=gb&LG=en&DB=EPD&PN=GB2378108&ID=GB+++2378108A++I+

Demirug
2003-03-29, 12:31:24
Originally posted by loewe
Mal in diesem Zusammenhang lesen:

http://l2.espacenet.com/espacenet/bnsviewer?CY=gb&LG=en&DB=EPD&PN=GB2378108&ID=GB+++2378108A++I+

Das Patent beschreibt ein Verfahren zur Nutzung eines Z-Range Buffers zur Reduktion des Bandbreiten und Speicherbedarfs für das Binning.

Um das ganze nun in diesen Zusammenhang zu bringen.

Eine Erweiterung dieses Verfahrens würde ein Object Culling mit einschränkungen erlauben. Eingeschränkt deshalb weil es nicht vollständig möglich ist Objekten nachträglich die Sichtbarkeit wieder abzuerkennen. Bei Objekten die aufgrund des Z-Range Buffers vollständig aussortiert werden und deshalb niemals die Displayliste erreichen könnte man in den entsprechneden Buffer gleich eine 0 schreiben. Wird ein Object allerdings erst nachträglich von einem andere verdeckt so ist es aufgrund der reduzierten Informationsmenge im Z-Range buffer wie gesagt nur noch in speziellen Fällen möglich den Sichtbarkeitscounter wieder zu reduzieren. Damit es funktioniert muss die neue Range den Z-Test vollständig (sowohl der min wie auch der Maxwert) bestehen und das Dreiecksfragment die Tile vollständig abdecken. In diesem Fall könnte dann alles was bisher in dieser Tile ist verworfen werden und für jedes Fragment das sich dort befindet der entsprechende Counter wieder reduziert werde. Da aber gerade die zweite Bedingung sich aufgrund immer kleiner werdender Dreiecken nur schwer erfüllen läst lohnt es sich IMO gar nicht erst für die bearbeitung dieses Falls Transitoren einzusetzen. Ein Object Culling welches aufgrund eines Z-Range Buffers durchgeführt wird ist also darauf angewiesen das die Objeckte möglichst Front to Back kommen. Aber das ist ja auch für eine hohe Effektivität des in dem Patent beschriebenen Verfahrens von Vorteil.

Interesant an dem Verfahren ist allerdings das damit auch ein TBDR von einem Early-Z Pass profitiert und man in gewiesser Weisse von dem IMR Kollegen sich was abgeschaut hat.

P.S: mit diesem Verfahren sollte sich auch die vorhanden Occlussion Culling Extensions für OpenGL sowie die entsprechende Funtion in DX9 unterstützen lassen. Zwar nicht mit der gleichen Genauigkeit wie bei einem IMR aber immer noch besser als gar nicht.

micki
2003-03-31, 16:52:32
in der arbeit addaptiere ich die vorhandene engine an bedürfnisse (schreibe also ergänzungen oder manchmal teile der engine um)

zuhause hab ich viele projekte am laufen z.B. meine engine und auch einige spiele.. mit ein grund für meine max 3h schlaf die nacht :D

MfG
micki

ps. bin süchtig nach coden.

Ailuros
2003-04-11, 03:53:29
Originally posted by loewe
Mal in diesem Zusammenhang lesen:

http://l2.espacenet.com/espacenet/bnsviewer?CY=gb&LG=en&DB=EPD&PN=GB2378108&ID=GB+++2378108A++I+

Obwohl es der Mehrheit hier schon bekannt ist, moechte ich betonen dass das Patent am 24. Juli 2001 eingereicht wurde :)

Kant
2004-04-28, 02:21:37
Auch wenn es an Leichenschändung grenzt einen 1 Jahr alten Thread auszugraben....

Aber die Diskussion bei opengl.org unter :
http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=3;t=011740

beschreibt doch eine Extension (für den NV40) die auf das hinausläuft was Demirug hier forderte, oder ?

Demirug
2004-04-28, 07:55:36
Original geschrieben von Kant
Auch wenn es an Leichenschändung grenzt einen 1 Jahr alten Thread auszugraben....

Aber die Diskussion bei opengl.org unter :
http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=3;t=011740

beschreibt doch eine Extension (für den NV40) die auf das hinausläuft was Demirug hier forderte, oder ?

Ja, das scheint in die Richtung zu gehen.

Matti
2004-04-29, 12:52:37
Original geschrieben von micki
ich kann übrigens 600k polys/s in meinen software z-buffer culler testen (p4 2ghz), wenn ich da 10k wirklich zeichnen muss macht das nicht die welt aus, besonders wie du gesagt hast, wenn eigentlich die graka schwitzt bei multipass pixelshadern mit wat weiß ich was für vector-rechner-brechern :)


Heutige Grafikkarten schaffen 20-50 MTris/s wenn man Display-Listen verwendet, also bringt dein SW-Culling nur was bei Shader-lastigen Szenen.

Original geschrieben von Demirug
In DX9 (bei OpenGL Herstellerabhängig schon länger) gibt es eine entsprechende Funktion die zählen kann wie viele Pixel sich verändert haben.

welche OpenGL-Funktion isses denn? *beidenganzenextensionsnichtmehrdurchblick*

Demirug
2004-04-29, 13:25:46
Original geschrieben von Matti
welche OpenGL-Funktion isses denn? *beidenganzenextensionsnichtmehrdurchblick*

GL_HP_occlusion_test (http://oss.sgi.com/projects/ogl-sample/registry/HP/occlusion_test.txt)

GL_NV_occlusion_query (http://oss.sgi.com/projects/ogl-sample/registry/NV/occlusion_query.txt)

zeckensack
2004-04-29, 23:41:00
Original geschrieben von Demirug
GL_HP_occlusion_test (http://oss.sgi.com/projects/ogl-sample/registry/HP/occlusion_test.txt)

GL_NV_occlusion_query (http://oss.sgi.com/projects/ogl-sample/registry/NV/occlusion_query.txt) Oder das hier:
ARB_occlusion_query (http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt)
How is this extension different from NV_occlusion_query?

The following changes have been made.
A "target" parameter has been added. Only one target exists at present, SAMPLES_PASSED_ARB, but future extensions could add additional types of queries.
Terminology changed slightly. "Pixel" was being used incorrectly, where "fragment" or "sample" would be more accurate.
Various NVIDIA-specific references have been removed.
Interactions with multisample have been changed slightly to allow implementations based on either a sample count or a fragment count. The result is returned in units of samples.
Clarified that using an id of zero is illegal.
Added missing spec language for IsQuery entry point.
General language, issues, etc. cleanup.
HP_occlusion_test is no longer required.
Modified the minimum required counter bits to be dependent on the implementation's maximum viewport or the value 0
Clarified that active query state is per target server state. This implies that a loop of QUERY_RESULT_AVAILABLE_ARB will return TRUE in finite time. NV_occlusion_query asked that the application flush to prevent an infinite loop.
Clarified the behavior of the async QUERY_RESULT_AVAILABLE_ARB command.
When the count of samples that pass the occlusion query overflows, the value should saturate.

Hardware- und Treiber-Support für diese Extension (http://www.delphi3d.net/hardware/extsupport.php?extension=GL_ARB_occlusion_query)

micki
2004-04-30, 21:40:36
Original geschrieben von Matti
Heutige Grafikkarten schaffen 20-50 MTris/s wenn man Display-Listen verwendet, also bringt dein SW-Culling nur was bei Shader-lastigen Szenen.

Wie ich schon schrieb, die großen Datenmengen möchte ich garnicht erst anfassen müssen wenn ich nicht vorher teste ob sie nötig sind. Ich teste dementsprechend bounding Volumes wie z.b. BoundingBoxes, ConvexHulls in meinem software renderer, also vielleicht nur ~25 triangles pro objekt dass aus ~5k triangles besteht.
Meine engine zeichnet dir auf diese weise gerne und locker 50MTris/s auf den Screen (Ati9500pro), also nicht nur stumpf 50MTris von denen du 5M siehst, sondern 50M die du höchstwahrscheinlich sehen wirst (naja 50% wegen backfaceculling usw.).
Dabei versuch ich auch nicht die Vertices die auf der Graka transformiert werden zu minimieren, sondern diejenigen die überhaupt hochgeladen werden müssen, denn das limitiert viel mehr.
wenn du dir überlegst, dass du in einem Level ohne probleme deine 10MTris hast, 32byte pro Tri bzw vertex, dann bist du bei 320MB, was machst du nun? schiebst du in deinen 512MB AGP speicher die vollen 320MB hoch und hoffst dass D3D sie vernünftigt in die Graka je nach not hinschiebt? oder steckst du für nen grossteil davon nur bounding volumes rein und fragst nach 5frames ab ob das volume gesehen werden würde und poppst dann für den spieler vielleicht sichtbar ein objekt auf? hmm.. oder renderst paar frame immer im voraus bevor er die perspektive ändert?

ich teste einfach die bounding volumes gegen meine occlusion map, das kann ich zudem schön aus allen möglichen perspektiven zugleich machen, also locker für 6 spotlights pro frame (ist ja fix). die pixelshaderleistung und speichermenge die ich dabei auf der graka spar' ist gerade bei dynamischen scenen sehr enorm! und da bin ich vollkommen flexibel, ich brauche kein bsp, keine portale, absolut "garnichts" statisches oder vorberechnetes in der scene selber, nur die objekte müssen beim convertieren ein paar berechnungen über sich ergehen lassen und Modeller können im Level ihre Einstellungen für Objekte machen.

MfG
micki