Pixelshader zu langsam
-
Hoi, ich bin's wieder mit meinem Pixelshader.

Bei nem Kumpel, der eine etwas betagte Grafikkarte besitzt, ist mein Terrain der große Performance-Bottleneck. Ich mach aber nichts wahnsinnig böses damit, es ist ein Quad, das texturiert wird. Das ganze ist eine Singlepass-Aktion. Die Performance nimmt bei geringerer Auflösung ganz erheblich zu (und ohne das Terrain zu rendern natürlich auch
). Also kommt IMHO fast nur noch der Pixelshader in Frage. Wie kann ich den noch weiter optimieren? Hier mal der Code:// Structures struct vertex { float4 pos : POSITION; float2 tex0 : TEXCOORD0; float2 tex1 : TEXCOORD1; float2 tex2 : TEXCOORD2; float2 alpha : TEXCOORD3; }; // Shaders vertex VS_Transform(vertex IN) { vertex OUT; OUT.pos = mul(IN.pos, worldViewProj); OUT.tex0 = IN.tex0; OUT.tex1 = IN.tex1; OUT.tex2 = IN.tex2; OUT.alpha = IN.alpha; return OUT; } float4 PS_Texture(vertex IN) : COLOR { float2 alphaValues = tex2D(AlphaSampler, IN.alpha).gb; // first layer float4 result = tex2D(DiffuseSampler0, IN.tex0); // second layer float4 temp = tex2D(DiffuseSampler1, IN.tex1); result = result * (1 - alphaValues.r) + temp * alphaValues.r; // third layer temp = tex2D(DiffuseSampler2, IN.tex2); result = result * (1 - alphaValues.g) + temp * alphaValues.g; return result; }Der Vertexshader nur der Vollständigkeit halber, es gibt wie gesagt nur 4 Vertices die abgearbeitet werden müssen.
Der Pixelshader verwendet 3 Terrain-Texturen und eine Blendmap. Der unterste Layer ist immer vollkommen opak, für die beiden anderen wird ein Alpha-Wert zum Blenden aus der Blendmap gelesen.
Das ist der Pass:
pass P0 { AlphaTestEnable = false; ZEnable = false; Lighting = false; CullMode = None; VertexShader = compile vs_1_1 VS_Transform(); PixelShader = compile ps_1_1 PS_Texture(); }Und das sagt der FX Composer dazu:
**************************************** Target: GeForceFX 5200 Ultra (NV34) :: Unified Compiler: v77.72 Cycles: 3 :: # R Registers: 2 Pixel throughput (assuming 1 cycle texture lookup) 266.67 MP/s ========================================= Shader performance using all FP16 Cycles: 2 :: # R Registers: 2 Pixel throughput (assuming 1 cycle texture lookup) 400.00 MP/s ========================================= Shader performance using all FP32 Cycles: 4 :: # R Registers: 4 Pixel throughput (assuming 1 cycle texture lookup) 200.00 MP/s **************************************** PS Instructions: 10 ps_1_1 def c0, 0, 1, 0, 0 def c1, 0, 0, 1, 0 tex t0 tex t1 tex t2 tex t3 dp3 r0, c0, t3 mul r0, r0, t1 dp3 r1, c0, 1-t3 mad r0, t0, r1, r0 dp3 r1, c1, t3 lrp r0, r1, t2, r0Sind 10 Instruktionen nicht eh schon ziemlich geil für das, was der Pixelshader alles macht? Hat jemand noch eine Idee, wie ich das verbessern kann?
-
Nur um das mal zu verdeutlichen: Mein Kumpel hat ohne Terrain ~ 130fps, mit Terrain hat er zwischen 13 und 16.
1280x1024: 13-16
1024x768: 25
800x600: 32-50Ich bin mir also schon ziemlich sicher, dass ich genau hier verbessern muss.

-
was für ne graka hat denn dein kumpel?
Und tust du dein Terrain vorher cullen oder brute force rendern?
-
Ne alte Radeon, ich kanns heute Abend mal in Erfahrung bringen. Zum Cullen gibt es IMHO nichts, da es nur ein Quad ist. Nur ein kleiner Teil vom Quad ist sichtbar aber was nicht sichtbar ist, sollte ja geclipt werden, ich kann mir nicht vorstellen, dass der Rasterizer für nicht sichtbare Pixel den Shader ausführt.
Kann bei alten Karten die Trilineare Texturefilterung zu krass sein?
-
Ich sag mal noch dazu, dass das Terrain bei mir überhaupt nicht reinhaut von der Performance her. Es scheint also speziell ein Problem mit älterer Hardware zu sein.
-
Um herauszufinden, ob es wirklich an der Komplexität des Shaders liegt, ersetze ihn doch mal durch einen "Dummy-Shader", der einfach nur eine konstante Farbe zurückliefert.
-
Ja, es liegt daran. Mit nem einfach weißen Terrain sind es 100fps (normal: 13). Mit dem normalen Shader aber nur Point-Filter sind es 36. Ich könnte aber eh höchstens auf den trilinearen filter verzichten, aber den bilinearen brauche ich. Das war also nur als Test und keine ernsthafte Möglichkeit, da wäre die Verbesserung also nochmal viel kleiner.
Scheinbar macht also der von mir gezeigte Pixelshader-Code wirklich den Flaschenhals aus. Habt ihr nun Tipps, wie ich ihn optimieren könnte? Ist ja praktisch mehr oder weniger mein erster eigener Shader.

-
Vielleicht ist die Anzahl der texture-lookups das Problem. Vielleicht kannste Dein Terrain feiner kacheln und das alpha per vertex übergeben? Das würde immerhin ein lookup sparen.
-
Kann es nicht sein, dass die alte Grafikkarte Pixelshader einfach nicht so schnell ausführen kann?
-
Jester schrieb:
Vielleicht ist die Anzahl der texture-lookups das Problem. Vielleicht kannste Dein Terrain feiner kacheln und das alpha per vertex übergeben? Das würde immerhin ein lookup sparen.
Dann müsste ich das Vertex-Alpha linear interpolieren, ist halt die Frage ob das die Sache besser macht. Keine genaue Ahnung wie schlimm die Lookups sind, aber zumindest ist der Unterschied zwischen trilinear und tripoint recht gering obwohl point schon deutlich billiger sein müsste, also verdächtige ich zur Zeit mehr die Rechnung. Aber da sieht anscheinend keiner was, tja schade.

Mit dem Vertex-Alpha kommt natürlich noch hinzu, dass ich dann nach Terrain-Art unterschiedlich fein kacheln muss (sonst hätte ich ne Million vertices), dabei 3 Ebenen berücksichtigen muss und dann später noch die Geometrie des Terrains. Und irgendwie muss dann am Ende was mit 1024x1024 Vertices rauskommen, weil es an jeder Stelle wenigstens einen Grund gibt, fein zu kacheln. Ich glaub, das ist nicht geil.
xindon schrieb:
Kann es nicht sein, dass die alte Grafikkarte Pixelshader einfach nicht so schnell ausführen kann?
Das ist natürlich so, aber mit irgendwas muss ich halt die Fläche füllen.
Durch den Pixelshader mach ich das wenigstens schon mal in einem Pass.
-
Ersetz doch einfach mal den alpha-Lookup durch nen fixen Wert und schau ob's was bringt ein lookup einzusparen. Ich könnte mir schon vorstellen, dass man die Unterteilung effizient machen kann. Aber ich stimme zu, dass das deutlich aufwendiger ist, als einfach im Pixelshader ein lookup zu machen.
-
Ok, test ich Morgen mal (ich würd's ja gleich testen, aber ich nenne nicht eine beschissene Grafikkarte mein Eigen).
Ich hoffe ja ehrlich gesagt, dass es das nicht ist, weil der alpha-lookup ist der einzige von 3, die ich mit viel Aufwand einsparen könnte.
-
Sieh es ein Optimizer, du bist einfach nen Shaderb00n

Irgendwie kann ich mir net vorstellen, dass die paar texture lookups so reinziehen. Ich mein was muss er da schon machen? Je nach Sampler ein paar Samplepoints lesen und dann interpolieren. Bei vielen Beleuchtungsmodellen benutzt man ja sogar Texturen als Optimierung und Multitexturing is ja absoluter Standard. Teste einfach mal die Geschwindigkeit des Codes mit und ohne Texture Lookups.
Hab den Thread nur überflogen aber irgendwo hast du geschrieben, dass du mit nem weißen Terrain 100fps hast. Irgendwie kommt mir dieser Wert schon verdammt niedrig vor. Ich hab mal mit MDX ein Terrain, bestehend aus ca. 130.000 Vertices, per Brute Force gerendert und hatte da ca 800fps.
-
this->that schrieb:
Sieh es ein Optimizer, du bist einfach nen Shaderb00n

Auf jeden Fall, deshalb sind ja Verbesserungsvorschläge ausdrücklich gewünscht.
this->that schrieb:
Hab den Thread nur überflogen aber irgendwo hast du geschrieben, dass du mit nem weißen Terrain 100fps hast. Irgendwie kommt mir dieser Wert schon verdammt niedrig vor. Ich hab mal mit MDX ein Terrain, bestehend aus ca. 130.000 Vertices, per Brute Force gerendert und hatte da ca 800fps.
Vielleicht war es nicht gut, dass du den Thread nur überflogen hast.

Ich habe mit nem korrekten Terrain (also nicht weiß) 650 fps bei 1600x1200. Du siehst also, überhaupt kein grundsätzliches Problem. Es geht hier nur darum, geht es noch besser, dass es für alte DX9-Karten auch noch taugt. Und wo muss ich genau ggf. Abstriche machen für diese Karten.