2016-06-26 3 views
0

Okay, also ich entwickle eine Android-App für ein Spiel, das ich mache (mit LibGDX). Und ich habe einen Fragment Shader und ich bemerkte, dass ich ~ 41 FPS hatte. Ich habe mit dem Code herumgespielt, um zu sehen, wo das Problem lag, und ich habe gesehen, dass die Änderung, wie ich ein Array von ArrayName [i] auf ArrayName [0] anwendete, wieder auf 60 FPS stieg, obwohl die Schleife nur einmal ausgeführt wurde diese spezifische Instanz.
Hier ist der Code:GLSL: Der Zugriff auf ein Array in einem For-Loop behindert die Leistung

#version 300 es 

precision highp float; 

uniform sampler2D u_texture; 

in vec2 vTexCoord0; 

struct BlackHole { 
    vec2 position; 
    float radius; 
    float deformRadius; 
}; 

uniform vec2 screenSize; 
uniform vec3 cameraPos; 
uniform float cameraZoom; 

uniform BlackHole blackHole[4]; 
uniform int count; 

out vec4 fragColor; 

void main() { 
    vec2 pos = vTexCoord0; 

    bool doSample = true; 

    for (int i = 0; i < count; i++) { 
     BlackHole hole = blackHole[i]; // <-------- blackHole is the array, and changing from [i] to [0] 
     vec2 position = (hole.position - cameraPos.xy)/cameraZoom + screenSize*0.5; 
     float radius = hole.radius/cameraZoom; 
     float deformRadius = hole.deformRadius/cameraZoom; 

     vec2 deltaPos = vec2(position.x - gl_FragCoord.x, position.y - gl_FragCoord.y); 
     float dist = length(deltaPos); 

     if (dist <= radius) { 
      fragColor = vec4(0, 0, 0, 1); 
      doSample = false; 
      break; 
     } else if (dist <= radius + 1.0) { 
      fragColor = vec4(1); 
      doSample = false; 
     } else if (dist <= deformRadius) {lensing 
      float distToEdge = deformRadius - dist; 
      pos += distToEdge * normalize(deltaPos)/screenSize; 
     } 
    } 

    if (doSample) 
     fragColor = texture(u_texture, pos); 
} 

In diesem speziellen Fall "count" ist 1.
Ist das nur eine intrinsische Eigenschaft von GLSL? Oder gibt es eine Lösung - der höchste Wert von "count" wäre 4, also könnte ich es erweitern und keine for-Schleife verwenden, aber ich denke, das ist keine sehr gute Lösung.
Also, weiß jemand, warum das passiert und/oder eine Möglichkeit, es zu beheben?

Antwort

3

Siehe GLSL ES 3.0 specification, Seite 140, „12.30 Dynamische Indizierung“:

Für GLSL ES 1,00, Unterstützung von dynamischer Indizierung von Arrays, Vektoren und Matrizen nicht beauftragt wurde, weil sie nicht direkt von einigen Implementierungen unterstützt wurden . Softwarelösungen (über Programmtransformationen) existieren für eine Teilmenge von Fällen, führen jedoch zu einer schlechten Leistung.

Beachten Sie, dass OpenGL ES 3.0 immer noch nicht von allen Geräten unterstützt wird. Um 50% of all Android devices unterstützt es in diesem Moment. Die tatsächliche Implementierung des Treibers/Compilers ist möglicherweise noch nicht so optimiert. Das tatsächliche Ergebnis und die Leistung Ihres Codes variieren daher wahrscheinlich von Gerät zu Gerät.

Versuchen Sie, dynamische Verzweigungen und Schleifen zu vermeiden (es würde nicht einmal für GLSL ES unter 3.0 kompilieren). Wenn Sie wissen, dass Ihre Schleife bei maximal 4-mal ausgeführt wird, dann einen Makro mit diesem Wert zu definieren:

#define COUNT 4 
... 
uniform BlackHole blackHole[COUNT]; 
... 
    for (int i = 0; i < COUNT; i++) { 

Wenn Sie dann nur haben, müssen sie die Schleife 2 oder 3 Mal, während Sie es für 4-mal zusammengestellt, dann fügen Sie einfach Werte in die verbleibenden Elemente ein, so dass es so aussieht, als ob diese Elemente nicht vorhanden wären (z. B. den Radius auf Null setzen). So funktioniert auch die libgdx default shader.

Das gleiche gilt für die Verzweigung in Ihrem Shader. Sie haben ziemlich viele if und else in Ihrem Code. Versuche diese zu entfernen. Ich habe Ihren Code nicht eingehend betrachtet, aber es sieht so aus, als könnten Sie ihn ändern, indem Sie z. a smoothstep statt Verzweigung.

Ein allgemeiner Tipp: Verwenden Sie einen Shader-Editor, der in Echtzeit die Auswirkungen des von Ihnen geschriebenen Codes zeigt. Zum Beispiel die PowerVR shader editor oder die Adreno shader editor. Dies wird dir sehr helfen.

+0

Gute Antwort. Glauben Sie, es würde ausreichen, eine zusätzliche Auswertung in der for-Schleife zu haben, zB 'i Andreas

+0

nein, das wird nicht helfen. siehe auch Seite 108 und weiter von https://www.khronos.org/files/opengles_shading_language.pdf. – Xoppa

+0

Also habe ich versucht, was Sie empfohlen haben, aber es hat es noch langsamer gemacht - und ich habe sogar versucht, die #version 330 es zu entfernen und es auf die Standardversion für einen LibGDX Shader zu setzen (was ich für OpenGL 2 halte, aber ich nicht sicher, wenn es ist) und das hat immer noch nicht geholfen. – KingDolphin

Verwandte Themen