GL ES: Optimalisasi shader fragmen

8

Rangkuman: Saya mendapatkan pelambatan FPS segera setelah saya mencoba mewarnai sprite (yaitu: gandakan tekstur dengan warna dalam fragmen shader)

Detail:

Perangkat keras: iPod touch 4

Saya menggambar 700 sprite di layar menggunakan glDrawArrays. Dan ya saya mengumpulkan semua ini dalam satu panggilan undian. Berikut ini menunjukkan struktur data Vertex:

struct Vertex {
    float Position[2];
    float Color[4];
    float Texture[2];
};

Ya saya mengirim warna dengan setiap titik karena saya secara selektif perlu mewarnai beberapa sprite tetapi tidak yang lain. Berikut ini adalah fragmen shader yang saya gunakan:

varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord );
}

Sampai sekarang ini berfungsi BESAR, memberi saya FPS 60 penuh !!!

TAPI

Segera setelah saya mengubah fragmen shader ke yang berikut (untuk memungkinkan pewarnaan):

varying lowp vec4 DestinationColor;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * DestinationColor;
}

Menggunakan tekstur 64x64 png berikut yang mengandung saluran alfa, rendering dengan glEnable (GL_BLEND):

masukkan deskripsi gambar di sini

Kinerja turun menjadi 47 FPS hanya karena perubahan tunggal ini {hanya dengan perkalian dengan SATU vektor} (FPS diukur menggunakan instrumen xcode dan detektif OpenGL). Apa yang sedang terjadi ?

Terima kasih.

Edit:

Saya juga telah mencoba melepas per atribut warna titik:

struct Vertex {
    float Position[2];
    float Texture[2];
};

Dan memodifikasi fragmen shader sebagai berikut:

precision lowp float;
varying lowp vec2 TexCoord;
uniform sampler2D TextureSampler;

void main(void)
{
    gl_FragColor = texture2D( TextureSampler, TexCoord ) * vec4(1.0,0.0,0.0,1.0);
}

Ini berjalan pada 52 FPS untuk 700 sprite (keuntungan hanya 5 FPS). Jadi ini bukan interpolasi, sepertinya penggandaannya sangat mahal. Hanya SATU multiplikasi ini?

fakhir
sumber
Apakah Anda telah mengaktifkan vsync? Angka-angka bisa berarti bahwa setelah perubahan Anda mulai kehilangan setiap vsync lainnya, yang mengarah ke 45 FPS rata-rata.
msell
Saya menguji pada iPhone 4, saya kira vsync sudah diaktifkan secara default. Itu menunjukkan 47 FPS dengan cara di xcode Instruments jadi saya pikir vsync tidak benar-benar masalah sama sekali. Tetapi pertanyaan saya yang sebenarnya adalah: Mengapa kinerja melambat dan bagaimana cara memperbaikinya?
fakhir
1
Apakah tekstur Anda memiliki saluran alfa? Jika tekstur tidak memiliki saluran alfa, dan rgb dikalikan dengan vec3, apakah itu menarik 60 fps lagi?
Will
Ya, tekstur memiliki saluran alfa. Silakan lihat tekstur yang terlampir di atas.
fakhir
2
Single core SGX 535, layar DPI tinggi dengan GPU tidak pernah dimaksudkan untuk menanganinya. Kinerja grafis pada resolusi asli pada perangkat itu selalu mengerikan. Anda harus menurunkan resolusi atau menargetkan 30 fps atau menargetkan perangkat keras yang lebih baru. Anda mengharapkan keajaiban dari GPU itu. Tidak perlu banyak untuk tangki itu.
Sean Middleditch

Jawaban:

2

Saya tidak berpikir masalah kinerja terjadi pada perkalian, tetapi pada interpolasi Anda DestinationColordi segitiga, antara vertex dan fragmen shader. Anda memiliki empat floats untuk menyisipkan di antara simpul pohon, untuk setiap fragmen untuk setiap sprite.

Untuk 700 sprite masing-masing 64x64 piksel, ini adalah 11468800 operasi tambahan per frame yang Anda minta untuk dilakukan GPU. Sangat mungkin bahwa Anda akan kehilangan beberapa vsyncs, dan karenanya jatuh ke FPS 40-ish.

Jika Anda ingin setiap simpul memiliki warna yang berbeda, sehingga Anda dapat memiliki gradien untuk setiap sprite, Anda kurang beruntung. Ada juga beberapa trik lain yang mungkin ingin Anda coba, tetapi saya pikir ini bukan masalahnya.

Karena apa yang tampaknya Anda lakukan adalah mewarnai setiap sprite, Anda dapat menurunkannya DestinationColormenjadi uniform, menggunakannya langsung dalam fragmen shader, dan mengubahnya untuk setiap panggilan. Dengan begitu tidak akan ada interpolasi yang terjadi. Anda akan kehilangan seluruh batching, tetapi Anda mungkin bisa batch sedikit jika Anda mengurutkannya berdasarkan warna.

Piyama Panda
sumber
Saya telah mengedit pertanyaan di atas dan menambahkan beberapa detail. Pada dasarnya saya mencoba menanggalkan per warna titik dan hanya melipatgandakan tekstur dengan vektor KONSTAN yaitu: gl_FragColor = tekstur2D (TextureSampler, TexCoord) * vec4 (1.0.0.0.0.0.1.0.0); . Mendapat 52 FPS, keuntungan hampir 5 FPS. Tetapi masih terlalu lambat dibandingkan dengan tidak ada warna. Memperlambat 8 ​​FPS hanya karena satu vektor perkalian?
fakhir
3
Tapi itu bukan perkalian tunggal - itu ~ 11 juta per frame.
Maximus Minimus
1
@ akhir Resolusi layar iPod Touch 4 adalah 960x640 piksel. Itu total 614400 piksel. Anda ingin membuat 700 sprite masing-masing 64x64 piksel. Itu 2867200 piksel, atau hampir 5 kali seluruh layar. Anda mungkin mendapatkan 60 fps asli Anda karena pengoptimal mengetahui apa yang Anda lakukan dan mungkin mengambil sampel gambar hanya sekali, tetapi jangan berharap itu terjadi untuk semua kasus. Pemrograman grafik seluler jauh lebih terbatas daripada pemrograman desktop, jadi bertindaklah sesuai itu.
Panda Pajama