Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

1

27.09.2013, 18:16

[GLSL] Buffer wie eine Liste füllen

Hey zusammen,

vielleicht eine etwas ungewöhnliche Frage.
Ich versuche derzeit ausgewählte Informationen aus meinen Shadern zu bekommen (gerna auch mit GLSL 4.4). Angenommen ich habe 512x512 Shader Aufrufe welche fröhlich nen Integer berechnen. Jetzt will ich davon beispielsweise 100 Integer (nach irgendeinem Auswahlkriterium) in einen Shader Storage Buffer schreiben (Ähnliche Funktionalität wie eine Liste mit .add(x))
Da kommen auf mich gleich mehrere Probleme zu:

1) Synchronisation, dass sich die Shader nicht gegenseitig irgendwas überschreiben. So wie ich die atomaren Funktionen wie atomicAdd verstanden habe bringen die mir hier nicht viel.
2) Den Index des Buffers berechnen. Dies wäre vmtl leicht über einen atomicCounter zu lösen.

Vielleicht ein kleines Beispiel damit ihr wisst was ich meine:

Gegeben seien 4 Shader Aufrufe S_i und der Buffer B

S_2 berechnet integer 4 -> nicht abspeichern
S_1 berechnet integer 5 -> abspeichern: B{5}
S_3 berechnet integer 8 -> abspeichern: B{5,8}
S_4 berechnet integer 3 -> nicht abspeichern

Ist eine solche Funktionalität in OpenGL / GLSL überhaupt möglich? Wenn ja habt ihr eine Idee wie man das angehen könnte?

Grüße

EDIT:
Eine Alternative wäre es den Buffer wie gewohnt zu befüllen und dann nach einem Kriterium in einem Shader zu sortieren.
Allerdings ist Sortieren auf GPUs recht langsam und aufwändig. Wenn ich von einem Buffer mit 512² Elementen nur die 3 kleinsten Einträge möchte ist das Sortieren ein wenig overkill :wacko:

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

2

27.09.2013, 18:50

Zitat

Wenn ich von einem Buffer mit 512² Elementen nur die 3 kleinsten Einträge möchte ist das Sortieren ein wenig overkill


Das könntest du schon mal lösen wenn du nicht sortierst sondern direkt guckst ob der neue Wert kleiner ist als der vorherige. Wenn ja wird der neue gespeichert.
Wie und wieso deine Shader asynchron laufen verstehe ich noch nicht.

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

3

27.09.2013, 22:45

Das könntest du schon mal lösen wenn du nicht sortierst sondern direkt guckst ob der neue Wert kleiner ist als der vorherige. Wenn ja wird der neue gespeichert.
Wie und wieso deine Shader asynchron laufen verstehe ich noch nicht.
Da liegt ja das Problem. So einfach gucken kann ich das im Shader nicht da diese ja parallel laufen und ich bekomm dann Inkonsistenzen

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

4

28.09.2013, 14:10

Müssen die Daten denn unbedingt aus den Shadern kommen? Lässt sich das nicht vorher auf der CPU berechnen und dann in einem Buffer übergeben?
Ich verstehe nicht ganz was du vorhast, erklär das noch mal genauer bitte.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

28.09.2013, 15:10

2) Den Index des Buffers berechnen. Dies wäre vmtl leicht über einen atomicCounter zu lösen.

Das ist eine gute Lösung und vermutlich auch, was ich vorschlagen würde (wobei ich natürlich nicht weiß, was genau du eigentlich erreichen willst).

Weitere, noch nicht genannte Alternativen wären z.B. Transform Feedback oder das Ganze in mehreren Passes zu machen, im ersten Pass geben deine Shader nur 0 oder 1 aus, je nachdem ob sie einen Wert produzieren werden, oder nicht, über eine parallel prefix sum kannst du dann für jedes Element einen Zielindex bestimmen und in einem weiteren Pass dann die eigentlichen Werte ausgeben. Letzeres ist nicht nur kompliziert, sondern auch genau so ineffizient, wie es klingt. Dennoch war es viele Jahre lang so ziemlich das Einzige, was man machen konnte...

Müssen die Daten denn unbedingt aus den Shadern kommen? Lässt sich das nicht vorher auf der CPU berechnen und dann in einem Buffer übergeben?

Es müssen immerhin 262144 Werte berechnet werden. Wenn diese Werte allesamt parallel berechnet werden können, wird die GPU das nicht nur wesentlich schneller erledigen als die CPU, es entfällt auch der Datentransfer über den PCI Bus...

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »dot« (28.09.2013, 15:20)


Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

6

30.09.2013, 14:53

Mal ein wenig Pseudocode

C-/C++-Quelltext

1
2
3
4
5
6
7
i = computeValue(); // Berechne den Value der zu speichern ist
if(i < treshold)
  return;
index = atomicCounter++; // liefert den Wert vor der Inkrementierung zurück!

// Problematische Stelle
Buffer[index] = i;


Ist die deklarierte problematische Stelle wirklich problematisch? Die Inkrementierung des atomicCounters ist ja atomic, demnach müsste jede Shaderinstanz einen eigenen unique index haben oder?
Dies sollte mein Problem doch bereits lösen falls ich nicht irre?
Es müssen immerhin 262144 Werte berechnet werden. Wenn diese Werte allesamt parallel berechnet werden können, wird die GPU das nicht nur wesentlich schneller erledigen als die CPU, es entfällt auch der Datentransfer über den PCI Bus..
Ja alle Werte können absolut unabhängig voneinander berechnet werden, deswegen ist die GPU hier für mich Pflicht.

Danke und Grüße

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

30.09.2013, 15:00

Ich bin mir ehrlich gesagt nicht sicher, ob der ++ operator in GLSL gleichwertig ist mit einem atomicCounterIncrement(); in der GLSL Spezifikation kann ich auf die Schnelle jedenfalls nichts finden, das dies implizieren würde. Ich würd besser ein explizites atomicCounterIncrement() machen...

Sc4v

Alter Hase

  • »Sc4v« ist der Autor dieses Themas

Beiträge: 376

Beruf: Student

  • Private Nachricht senden

8

30.09.2013, 15:52

Ich bin mir ehrlich gesagt nicht sicher, ob der ++ operator in GLSL gleichwertig ist mit einem atomicCounterIncrement(); in der GLSL Spezifikation kann ich auf die Schnelle jedenfalls nichts finden, das dies implizieren würde. Ich würd besser ein explizites atomicCounterIncrement() machen...
Ja auf jedenfall, das hatte ich auch gemeint! Sorry für die Verwirrung aber ich hatte keine Lust nach dem Befehl zu suchen und hab deswegen auch Pseudocode gesagt ^^

Werbeanzeige