if(..) im Shaderprogramm

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

if(..) im Shaderprogramm

Beitrag von dronus »

Hi,

wann führt ein if im Pixel-Shaderprogramm dazu dass die nicht erfüllte Alternative wirklich nicht berechnet werden muss?

Hängt das von der Benutztung von Konstanten, Interpolatoren oder Texturen oder weiteren speziellen Eigenschaften in der Bedingung ab?

Ist ein Shader machbar, der vier ganz verschiedene Materialien hat und diese abhängig von einer Textur auswählt?

Dank & alles Gute
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Aramis »

Es hängt im wesentlichen vom Shading-Modell ab. Mit dem Shader Model 3.0 sind Branches ziemlich billig ... ich hab da was von 2 Taktzyklen Overhead auf Nvidia Hardware im Kopf. Nicht erfüllte Alternativen werden auf SM3.0-Hardware auch nicht berechnet. Statische branches - also solche, die für einen ganzen Drawcall identisch sind - werden sowieso (afaik vom Treiber) wegoptimiert.

Einziger Nachteil von Branches ist, dass du keine Gradienten benutzen kannst (ddx, ddy). Logischerweise, denn die sind darauf angewiesen dass ein Pixelblock auf der GPU synchron verarbeitet wird. Wenn du also darauf angewiesen bist, musst du solche Instruktionen aus allen Branches rausziehen, selbst wenn du die Information nur in 1/4 aller Fälle brauchst.
st ein Shader machbar, der vier ganz verschiedene Materialien hat und diese abhängig von einer Textur auswählt?
Ja - wird aber recht kostspielig. Vielleicht kannst du die 'ganz verschiedenen Materialien' ja doch in einem Codepfad vereinen.
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Jörg »

Und es haengt vom Shader-Code ab. Wenn Du wirklich sicher gehen willst, dass dynamische Verzweigungen verwendet werden, solltest Du den Assembler-Output ueberpruefen. D3DXSHADER_PREFER_FLOW_CONTROL bzw. /Gfp koennen hilfreich sein.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Krishty »

http://igetyourfail.blogspot.com/2009/1 ... logic.html :)

Wenn es wirklich um sowas wie mehrere Materialien in einem Shader geht („Über-Shader“), würde ich wie Aramis dazu tendieren, das in einem einzelnen Code-Pfad unterzubringen (vllt reichen Arrays + Materialindex?) … oder vllt D3D11s Dynamic Linkage anschauen …

… wäre schon nett zu wissen, von welchem Shader-Model und welcher API wir hier überhaupt sprechen.

Was Aramis mit ddx und ddy angemerkt hat, hat übrigens die nicht unerhebliche Auswirkung, dass die (> bilineare) Texturfilterung möglicherweise nicht mehr zur Verfügung steht. Als jemand, der Flimmern als die größte Pest heutiger Grafik-Engines ansieht (weil heute mein bigotter Dienstag ist: Ich benutze trotzdem ATI-Hardware), empfehle ich, das zu vermeiden.

Noch was zu den Kosten: Ich habe noch im Hinterkopf, dass Nvidia-Hardware zwar gut im Branchen ist, ATI-Hardware aber katastrophal (superparallel mit 96 Shader-Einheiten vs. superskalar mit 800 Shader-Einheiten). Ist aber ohne Gewähr.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Schrompf »

Was die Performance angeht, muss man wirklich vorsichtig sein. Es hängt sehr davon ab, wie die Grafikkarte Blöcke bildet. Dafür gab es auch einen richtigen Fachbegriff, aber der ist mir gerade entfallen. Es bedeutet primär, dass die Shader-Ausführungen für einen Pixelblock *beide* Pfade eines if-else nehmen, sobald auch nur ein Pixel im Block einem abweichenden Ausführungspfad folgt. Bei früheren SM3.0-Grafikkarten waren die Blöcke noch recht groß... ich habe da was von 16x16 Pixeln im Ohr. Wenn innerhalb dieser 16x16 Pixel auch nur ein Pixel den else-Pfad nimmt und alle anderen den if-Pfad, dann werden beide Zweige ausgeführt.

Es hängt also sehr davon ab, wie räumlich verschieden die Ausführungspfade benutzt werden. Wenn Du grob die linke Hälfte eines bildschirmfüllenden Objekts im if und die andere Hälfte im else abhandelst, kostet das if nur ein paar wenige Taktzyklen. Wenn selbst benachbarte Pixel sehr oft unterschiedliche Pfade nehmen, bezahlst Du quasi beide Pfade plus den Overhead für's Branching.

Nebenbemerkung: ich habe gelegentlich einige Experimente zu dem Thema gemacht. Ich habe bisher noch nicht einen einzigen Fall gefunden, wo ein Shader durch Dynamic Branching schneller wurde. Aktuelles Beispiel ist NVidias Percentage Closer Soft Shadowmapping auf ner ATI Radeon 4870 - die Framerate *steigt*, wenn ich das Early-Out-if entferne, das angeblich 16 Texturzugriffe einsparen soll. Meine Erfahrungen sind jetzt nicht repräsentativ oder sowas, aber für mich durchaus bemerkenswert.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Krishty »

Schrompf hat geschrieben:Bei früheren SM3.0-Grafikkarten waren die Blöcke noch recht groß... ich habe da was von 16x16 Pixeln im Ohr.
Hier ist von 2 × 2 und 4 × 4 Pixeln die Rede (was aber schon „schlimm“ genug ist).
Schrompf hat geschrieben:Ich habe bisher noch nicht einen einzigen Fall gefunden, wo ein Shader durch Dynamic Branching schneller wurde.
Ich genau eins – mein Atmospheric Scattering (auf ATI-Hardware). Da sprechen wir aber von hunderten Texturzugriffen, die gespart werden.

So hoch der Grenzwert zur Zeit aber auch liegen mag, er dürfte in Zukunft sinken – irgendwo hatte ATI Direct3D 11 mal als die „Ära des Dynamic Branching“ (oder so) bezeichnet. Vor allem wegen der Performance der Compute-Shader soll Dynamic Branching also in Zukunft erheblich performanter werden.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Jörg »

Und zu guter letzt: Was das Treiber-Backend aus dem Code macht, weiss man eh nicht so genau. Zumindest NVidia-Karten bieten ja noch die Zwischenstufe "Conditional Execution" (siehe CUDA ptx Dokumentation), aehnlich den ARM-Prozessoren.

Folglich gilt auch hier: Einfach Implementieren und Testen ;)
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

Re: if(..) im Shaderprogramm

Beitrag von dronus »

Na, ich hab erstmal nicht nach bestimmten Shader-Versionen gefragt weil ich gerne Antworten wollte die auf mehr als einem Rechner stimmen :-)

Nungut, dann geht probieren über studieren.


Ich hab jetzt grad über Deferred Shading gelesen, und mir ist nicht ganz klar: Wird dazu die gesamte Szene am Ende am nochmal gerendert, um in jedem Pixel mit dem richtigen Material zu shaden? Da scheint mir könnte es doch Sinn machen für jeden Pixel eine Materialnummer zu schreiben und später im Shader mit einem rieeeesigen if(..) else(..) die verschiedenen Materialien auszuwählen, wärend man einfach den ganzen Screen mit einem Quad rendert?
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: if(..) im Shaderprogramm

Beitrag von Aramis »

Da scheint mir könnte es doch Sinn machen für jeden Pixel eine Materialnummer zu schreiben
Genau so in etwa läuft es auch. Du schreibst im eigentlichen (und, von einem ZPrepass abgesehen, normalerweise einzigen) Renderpass die Vertexpositionen bzw. Normalen sowie alle anderen für's Shading erforderlichen Informationen in mehrere RenderTargets raus. Im finalen Pass zeichnest du ein bildschirmfüllendes Rechteck und führst dein Deferred Shading durch.

Auf das mit dem if(material_index == 0) ... else if .. würde ich aber auch da verzichten. Lieber Materialinformationen in Texturen kodieren und diese mit dem Materialindex addressieren. Stalker macht es so (9.4.3 Materials and Surface-Light Interaction).
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

Re: if(..) im Shaderprogramm

Beitrag von dronus »

Aramis hat geschrieben:Lieber Materialinformationen in Texturen kodieren und diese mit dem Materialindex addressieren
Klingt cool.

Ist es dann ok einige Eigenschaften (vielleicht diffuse Farbe) mit in Buffer zu rendern, damit man dort die Freiheit hat jede Farbe zu vergeben? Oder muss man den Buffer unbedingt so klein wie möglich halten..
Stefan Zerbst
Moderator
Beiträge: 189
Registriert: 25.02.2009, 19:54

Re: if(..) im Shaderprogramm

Beitrag von Stefan Zerbst »

Hi,

meinst du mit "Buffer" ob du bereits Farbe in dem RenderPass mit in die Render Targets schreiben kannst / darfst? Klar geht das, du kannst dir ein eigenes Layout für den sogenannten G-(ometrie)-Buffer definieren so wie es dir passt. Das ist ja nur eine Ansammlung verschiedener RenderTargets deren RGBA Werte du "vergewaltigst". Die ambiente Farbe könnte man zum Beispiel schon in diesem Pass mitschreiben.

Ciao,
Stefan
dronus
Establishment
Beiträge: 114
Registriert: 11.01.2010, 01:53

Re: if(..) im Shaderprogramm

Beitrag von dronus »

Ok, also wenn man sehr viele verschiedene Materialien hat sollte man eher Buffer für Objekt-Farbe, Specularstärke und so weiter machen. Dann muss der Shader keine Materialeigenschaften mehr in Texturen nachschlagen. Dafür müssen aber viel mehr Daten geschrieben / gelesen werden, ist das akzeptabel?

Texturen muss man sowieso im 1. Pass rendern, sonst müsste ja der zweite Pass sämtliche Texturen zur Verfügung haben die irgendwo im Bild vorkommen..
Stefan Zerbst
Moderator
Beiträge: 189
Registriert: 25.02.2009, 19:54

Re: if(..) im Shaderprogramm

Beitrag von Stefan Zerbst »

Hi,

vielleicht schaust du dir einfach mal ein deferred shading sample an? Der G-Buffer besteht nur aus n RenderTargets und diese werden dann im finalen Pass (das eigentliche deferred shading) als Texturen gesetzt um die Informationen für das shading im Pixel Shader auszulesen. Es ist also egal ob du ganze Materialien in Texturen speicherst oder die einzelnen MaterialAttribute im G-Buffer. Das kommt in etwa auf dasselbe raus.

Ciao,
Stefan
Antworten