Moin, aalso ich bin noch beim Shaderoptimieren. Ich denke wenn ich alles richtig verstanden habe wird der Fragmentshader für jeden "Pixel" und der Vertex-Shader für jeden Vertex. D.h. das der Fragmentshader um ein vielfaches öfters durchlaufen wird als der Vertex. Darum sollte man ja so viel wie möglich schon im Vertex-Shader rechnen.. Bis dahin korrekt?
Bei mir ist es nun so das ich mit meinem Projektionsshader für mehrere Projektoren ein wenig probleme bekomme meine berechneten texturkoordinaten an den fragmentshader zu bekommen.. Aktuell hab ich das alles so begrenzt das ich max. 7 Projektoren rendern kann. Das ergibt dann 30 varying floats. Meine Karte sagt mir zwar das ich 60 davon nutzen kann, doch wie siehts bei anderen Grakas aus? Ich hab schon manche Berechnungen in den Fragmentshader übernommenm um auf die geringe anzahl von Varyings zu kommen.. Doch warum ist das so dolle limitiert? Gibts vielleicht irgendeinen anderen Trick die Daten in den FS zu bekommen?
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
Thmfrnk hat geschrieben:
Moin, aalso ich bin noch beim Shaderoptimieren. Ich denke wenn ich alles richtig verstanden habe wird der Fragmentshader für jeden "Pixel" und der Vertex-Shader für jeden Vertex. D.h. das der Fragmentshader um ein vielfaches öfters durchlaufen wird als der Vertex. Darum sollte man ja so viel wie möglich schon im Vertex-Shader rechnen.. Bis dahin korrekt?
Kommt immer drauf an. In der Regel trifft das zu. Bei Grafikchips der DirectX9/OpenGL2-Generation war es noch so, dass Fragment- und Vertexshader wirklich von unterschiedlichen Rechenwerken ausgeführt wurden. D.h. man hatte ein festes Verhältnis zwischen Vertexshader- und Fragmentshaderleistung. Auf solcher Hardware kann es auch leicht dazu kommen, dass der Vertexshader den Fragmentshader ausbremst. Bei neueren Grafikkarten kann der Treiber entscheiden, wie viele Shaderunits er wofür einsetzt - so ist es z.B. auch möglich alle Rechenwerke für universelle Berechnungen zu nutzen. Bei Nvidia gibt es eine interessante Präsentation dazu (auch als Video). Wie gut aktuelle Treiber das bei all den reinspielenden Faktoren entscheiden kann, weiß ich nicht.
Thmfrnk hat geschrieben:
Bei mir ist es nun so das ich mit meinem Projektionsshader für mehrere Projektoren ein wenig probleme bekomme meine berechneten texturkoordinaten an den fragmentshader zu bekommen.. Aktuell hab ich das alles so begrenzt das ich max. 7 Projektoren rendern kann. Das ergibt dann 30 varying floats. Meine Karte sagt mir zwar das ich 60 davon nutzen kann, doch wie siehts bei anderen Grakas aus? Ich hab schon manche Berechnungen in den Fragmentshader übernommenm um auf die geringe anzahl von Varyings zu kommen.. Doch warum ist das so dolle limitiert? Gibts vielleicht irgendeinen anderen Trick die Daten in den FS zu bekommen?
Tricks gibt es fast immer - man muss nur drauf kommen. Laut GLSL-Tutorial muss jede GLSL-fähige Grafikkarte mindestens 32 varying floats unterstützen. Vielleicht postest du mal etwas Code, damit man ein bessere Chance hat, um auf Optimierungsideen zu kommen?
Zuletzt geändert von mrtrain am Mi Aug 31, 2011 20:53, insgesamt 1-mal geändert.
ich bastel den Shader grad noch bissl um, werde ihn dann man hier reinstellen, dann könnt ihr mal drüber gucken was man noch machen kann..
Passt hier vielleicht nicht ganz aber, kurze Frage am Rande: wenn ich in einer Schleife eine Variable deklariere, wird diese im jeden durchlauf erneut reserviert oder einfach überschrieben?
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
Ich glaube, die Compiler von ATI und Nvidia sind da ziemlich gut. Ich meine einmal in einem Paper von Nvidia gelesen zu haben, dass man ruhig das Ergebnis jeder Zeile in einer neuen Variable speichern soll, wenn es einem übersichtlicher erscheint. Der Compiler würde sich schon drum kümmern, dass nicht mehr Register gebraucht werden als nötig. Aber auf der sicheren Seite ist man natürlich, wenn man die Variable außerhalb der Schleife deklariert.
Zuletzt geändert von mrtrain am Mi Aug 31, 2011 20:54, insgesamt 1-mal geändert.
soo hier meine beiden Shader. Funktionieren tun die Super. Sieht hammergeil aus. Doch sobald ich ca 30 Lampen drin hab (in mehreren Pässen) und mal näher an die geometrie gehe, gehen meine beiden CPU Kerne auf 100% und die FPS geht unter 20..
uniform vec4 LampColors[max_lights]; //Lichtfarbe und intensität uniform int GoboIndex[max_lights]; //gibt an welcher Gobo Sampler projeziert werden soll uniform int GlobalLight; //gibt an ob globales Punktlicht verwendet werden soll uniform vec4 LightPos[max_lights]; //Lampenpositionen für evtl. weitere Berechnungen
Jede Instanz braucht ihrere eigenen Varyings. Es gibt zwei Möglichkeiten: 1. Jede Shaderunit hat lokal ihren eigenen Speicher direkt auf dem Chip integriert. Speicher braucht viel Fläche, daher ist der Speicher klein, weil dann eben mehr Shader-Units auf den Chip passen. 2. Die Shaderunits teilen sich einen gemeinsamen Speicher. Hier wird irgendwann der Speicher voll sein und es können nicht mehr alle Shaderunits gleichzeitig arbeiten (=> ab diesem Punkt wird es rapide langsamer.)
=> Warum legst du nicht einfach diese Schleife in den Fragmentshader:
Code:
for (int i=0; i < max_lights; ++i) { projCoord[i] = TexGenMats[i] * posWorld; }
Dann wäre das varying-Problem gelöst. Eine Multiplikation Matrix*Vektor ist jetzt nichts was man nicht auch im Fragmentshader machen könnte. Für die Grafikkarte sind das gerade mal vier Operationen, ist ja ein Vektorprozessor der vec4 am Stück bearbeiten kann. => 4 mal dot-Produkt. Des weiteren brauchst du nur drei der vier Werte die da berechnet werden, also 3 dot-Produkte. Eigentlich sollte eine mat4x3 als Texturmatrix reichen.
Registriert: Di Okt 13, 2009 17:25 Beiträge: 365
Programmiersprache: C++
Also eins vorweg: Ich bin kein Shader Pro und mit Projektion habe ich auch noch nicht viel am Hut gehabt. Also sehe ich bestimmt höchstens die Hälfte der Verbesserungsmöglichkeiten. Und wie ich sehe, hat Coolcat ja auch schon was aus der eben erwähnten Kopfbedeckung gezaubert. Hier meine Verbesserungsvorschläge:
Im Fragmentshader solltest du v.a. die vielen if-Tests vermeiden. Der Fall, dass keine "Hintergrund"textur vorkommt, dürfte doch ziemlich selten sein, oder? Falls nicht, kann man notfalls auch einfach eine weiße 2x2 Textur binden. Auch das if(GlobalLight>0) sehe ich skeptisch. Vielleicht lieber zwei verschiedene Shader (einen mit und einen ohne GlobalLight) nehmen. Das 8-fache if-else in deiner for-Schleife ist meiner Ansicht nach ein hammermäßiger Performanceschlucker. Wäre es nicht möglich, auf Programmebene dafür zu sorgen, dass das erste light immer zu projMap0 gehört? Dann könntest du dir die sogar die for-Schleife sparen.
Übrigens, bist du sicher, dass
Code:
const int max_lights = 7;
richtig ist? Wenn du willst, was ich denke was du willst, muss da 8 hin.
Zuletzt geändert von mrtrain am Mi Aug 31, 2011 20:54, insgesamt 1-mal geändert.
Die große if-Abfrage ist notwendig da man Sampler leider nicht in ein Array packen kann. Man könnte ggf. ein switch benutzen, dass kann der Compiler möglicherweise besser optimieren. Ein "switch(i)" lässt sich nämlich ersetzen durch "goto(StartZeile + 2 * i)", wenn wie hier jeder Fall genau zwei Zeilen braucht. Das ist auch der Grund warum man bei switch ein break nach jedem Fall benötigt: Da wird ein goto gebraucht. Ob der Compiler so was drauf hat weiß ich aber natürlich nicht.
Der Sinn von GoboIndex[i] ist wohl das man für jedes gerenderte Objekt die Texturen einzeln setzen kann ohne die Texturen neu binden zu müssen. Musst du probieren ob das langsamer ist, schneller ist oder ggf. auch gar nichts ausmacht
Als weitere Optimierung könntest du die Textur nur dann abfragen, wenn du sie auch wirklich benötigst, sprich wenn
Code:
if (any(LampColors[i] * lambertTerm * att >= 1.0/255.0)) { ...
(Hinweis: ein LampColors[i] >= 1.0 gibt ein bvec4, also ein bool-vector. Die Funktion "any" gibt true, wenn einer der vier Werte true ist.)
bzw hab ich das /255 weggelassen weil ich nicht weiß wofür?!
Du hast 256 Farben pro Kanal...also 1.0/255.0 ist die dunkelste Farbe die irgendeinen Unterschied macht. Gut genau genommen 0.5/255.0, aber das sieht man eh nich.
hier nun meine bearbeitete Version. Doch im Vergleich zu vorher ist diese Version nur schneller (ca +3-4 fps) wenn ich weit von der Geometrie weg bin. Sowie ich nah dran bin (was häufiger vorkommt) ist der neue Shader ca 4-8 fps schlechter..
uniform vec4 LampColors[max_lights]; //Lichtfarbe und intensität uniform int GoboIndex[max_lights]; //gibt an welcher Gobo Sampler projeziert werden soll uniform int GlobalLight; //gibt an ob globales Punktlicht verwendet werden soll uniform vec4 LightPos[max_lights]; //Lampenpositionen für evtl. weitere Berechnungen uniform mat4 TexGenMats[max_lights]; //Texturprojektionsmatrix
Also du sagst du hast maximal 32 floats. Davon gehen 12 floats hierfür drauf:
Code:
varying vec4 posWorld; // <--- hier reicht ein vec3! varying vec3 normal; varying vec4 posEye; // <--- hier reicht ein vec3! varying vec3 globalLightVec;
Damit hast du noch 20 floats übrig, das reicht für die ersten 6 Texturprojektionen, wenn das jeweils ein vec3 ist. Die restlichen Projektionen machst du dann eben im Fragmentshader.
du sprichst von projectionen, ich kann doch nur die Texturmatrix berechnung im Vertexshader machen (so wie ichs vorher hatte..)? Ich hab eben mal ein paar Tests gemacht, also ob ich nun 30 Lampen mit einem Shaderdurchgang rendere oder 5x 6 Lampen Rendere. Das ändert kaum was. Was in meinem Code sind denn die größten Bremsen? Die ifs? Später soll auch noch eine Shattenberechnung mit rein, also brauch dann auch noch platz für die Tiefentexturen der einzelnen Lampen. Also quasi 3x Projektionstextur und 3x Tiefentextur.. Damit sollte ich dann wohl immer 3 Lampen mit einemmal Rendern können..
Mitglieder in diesem Forum: 0 Mitglieder und 19 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.