performance: (geometry instancing) uniform buffers vs glVertexAttribDivisor



  • rapso schrieb:

    TravisG schrieb:

    rapso schrieb:

    TravisG schrieb:

    ...(beim Rendern von ~5000 Dreiecken). ...

    ist dir klar dass es beim instanzing um drawcalls und nicht um dreiecke geht?

    ja, und? was hat das mit dem problem zu tun?

    ein trecker der mehr PS als ein sportwagen hat wird nicht zwingend eine kuerzere zeit auf dem nuerburgring bringen.

    du baust nen trecker -> wunderst dich ueber die doppelte rundenzeit.

    Verstehe nicht was du meinst. Beide Varianten zeichnen 5000 Dreiecke. Beide Varianten sind benutzen Instancing. Hab die Zahl nur angegeben, falls sie für irgendwas relevant sein könnte.



  • Worauf er hinauswill: Die Anzahl an Dreiecken allein sagt hier überhaupt nichts aus. Interessant wäre vor allem die Anzahl an Instanzen und erst dann evtl. die Anzahl der Dreiecke pro Instanz, da man ja davon ausgehen muss, dass eine Instanz aus relativ wenigen Dreiecken besteht, denn wieso würdest du sonst Instancing verwenden wollen... 😉

    Btw: 5k Dreiecke sind für eine moderne GPU gar nix, das packt vermutlich sogar dein Smartphone ohne größere Probleme... 😉



  • dot schrieb:

    Worauf er hinauswill: Die Anzahl an Dreiecken allein sagt hier überhaupt nichts aus. Interessant wäre vor allem die Anzahl an Instanzen und erst dann evtl. die Anzahl der Dreiecke pro Instanz, da man ja davon ausgehen muss, dass eine Instanz aus relativ wenigen Dreiecken besteht, denn wieso würdest du sonst Instancing verwenden wollen... 😉

    Btw: 5k Dreiecke sind für eine moderne GPU gar nix, das packt vermutlich sogar dein Smartphone ohne größere Probleme... 😉

    Achso... Sorry 🤡 Das sind 5000 Instanzen (ein Dreieck pro Instanz). Dachte ich impliziere das stark genug wenn ich über Instancing rede.

    ~300 Tris pro Instanz haben am Performancebild nichts geändert. Wie es mit mehr oder weniger Instanzen aussieht weiss ich nicht. Weniger hab ich nichts getestet, bei 10k ist mir die Grafikkarte abgeschmiert und ich hab mich nicht mehr getraut.


  • Mod

    gibt gl_InstanceID nicht die ID der primitive an und nicht von tatsaechlichen instanz?

    anyway, wei schon paar mal gesagt, instanzing optimiert fuer drawcalls, du misst gpu performance, drawcalls sind jedoch cpu basirend.

    wie du feststellst, constant reading ist schneller als main-memory reading auf der gpu.

    wie zeichnest du mit uniform buffern 10k instances mit je 100 polys?



  • rapso schrieb:

    gibt gl_InstanceID nicht die ID der primitive an und nicht von tatsaechlichen instanz?

    Nö, das was du meinst ist wohl gl_PrimitiveID... 😉


  • Mod

    ok, mein ogl sheet sagte es ist ein 'primitive id', so wie hier
    http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_InstanceID.xml
    dann sorry.



  • rapso schrieb:

    gibt gl_InstanceID nicht die ID der primitive an und nicht von tatsaechlichen instanz?

    Nö das ist die Instanz. Zumindest wüsste ich nicht warum mein Code sonst funktioniert. Hier (http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_InstanceID.xml) steht zwar auch es ist die Primitive, aber ich glaube das ist nur schlechte Wortwahl.

    wie du feststellst, constant reading ist schneller als main-memory reading auf der gpu.

    Hm... kannst du das genauer erklären? Naiv würde ich mir vorstellen dass sowohl bei nem Uniform Buffer als auch bei nem normalen Array Buffer das Zeug irgendwo auf der Grafikkarte im Speicher landet und dann irgendwie beim Ausführen des Shaders herangezogen wird. Die Ausgangsdaten finde ich sehen ziemlich gleich aus... bei beiden Varianten weiss die Grafikkarte wie groß die Gesamtladung ist, die Datenmenge unterscheidet sich nicht, beides liegt kontinuierlich im Speicher. Wird eines der beiden Buffer-Varianten besonders behandelt?

    wie zeichnest du mit uniform buffern 10k instances mit je 100 polys?

    10k gar nicht, da gabs bei mir nen fullscreen-quad der über den rgb farbraum interpoliert hat 🤡

    Aber prinzipiell einfach ein Uniform-Buffer der 10k Matrizen hat (oder halt sonstige Daten die sich pro Instanz ändern) und dann wie oben gesehen im Shader hardgecodet wie viel da ankommt (geht bestimmt etwas eleganter).

    Oder gehts dir um was anderes?



  • rapso schrieb:

    ok, mein ogl sheet sagte es ist ein 'primitive id', so wie hier
    http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_InstanceID.xml
    dann sorry.

    Da hast du wohl einen Fehler in den Reference Pages gefunden:

    OpenGL Specification schrieb:

    gl_InstanceID holds the integer instance number of the current primitive in an instanced draw call



  • TravisG schrieb:

    Naiv würde ich mir vorstellen dass sowohl bei nem Uniform Buffer als auch bei nem normalen Array Buffer das Zeug irgendwo auf der Grafikkarte im Speicher landet und dann irgendwie beim Ausführen des Shaders herangezogen wird.

    Richtig; allerdings hat eine GPU verschiedene Speicherbereiche (eigentlich einfach verschiedene Caches), die für verschiedene Zugriffsmuster optimiert sind. Instanzdaten, die du mit den Vertices fütterst, gehen durch den vertex fetcher (Input Assembler Stage), der (zumindest auf Desktop Hardware) der zwar vermutlich auch cached, aber offenbar nicht so ganz auf Broadcasting (verteilen der gleichen Daten an mehrere Cores) ausgelegt ist und die Werte wohl relativ oft aus dem Global Memory holen wird. Uniform Buffer dagegen, liegen im Constant Memory, d.h. die gehen durch den sog. Constant Cache, der einzig und allein auf gleichzeitigen Zugriff von vielen Cores auf die selbe Adresse ausgelegt ist... 😉


  • Mod

    TravisG schrieb:

    rapso schrieb:

    gibt gl_InstanceID nicht die ID der primitive an und nicht von tatsaechlichen instanz?

    Nö das ist die Instanz. Zumindest wüsste ich nicht warum mein Code sonst funktioniert. Hier (http://www.opengl.org/sdk/docs/manglsl/xhtml/gl_InstanceID.xml) steht zwar auch es ist die Primitive, aber ich glaube das ist nur schlechte Wortwahl.

    war nur eine randnotiz, nicht dass wir birnen mit aepfeln vergleichen 😉

    wie du feststellst, constant reading ist schneller als main-memory reading auf der gpu.

    Hm... kannst du das genauer erklären? Naiv würde ich mir vorstellen dass sowohl bei nem Uniform Buffer als auch bei nem normalen Array Buffer das Zeug irgendwo auf der Grafikkarte im Speicher landet und dann irgendwie beim Ausführen des Shaders herangezogen wird. Die Ausgangsdaten finde ich sehen ziemlich gleich aus... bei beiden Varianten weiss die Grafikkarte wie groß die Gesamtladung ist, die Datenmenge unterscheidet sich nicht, beides liegt kontinuierlich im Speicher. Wird eines der beiden Buffer-Varianten besonders behandelt?

    constant buffer sind glaube ich das zweit bzw dritt schnellste (je nach hw), einzig register sind schneller (und manchmal wohl local store -> stack wuerde ein c programmer wohl sagen, aber das siehst du als 3d programmierer wohl nichtmal, nur ocl/cuda).

    wie zeichnest du mit uniform buffern 10k instances mit je 100 polys?

    10k gar nicht, da gabs bei mir nen fullscreen-quad der über den rgb farbraum interpoliert hat 🤡

    emm, du meinst, du zeichnest dauernt fullscreen quads zum benchmarken?
    (ich denke ich missverstehe)

    Aber prinzipiell einfach ein Uniform-Buffer der 10k Matrizen hat (oder halt sonstige Daten die sich pro Instanz ändern) und dann wie oben gesehen im Shader hardgecodet wie viel da ankommt (geht bestimmt etwas eleganter).

    Oder gehts dir um was anderes?

    ich wollte sehen wie du die drawcalls abschickst und was genau zu zeichnest. z.b. waere es fuer soeinen benchmark unnoetig ueberhaupt pixel zu zeichnen.



  • rapso schrieb:

    wie zeichnest du mit uniform buffern 10k instances mit je 100 polys?

    10k gar nicht, da gabs bei mir nen fullscreen-quad der über den rgb farbraum interpoliert hat 🤡

    emm, du meinst, du zeichnest dauernt fullscreen quads zum benchmarken?
    (ich denke ich missverstehe)

    Meine Grafikkarte ist abgeschmiert, danach hab ich das Testen sein lassen.

    Aber prinzipiell einfach ein Uniform-Buffer der 10k Matrizen hat (oder halt sonstige Daten die sich pro Instanz ändern) und dann wie oben gesehen im Shader hardgecodet wie viel da ankommt (geht bestimmt etwas eleganter).

    Oder gehts dir um was anderes?

    ich wollte sehen wie du die drawcalls abschickst und was genau zu zeichnest. z.b. waere es fuer soeinen benchmark unnoetig ueberhaupt pixel zu zeichnen.

    glUseProgram(_shader);
    
    //methodenabhaengig hier dann noch uniform buffer oder normalen buffer updaten
    
    glBindBuffer(GL_ARRAY_BUFFER,_buffer);
    glEnableVertexAttribArray(VERTEX_ATTRIB_INDEX);
    
    glVertexAttribPointer(VERTEX_ATTRIB_INDEX,4,GL_FLOAT,GL_FALSE,0,0);
    
    glDrawArraysInstanced(GL_TRIANGLES,0,_numTriangles,instanceCount);
    
    glDisableVertexAttribArray(VERTEX_ATTRIB_INDEX);
    
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glUseProgram(0);
    


  • TravisG schrieb:

    rapso schrieb:

    wie zeichnest du mit uniform buffern 10k instances mit je 100 polys?

    10k gar nicht, da gabs bei mir nen fullscreen-quad der über den rgb farbraum interpoliert hat 🤡

    emm, du meinst, du zeichnest dauernt fullscreen quads zum benchmarken?
    (ich denke ich missverstehe)

    Meine Grafikkarte ist abgeschmiert, danach hab ich das Testen sein lassen.

    windows? hat es mehr als 2s gedauert? windows watch dog?

    wenn du wirklich fullscreen quads gezeichnet haben solltest, wundert es mich wenn du ueberhaupt einen unterschied wahrgenommen hast.



  • raps schrieb:

    TravisG schrieb:

    rapso schrieb:

    wie zeichnest du mit uniform buffern 10k instances mit je 100 polys?

    10k gar nicht, da gabs bei mir nen fullscreen-quad der über den rgb farbraum interpoliert hat 🤡

    emm, du meinst, du zeichnest dauernt fullscreen quads zum benchmarken?
    (ich denke ich missverstehe)

    Meine Grafikkarte ist abgeschmiert, danach hab ich das Testen sein lassen.

    windows? hat es mehr als 2s gedauert? windows watch dog?

    wenn du wirklich fullscreen quads gezeichnet haben solltest, wundert es mich wenn du ueberhaupt einen unterschied wahrgenommen hast.

    nene, der fullscreen quad war ein witz. Wenn meine Grafikkarte abschmiert "zeichnet sie nen fullscreen quad der über den rgb farbraum interpoliert". Also Monitor mit bunten Farben 😃



  • axo 🤡

    falls du dich wunderst wieso es beides gibt, das langsammerere war zuerst da und ein reines software feature wegen der langsammkeit von directx 😉

    bevor es das gab, haben wir einfach den vertexbuffer x-mal groesser gemacht, in einen channel vom vertex (z.b. alpha vom vertex color) den index zur matrize hinterlegt und damit instanzing 'simuliert'

    davor gab es dieses "matrix-palette-skinning" auch schon, aber eher ein rendering feature als ein performance feature (-> war langsammer als mehrere drawcalls).


Anmelden zum Antworten