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

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

1

02.04.2010, 15:02

[HLSL] if - Performance

Hi Leute!
Es wird ja immer geraten keine ifs oder Schleifen zu benutzen, bei denen von vorn herein nicht feststeht, ob bzw. wie oft sie durchlaufen werden.
Im Prinzip ist das ja logisch. Dann kann ausgerollt oder einfach die Abfrage weggelassen werden. Klar macht das mehr Performance aus.

Aber was ist, wenn durch so eine Bedingung Rechenarbeit gespart werden kann?
Zum Beispiel bei Beleuchtung: Wenn die (dynamische) Lichtquelle aus ist, wird der Schritt weggelassen.

Was ist besser: Doch ein paar ifs, oder lieber rechnen lassen?

Gotbread

Alter Hase

Beiträge: 421

Beruf: Student (Etechnik) + Hiwi

  • Private Nachricht senden

2

02.04.2010, 15:18

Kann man so nicht sagen, einige profile, die kein echtes if haben, rechnen beide seiten aus, und wählen dann auf mathematische weise das ergebnis
(z.b. val = condition * var1 + (1 - condition * var2);)

wenn die bedingung nur von variablen abhängt, die das programm setzt, sollte es immernoch sehr schnell sein.
außerdem werden pixel immer in gruppen berechnet, also lohnt sich die if abfrage nur, wenn z.b. ein 32*32 pixel bereich den selben controlpfad nimmt.

das einzige was sich lohnen würde, zu überspringen sind textur-anweisungen, mathematische berechnungen sind meist eh schnell genug.
Mfg Goti
www.gotbread.bplaced.net
viele tolle spiele kostenlos, viele hardware-basteleien :)

"Es ist nicht undicht, es läuft über" - Homer Simpson

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

3

02.04.2010, 15:40

Gut, danke!

Ich lass dann einfach etwas mehr berechnen als notwendig.

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

4

02.04.2010, 17:09

Bei if in Shadern muss grundsätzlich zwischen Static Branching und Dynamic Branching unterschieden werden.
Ersteres hast du immer dann, wenn die Bedingung von einem zur Shaderlaufzeit konstanten Wert abhängt - das ist nicht annähernd so schlimm und wird dann tatsächlich gar nicht per Vertex oder per Fragment durchgeführt; man kann damit auch recht schön einfache Permutationen eines Shaders herbeiführen ohne die Performance groß zu beeinflussen.
Hängt die Bedingung allerdings von irgendeinen per Vertex/Fragment berechneten Wert ab, so spricht man von Dynamic Branching. Das ist erst ab Shader 3.0 verfügbar und sollte mit höchster Vorsicht genossen werden. In manchen Fällen kann man damit tatsächlich die Performance verbessern. Zum Beispiel habe ich für die Soft Shadows in Xrodon eine Dynamic Branch eingeführt, damit möglichst nur in Schattenübergangsbereichen die Shadowmap 36 mal gesampelt - an anderen Stellen wird sie "nur" 8x gesampelt (die ersten 8 Samples dienen als Testwert).
Das Problem ist allerdings, dass sich dieser Performancezuwachs auf den ersten Grakas die zum Dynamic Branching fähig waren sich alles andere als gleich verhält - manchmal läufts damit besser, manchmal sogar schlechter.

Sehr schön zusammengefasst wie Dynamic Branching intern funktioniert und warum es nicht immer die erwarteten Ergebnisse liefert findest du hier ab Seite 3.
Außerdem wird hier noch aufgezeigt welche Probleme es beim Samplen von Texturen innerhalb einer Branch geben kann (war für meinen Shadowmapping-Fall sehr wichtig)

Bei den Schleifen gilt: Die Schleifen mit konstanter Iteration werden vom Shadercompiler aufgedröselt in Code; dynamische Anzahl von Iterationen ist erst im Shader 3.0 möglich.

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

5

09.04.2010, 19:25

Mal ein praktisches Beispiel: SpotLight
Wenn das Pixel außerhalb des Lichtkegels liegt, könnte man sich die Berechnung sparen.
Man brancht dynamisch für jeden Vertex/Pixel, ob der im beleuchteten Bereich liegt. Wenn ja, wird er beleuchtet.

Hier wird das so gemacht: http://www.ozone3d.net/tutorials/glsl_li…g_p3.php#part_3
und in Davids Buch wird auch erwähnt, dass dadurch die Performance gesteigert werden kann. Allerdings kenne ich den Source der FFP nicht.
Was ist jetzt besser?

Ach ja: Da ich SM 4_0 benutze, gehe ich mal von neueren, leistungskräftigeren Grakas aus.

Beiträge: 774

Beruf: Student

  • Private Nachricht senden

6

09.04.2010, 19:44

Bei kleinen Spotlights kann es sich auf modernen Grafikkarten wird sichs wohl lohnen.. naja der Autor schreibt ja ganz unten was darüber.. kurz bevor ich das gesehn hab wollte ich genau das einwerfen: 2 Branches machen sicher keinen Sinn ^^
Da sieht man auch an sich schön was das ausmacht:

Zitat

Here is an optimized version of the previous pixel shader suggested by one of the forum members in this topic This version removes one dynamic branching and seriously improves the code speed (there are about 100 FPS of difference between both pixel shaders!!!):
Ich denke die verbleibende Branch dürfte wohl meistens ihren Performanceverlust ungefähr aufwiegen.. das dürfte aber stark variieren je nach Grafikkarte und Szene. Es wäre sicher einen Versuch wert die auch mal wegzulassen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

7

09.04.2010, 19:54

Pauschal kann man da nicht wirklich eine Aussage treffen. Es kann durchaus sein dass das if einen Performancevorteil bringt (vor allem auf D3D10+ Hardware), es kann aber auch sein dass das extreme Gegenteil der Fall ist. Am besten probierst dus für deinen konkreten Fall einfach aus...

BlazeX

Alter Hase

  • »BlazeX« ist der Autor dieses Themas

Beiträge: 478

Wohnort: DD

Beruf: Maschinenbau-Student

  • Private Nachricht senden

8

09.04.2010, 21:31

Ich habs mal ausprobiert. Mit DB 1077 FPS, ohne 1078 FPS. Abzüglich Messtoleranz => Pustekuchen.

Hier ist mal der Shading-Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//////////////////////////////////////////////////////////////////
//Spotlicht berechnen
float4 SpotLightDiffuse(float3 vLightPosition, float3 vSpotDir,
                        float4 LightColor, float fAttenuation0, float fAttenuation1,
                        float fCosHalfPhi, float fCosHalfTheta, float fFalloff,
                        float3 vPosition, float3 vNormal)
{
    float3 vNegLightDir= vLightPosition - vPosition;
    float3 vNormalizedNegLightDir= normalize(vNegLightDir);

    float fIntensity= saturate(dot(vNormal, vNormalizedNegLightDir));
    float fSpotStencil= pow(
        (saturate(-dot(vSpotDir, vNormalizedNegLightDir) - fCosHalfPhi))
        / (fCosHalfTheta - fCosHalfPhi),
        fFalloff);
    float fAttenuation= saturate(1 / (fAttenuation0 + fAttenuation1 * length(vNegLightDir)));

    return(fSpotStencil * fIntensity * fAttenuation * LightColor);
}

float4 SpotLightSpecular(float3 vLightPosition, float3 vSpotDir,
                         float4 LightColor, float fAttenuation0, float fAttenuation1,
                         float fCosHalfPhi, float fCosHalfTheta, float fFalloff,
                         float3 vPosition, float3 vNormal, float fPower,
                         float3 vViewDir)
{
    float3 vNegLightDir= vLightPosition - vPosition;
    float3 vNormalizedNegLightDir= normalize(vNegLightDir);

    float fIntensity= pow(saturate( dot(reflect(vNormalizedNegLightDir, vNormal),
                                        vViewDir) ), fPower);
    float fSpotStencil= pow(
        (saturate(-dot(vSpotDir, vNormalizedNegLightDir) - fCosHalfPhi))
        / (fCosHalfTheta - fCosHalfPhi),
        fFalloff);
    float fAttenuation= saturate(1 / (fAttenuation0 + fAttenuation1 * length(vNegLightDir)));

    return(fSpotStencil * fIntensity * fAttenuation * LightColor);
}


Und da ist mir aufgefallen, dass bei Backface-Dreiecken in der Spekular-Berechnung positive Ergbnisse rauskommen :huh: Die werden zwar eh gecullt, aber ich kann das irgendwie nicht rechnerisch nachvollziehen.

Werbeanzeige