bu kesin şeyi kendim yaptığım açıklar ve burada optimize edilebilecek bazı şeyleri görüyoruz.
İlk olarak, enableTexture
koşullu koşulunu kaldırırdım ve bunun yerine gölgelendiricinizi iki programa ayırırdım, biri bunun gerçek durumu için, diğeri ise false için. IOS fragman shader'larında, özellikle de içinde doku bulunan okuyucularda şartlı koşullar çok pahalıdır.
İkincisi, burada dokuz bağımlı doku okuması var. Bunlar, doku koordinatlarının parça gölgelendirici içinde hesaplandığı doku okumalarıdır. IOS cihazlarındaki PowerVR GPU'larda bağlı doku okumaları çok pahalıdır, çünkü donanımın önbellekleme kullanarak doku okumalarını optimize etmesini engeller, çünkü 8 çevreleyen piksel ve bir merkezi nokta için sabit bir uzaklıktan örnekleme yapıyorsanız, bu hesaplamalar yapılmalıdır. köşe gölgelendirici içine taşındı.Bu aynı zamanda, her bir piksel için, her bir piksel için bir kez gerçekleştirilmesinin gerekmediği anlamına gelir ve daha sonra donanım enterpolasyonu geri kalanı işleyecektir.
Üçüncüsü, şimdilik() döngüler iOS shader derleyicisi tarafından bugüne kadar hiç kullanılmamıştı, bu yüzden elimden gelenin en iyisini yapmaya eğilimliyim.
Daha önce de belirttiğim gibi, açık kaynak kodlu iOS GPUImage çerçevesindeki bu tür evrimsel gölgelendiriciler yaptım.
attribute vec4 position;
attribute vec4 inputTextureCoordinate;
uniform highp float texelWidth;
uniform highp float texelHeight;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
void main()
{
gl_Position = position;
vec2 widthStep = vec2(texelWidth, 0.0);
vec2 heightStep = vec2(0.0, texelHeight);
vec2 widthHeightStep = vec2(texelWidth, texelHeight);
vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);
textureCoordinate = inputTextureCoordinate.xy;
leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;
rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;
topTextureCoordinate = inputTextureCoordinate.xy - heightStep;
topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;
topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;
bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;
bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;
bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;
}
ve aşağıdaki fragman gölgelendirici:
precision highp float;
uniform sampler2D inputImageTexture;
uniform mediump mat3 convolutionMatrix;
varying vec2 textureCoordinate;
varying vec2 leftTextureCoordinate;
varying vec2 rightTextureCoordinate;
varying vec2 topTextureCoordinate;
varying vec2 topLeftTextureCoordinate;
varying vec2 topRightTextureCoordinate;
varying vec2 bottomTextureCoordinate;
varying vec2 bottomLeftTextureCoordinate;
varying vec2 bottomRightTextureCoordinate;
void main()
{
mediump vec4 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate);
mediump vec4 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate);
mediump vec4 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate);
mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
mediump vec4 leftColor = texture2D(inputImageTexture, leftTextureCoordinate);
mediump vec4 rightColor = texture2D(inputImageTexture, rightTextureCoordinate);
mediump vec4 topColor = texture2D(inputImageTexture, topTextureCoordinate);
mediump vec4 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate);
mediump vec4 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate);
mediump vec4 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
resultColor += leftColor * convolutionMatrix[1][0] + centerColor * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];
gl_FragColor = resultColor;
}
texelWidth
ve texelHeight
üniforma giriş görüntüsünün genişliğinin ters ve yüksekliği genel evrişim filtre için, aşağıdaki tepe gölgelendirici kullanmak ve convolutionMatrix
forması, evrişiminizdeki çeşitli örneklerin ağırlıklarını belirtir.
Bir iPhone 4'te, bu 640x480 kamera video karesi için 4-8 ms'de çalışır; bu, bu görüntü boyutunda 60 FPS işleme için yeterince iyidir. Kenar algılama gibi bir şey yapmanız gerekiyorsa, yukarıdakileri basitleştirebilir, ön geçişte görüntüyü parlaklığa dönüştürebilir ve ardından yalnızca bir renk kanalından örnekleyebilirsiniz. Aynı cihazdaki kare başına yaklaşık 2 ms daha hızlı.
"* Texture2D() çağrısını döngüde yalnızca katı bir vec4 ile değiştirmeyi denedim ve sorun değil *" Bu ne anlama geliyor? Daha hızlı mı oldu? Performansı değişmedi mi? Ne oldu? –
"* Bunun neden herhangi bir soruna neden olduğunu göremiyorum. *" Shader çağrısında * dokuya * erişiyorsunuz ve bir soruna neden olabileceğini görmüyor musunuz? Ayrıca, orta dokusuna iki kez erişiyorsunuz. –
Doku aramaları olmadan (sonuncu hariç) katı bir 60 fps alıyorum. Dediğim gibi, bu optimize edilmiyor, ancak bu doku çağrılarından kaçınmanın bir yolu yok. Filtre başka türlü çalışamadı. Ama çok sayıda oyun gördüm, mobil ve değil, evrişim filtrelerine dayanan efektler kullanıyorlar ve herhangi bir sorun yaşamayacak gibi görünmüyorlar. Onlardan sakınmak için bir hile yok mu? – user1137704