FSAA? Multisampling?



  • Das 1-Byte-Alignment hat keine Auswirkungen weil die floats eh 32bit gross sind.
    Du solltest Deinen Indexbuffer so sortieren, dass moeglichst linear aus dem Vertexbuffer gelesen wird und moeglichst viele Vertices aus dem (kleinen) Post-T&L-Cache wiederverwendet werden koennen.



  • hellihjb schrieb:

    Das 1-Byte-Alignment hat keine Auswirkungen weil die floats eh 32bit gross sind.
    Du solltest Deinen Indexbuffer so sortieren, dass moeglichst linear aus dem Vertexbuffer gelesen wird und moeglichst viele Vertices aus dem (kleinen) Post-T&L-Cache wiederverwendet werden koennen.

    Das mit dem Sortieren ist mir jetzt irgendwie unklar.
    Ich habe ne Menge triangles mit ziemlich durchgemischten Indizes. Was ist denn da eine gute Sortierung?
    wenn ich jetzt die Dreiecke
    1,2,3
    5,1,3
    4,2,5
    2,4,1
    5,4,3

    hätte... Ich kann mir jetzt nicht wirklich etwas überlegen um die indices linear verlaufen zu lassen... Ich könnte natürlich auch schon beim exportieren die vertices sortieren...



  • Selbst bei nur 17 vertices und 36 indizes sieht man den unterschied in der framerate (ca. 5-6 frames) da kann doch irgendwas nicht stimmen?
    edit: ich glaube das mit dem sortieren des Indexbuffers hat einen eigenen Thread verdient...


  • Mod

    Azrael, il Meraz schrieb:

    16 bit anstatt 32 Bit Indices geben 2-3 frames mehr (bei 200 frames insgesamt)

    Ich bin dem Artikel bei oZone3D gefolgt und meine Datentypen so definiert:

    #pragma pack(push, 1)
    typedef struct
    {
        float x;
        float y;
        float z;
    } AL_VertCrd;
    #pragma pack(pop)
    

    das soll weniger datenscheffel verursachen. hatte diese pragmas auch grad weggelassen - kein performanceunterschied. Hatte meine Datentypen auf 32 bits um leere member ergänzt - hatte performanceverlust von 5-10%.

    Im Vertexbuffer wird jeder vertex mindestens einmal im element array buffer indiziert...

    aber du hast nicht jede deiner structs sondern schon das ganze vertex auf 32byte alligned, oder?



  • Ich poste mal hier, weils hier eher um mehrere buffer/ein buffer geht.

    Kann es sein, dass die GeForce FX serie eine ziemliche ausnahme bei mehreren buffern/einem Buffer ist? Ich habe nähmlich bei gleichem Code mit meiner GeForce FX 5500 bei mehreren Buffern einen performancegewinn von ca. 30-40%. während bei einer integriertel inten GMA x3100 die performance um ca. 10-15% sinkt. mit einer GeForce 8800gt spürt man bei meinem ursprünglichen model kaum was, bei einem model mit 30x sovielen vertices kann man bei mehreren Buffern auch einen performanceverlust von ca 20% erkennen.

    Frage: ist die GeForce FX ein krüppel? :D:D:D



  • Ich hab eine Geforce 8800 GTS und auch mehrere Buffer. Je einen für Vertices, TextureCoords und Material. Ich sehe keinen Unterschied, wenn ich es auf einen reduziere, was die FPS angeht. Auch bei meiner ATI die onboard läuft ist kein Unterschied. Hab auch schon beide Methode ausprobiert. Bei NEHE propagieren Sie 3 Buffer im Tutorial zu VBO, auf anderen Seiten einen Buffer.
    rya.



  • Wenn die einzelnen Buffer sequentiell, dh streaming- & cache-freundlich, ausgelesen werden koennen macht es *keinen* Unterschied wieviele Buffer es gibt weil die zu uebertragende Datenmenge gleich ist (grobe Fehler in Treiber und/oder Hardware ausgenommen).
    Die Kosten "eines" Cache-Miss multiplizieren sich aber mit der Anzahl der Buffer.

    Der Vorteil getrennter Buffer liegt aber auf der anderen Seite:
    Will man die Geometrie CPU-seitig veraendern (Animation/Skinning) muessen nicht alle Vertexattribute uebertragen werden und man spart einen erheblichen Prozentsatz Bus-Traffic.



  • Passt vielleicht ganz gut, was ich gestern gecodet habe: Ich bake in einem größeren Level für alle statischen Models per-Vertex-Ambient Occlusion (per Vertex reicht, da die Models sowieso eher organisch sind und deshalb eine ziemlich hohe Tesselierung haben). Das habe ich so implementiert, dass jede Instanz von einem statischen Model im Level ihren eigenen AO-Daten-Stream hat. Die anderen Daten für Position, Normal, Texcoord, Tangent etc werden klarerweise geshart.

    Das lässt sich relativ problemlos ins Rendering integrieren, indem einfach je nach Model-Instanz ein anderer AO-Stream reingehängt wird, die Vertex Declaration bleibt immer dieselbe (die sagt ja nur, dass es einen zusätzlichen Stream für AO gibt, nicht welchen). Das würde natürlich auch funktionieren wenn Positions, Normals etc in einem interleaved buffer gespeichert wären, aber es ist mir gerade eingefallen als nette Verwendungsmöglichkeit für mehrere Stream Sources.


  • Mod

    hellihjb schrieb:

    Wenn die einzelnen Buffer sequentiell, dh streaming- & cache-freundlich, ausgelesen werden koennen macht es *keinen* Unterschied wieviele Buffer es gibt weil die zu uebertragende Datenmenge gleich ist (grobe Fehler in Treiber und/oder Hardware ausgenommen).
    Die Kosten "eines" Cache-Miss multiplizieren sich aber mit der Anzahl der Buffer.

    mit steigender anzahl buffer hast du spruenge im speicher, random reads sind dabei teuerer als wenn alles in der sellben speicherbank waere. cachemisses hast du wie gesagt nicht, alle speicheranfragen sind vorhersehbar und somit kann auch alles im voraus geladen werden. stalls hast du jedoch, wenn das reinstreaming nicht schnell genug ist z.b. eben wegen random reads.



  • Tut mir leid die Werte die ich oben angegeben hab waren nicht richtig. Ich hab paar fehler im code gemacht die mir auf den anderen systemen performance gekostet haben. Ein großer Buffer macht wohl nicht wirklich Sinn wenn er keine Interleavte Vertexattribute speichert :).

    Habs jetzt mit optimierter Geometrie versucht... Die war zuvor wohl noch besser optimiert :D.

    Ich bleib jetzt auf jeden Fall bei mehreren Buffern 🙂



  • cachemisses hast du wie gesagt nicht, alle speicheranfragen sind vorhersehbar

    Die Reihenfolge ist aufgrund des Indexbuffers zwar bekannt, aber das Streaming der Vertex-Daten in den Pre-T&L-Cache unterliegt dabei der Groesse der Cache-Line. Es wird also zwangslaeufig nicht nur der Vertex des naechsten Index uebertragen sondern die darauffolgenden "n" Vertices.
    Darum ist der Pre-T&L-Cache verhaeltnismaessig gross ausgelegt um hier unnoetigen Speichertraffic zu vermeiden.
    Ein "Cache-Miss" (Daten die im Cache erwartet werden sind noch nicht da weil "falsche" Daten uebertragen worden sind) kommt also durchaus vor.

    mit steigender anzahl buffer hast du spruenge im speicher

    Bei "n" Buffern muessen zunaechst auch "n" Cache-Lines gelesen werden (dafuer sind damit auch entsprechend mehr Vertices "da"). Da die Latenz beim Rendercall ohnehin riesig ist, bezweifle ich dass man das irgendwie erfassen koennte.


  • Mod

    hellihjb schrieb:

    cachemisses hast du wie gesagt nicht, alle speicheranfragen sind vorhersehbar

    Die Reihenfolge ist aufgrund des Indexbuffers zwar bekannt, aber das Streaming der Vertex-Daten in den Pre-T&L-Cache unterliegt dabei der Groesse der Cache-Line. Es wird also zwangslaeufig nicht nur der Vertex des naechsten Index uebertragen sondern die darauffolgenden "n" Vertices.

    es geht nicht darum wieviele vertices auf einmal reinpassen, sondern wie gross die latenz ist um alle daten fuer einen vertex einzulesen.
    hast du einen buffer, hast du (besonders mit vertex reordering entsprechend den indices) eine recht sequentielle lesereihenfolge, darauf ist die hardware optimiert.
    hast du 8 streams, musst du 8mal switchen (selbst wenn du 8vertices bei jedem durchgang wegen der cacheline groesse gelesen hast).
    verglichen mit dem eigentlichen datentransfer ist der erste zugriff extrem teuer. das kann man sich wie mit dem streamen von cd/DVD vorstellen, liegen alle daten hintereinander und liest man sie so, kann man selbst bei 75% redundanzdaten schneller sein als wenn man die optimale datenmenge lesen wuerde, dafuer aber jedesmal seekt.

    Darum ist der Pre-T&L-Cache verhaeltnismaessig gross ausgelegt um hier unnoetigen Speichertraffic zu vermeiden.

    der puffer ist relativ klein, weil
    1. es keinen sinn macht vor dem VS einen grossen cache zu haben, den legt man eher dahinter an
    2. es nur ein streampuffer ist, die sind sehr winzig, weil davon ausgegangen wird, dass die daten nur einmal benutzt werden (was mit den caches danach auch zu 80% so ist). das heisst, die caches mit der funktionsweise von cpu caches wuerden ueberhaupt nur 20% der zugriffe auffangen muessen, diese 20% sind zudem so extrem vorhersehbar dass man sie reinstreamen kann bevor es soweit ist.
    grosse caches wuerden nur was bringen bei sehr schlechten daten, also wenig, vertices, dafuer aber extrem verstreut und oft wiederverwendet.
    doch genau das umgeht man mit der softwareseitigen optimierung.

    Ein "Cache-Miss" (Daten die im Cache erwartet werden sind noch nicht da weil "falsche" Daten uebertragen worden sind) kommt also durchaus vor.

    ich weiss nicht genau was du mit 'falsche daten uebertragen worden sind' meinst. es werden genau die uebertragen die 'bald' benutzt werden, spekulativ werden keine daten geladen, sie koennen also nicht falsch sein. (deswegen denk ich du meinst was anderes?)

    mit steigender anzahl buffer hast du spruenge im speicher

    Bei "n" Buffern muessen zunaechst auch "n" Cache-Lines gelesen werden (dafuer sind damit auch entsprechend mehr Vertices "da"). Da die Latenz beim Rendercall ohnehin riesig ist, bezweifle ich dass man das irgendwie erfassen koennte.

    ich meine verschiedene buffer in einem drawcall aus denen gestreamt wird, statt einen vertexbuffer.



  • Es wird niemals ein einzelner Vertex eingelesen sondern immer eine gesamte Cache-Line (deren Groesse ist mir nicht bekannt, beinhaltet aber *mehrere* Vertices).
    Das Einlesen der Vertices orientiert sich also nicht ausschliesslich an den Indizes, sondern es landen zwangslaeufig zusaetzliche Vertices im Cache wenn das Indexing nicht strikt sequenziell verlaeuft.
    Aus diesem Grund ist der Pre-T&L-Cache sehr gross (im Megabyte-Bereich) - auch wenn Du mir das partou nicht glauben moechtest 😉


  • Mod

    hellihjb schrieb:

    ... auch wenn Du mir das partou nicht glauben moechtest 😉

    mit moechten hat das nicht viel zu tun. auch wenn ich es 100% weiss, hab ich gerade in den hardware manuals die ich von den wichtigsten gpus habe nachgesehen, laut denen ist es ein bruchteil von dem was eine normale cpu als L1 cache hat. (tut mir leid, genaue zahlen darf ich nicht sagen).

    wenn man kurz sucht, findet man auch an anderen stellen aussagen dass der cache relativ klein ist: z.b.

    wenn der cache gross waere, waere es einem egal wie das allignment von den vertices ist, weil im sram random zugriffe egal sind, da muss man sich nicht um cachelines sorgen. wenn zugriffe aber cachekritisch sind, muss man das schon, und jeder gpu hersteller sagt, dass man 32byte allignen soll, damit man den cache besser ausnutzt. das haette wenig sinn wenn der cache gross waere.



  • rapso schrieb:

    und jeder gpu hersteller sagt, dass man 32byte allignen soll, damit man den cache besser ausnutzt. das haette wenig sinn wenn der cache gross waere.

    moment mal. 32 BYTE? oder doch bit?


  • Mod

    Azrael, il Meraz schrieb:

    rapso schrieb:

    und jeder gpu hersteller sagt, dass man 32byte allignen soll, damit man den cache besser ausnutzt. das haette wenig sinn wenn der cache gross waere.

    moment mal. 32 BYTE? oder doch bit?

    byte 😉 kleiner als 32bit koenntest du garnicht allignen, das muesste man also nicht explizit nennen 😉



  • gilt das jetzt für interleavte buffer oder allgemein?



  • hab ich gerade in den hardware manuals die ich von den wichtigsten gpus habe nachgesehen, laut denen ist es ein bruchteil von dem was eine normale cpu als L1 cache hat

    In den Unterlagen vom XDK (XBox1 wohlbemerkt) wird die Groesse mit 4kB beziffert.
    Fuer aktuelle GPUs findet man wenig konkretes aber haeufig dieses:

    Pre T&L cache:
    – Much larger than post T&L cache:
    – On GeForce FX 3000: ~8,000 vertices
    – On GeForce FX 6800: ~64,000 vertices

    Quelle: Rendering Huge Triangle Meshes with OpenGL.



  • Argh - mein vertex ist 36 byte groß. Lohnt sich da eine aufstockung auf 64 byte?


  • Mod

    hellihjb schrieb:

    hab ich gerade in den hardware manuals die ich von den wichtigsten gpus habe nachgesehen, laut denen ist es ein bruchteil von dem was eine normale cpu als L1 cache hat

    In den Unterlagen vom XDK (XBox1 wohlbemerkt) wird die Groesse mit 4kB beziffert.

    nett dass du an NDA informationen freigibst 🙂
    und 128 vertices find ich schon recht winzig und du wuerdest erstaunt sein wie wenig sich dieser wert veraendert hat.

    Fuer aktuelle GPUs findet man wenig konkretes aber haeufig dieses:

    Pre T&L cache:
    – Much larger than post T&L cache:
    – On GeForce FX 3000: ~8,000 vertices
    – On GeForce FX 6800: ~64,000 vertices

    Quelle: Rendering Huge Triangle Meshes with OpenGL.

    von ati gibt es wohl irgendwo public informationen dass es 32kb sind bei den allerneusten karten.

    wie gesagt, das sind winzige caches, verglichen mit der groesse die ein normales mesh hat und sie dienen nur dem streming, entsprechend sieht du sicher auch in deinem nda papern dass sie anders organisiert sind. das sind gerade mal 16 zugriffe von einem vertexshader-array mit 8units.

    die zahlen mit 64000vertices, also 2MB (bei 32byte/vertex) hat kein streaming chip.


Anmelden zum Antworten