Pixi.js: dianggap gl-matriks?

Dibuat pada 30 Jun 2017  ·  39Komentar  ·  Sumber: pixijs/pixi.js

Ini mungkin bid'ah, tapi saya akan melontarkan ide di sini dan membiarkan orang-orang meneriakkan pembunuhan berdarah...pernahkah kita mempertimbangkan kemungkinan standarisasi pada matriks, titik-titik yang berbasis array dan bukan berbasis objek? WebGL mengharapkan array di sebagian besar vertex/texture/etc apis. Ada juga banyak modul ekosistem yang ada yang menstandarisasi array lama atau asli (misalnya, https://github.com/toji/gl-matrix) gl-matrix akan menyenangkan mengingat banyak browser memiliki dukungan SIMD perangkat keras di belakang bendera , dan akan segera tersedia (sebenarnya, gl-matrix secara internal mendukung ini sekarang.)

Saya menyadari ini akan menjadi perubahan paradigma besar-besaran untuk pixi, dan benar-benar menghancurkan kompatibilitas ke belakang ...

Komentar yang paling membantu

@GoodBoyDigital Saya pikir mungkin Anda benar. beralih ke mrs teman saya. google, saya menemukan ini:

https://stackoverflow.com/questions/15823021/when-to-use-float32array-instead-of-array-in-javascript

jawaban berperingkat teratas (saat ini dengan 44 suara) tampaknya masuk akal dan relevan.

Semua 39 komentar

1) SIMD mati. https://github.com/rwaldron/tc39-notes/blob/a66df6740eec3358d5e24f81817db99d6ee41401/es8/2017-03/mar-21.md#10if -simdjs-status-update

2) 6 bidang sederhana "a,b,c,d,tx,ty" berkinerja jauh lebih baik daripada matriks Float32Array(9). Tidak dapat memberikan tautan ke tes, tetapi saya dan @GoodBoyDigital sudah mencoba mengintegrasikannya.

3) JS melakukan presisi ganda, yang sangat penting untuk aplikasi yang bekerja dengan koordinat besar. "proyeksi x transformasi" untuk grafik dan dan sprite lebih baik berada di sisi JS.

Saya menggunakan Float32Array (9) di v5 yang dalam pengujian jsperf saya serupa jika tidak memiliki kinerja yang sama, dan mencegah kami untuk melakukan operasi toArray dan transpose.

https://github.com/pixijs/pixi.js/blob/455c059e8d155c1d9a05fc2ece2c02b3bdf8bf84/plugins/core/src/math/Matrix.js

gl-matrix bermanfaat karena memiliki SIMD (yang seperti yang disebutkan Ivan adalah spesifikasi mati), tetapi juga memiliki kekurangan dalam implementasinya. Kami ingin matriks 3x3 ( Float32Array(9) ) mencapai GPU, tetapi lakukan operasi seolah-olah matriks 2D untuk menghemat waktu komputasi. gl-matrix tidak memiliki mekanisme yang baik untuk itu.

Versi v5 menggunakan penyimpanan yang dapat kami unggah langsung ke GPU serta hanya beroperasi pada bagian 2D yang kami pedulikan. Ini juga menyiapkan kami untuk dapat menggunakan SharedArrayBuffers dan pengoptimalan lain yang memungkinkan kami melakukan lebih banyak pekerjaan pada pekerja web. Kami akan melihat seberapa jauh kami bisa melakukannya.

@englercj Saya khawatir kita harus menggunakan Math.fround di banyak tempat agar konsisten. Coba perf Float64Array.

Saya dapat mencoba membuatnya Float64Array, tetapi kemudian kami masih perlu menguranginya menjadi presisi tunggal untuk diunggah. Perlu diingat juga, saat ini kita menggunakan float32 saat kita mengupload ke GPU . Jadi kami menghitung secara ganda, lalu memotong menjadi tunggal. Ini mungkin lebih akurat daripada melakukan semuanya secara tunggal, tetapi saya ingin mencoba dan konsisten dengan tipe data yang kami unggah. Sayangnya itu berarti presisi tunggal hingga GL 4.0, dan WebGL 2 hanya GL ES 3.0 :(

Unggahan matriks tidak pernah menjadi hambatan kami, kami menggunakan "uniform3fv" di tempat-tempat itu, ini bukan operasi sederhana, dan diikuti dengan drawCall, dan dalam kebanyakan kasus, unggahan buffer besar. Aplikasi pixi berat hanya melakukan sekitar 400 drawcalls per frame,

Setelah menghadapi masalah pengguna dengan koordinat besar, saya lebih suka menyimpan semuanya dengan presisi ganda hingga kami mengunggahnya.

Juga, notasi "a,b,c,d,tx,ty" lebih mudah ditulis dan dibaca daripada "0,1,3,4,6,7". Ini juga digunakan di tulang belakang, mereka memiliki transformasi yang sangat canggih di atas itu. Jika kita beralih ke matriks, tidak akan mudah untuk memeriksa kode kita nanti. Bagi sebagian orang sulit membayangkan operasi matriks, tetapi saya membacanya dengan mudah.

UPD. Saya juga berpikir ini akan membantu kami lebih dari mengonversi matriks: https://github.com/gameofbombs/gobi/blob/master/src/core/math/FlatTransform2d.ts , itu transformasi "Flat", berisi semua bidang yang diperlukan untuk perhitungan matriks.

UPD2. Tetapi untuk transformasi 3d, Float32Array (16) lebih baik dan saya tidak akan menentangnya.

Suara saya pergi ke salah satu yang memberikan kinerja terbaik. Terakhir saya memeriksanya menggunakan objek di atas array lebih cepat. Meskipun saya tidak 100% yakin apakah itu masih benar, itu mungkin telah berubah!

Untuk 3d saya menyukai gaya gl-matrix, terutama karena banyak hal yang diunggah ke GPU! Dengan Pixi ini umumnya tidak terjadi. Kebanyakan manipulasi terjadi di js land (misalnya sprite batcher).

https://jsperf.com/obj-vs-array-view-access/1

Berikut adalah pengujian yang saya lakukan. Objek lebih lambat dari Float32Array, keduanya jauh lebih lambat dari Array normal. Kemudian kita mendapatkan presisi ganda dan kecepatan CPU tercepat dan dapat langsung diunggah.

Sunting: Sepertinya hasil Array itu kebetulan, saya tidak dapat mereproduksinya?

Suara saya pergi ke salah satu yang memberikan kinerja terbaik.
Terakhir saya memeriksanya menggunakan objek di atas array lebih cepat.

Ini sangat menarik. Tampaknya berlawanan dengan intuisi bahwa objek akan lebih cepat daripada array numerik murni, karena vm yang mendasarinya harus dapat melakukan sejumlah optimasi, mengetahui bahwa semantik objek sebagian besar dapat dihilangkan. Saya ingin tahu apakah Anda punya ide _why_ objek mungkin lebih cepat?

Hasil yang relevan dari komputer saya (i7, Windows 10):

Krom 59:

image

Firefox 54.0.1 (32-bit):

image

Microsoft Edge 40.15063.0.0:

image

Sepertinya hasil chrome saya dari Array menjadi lebih cepat adalah kebetulan, tidak yakin apa itu tetapi tidak dapat mereproduksinya sekarang. Itu sekitar 50M ops/s, tetapi 500M ops/s pada satu putaran yang saya lakukan sebelumnya. Aneh...

Bagaimanapun, anggota Float32Array secara konsisten memiliki kecepatan yang sama atau lebih cepat dari objek di semua browser. Itulah sebabnya saya menggantinya, kecepatannya sama seperti sebelumnya (atau lebih cepat) tetapi sekarang kami menghindari transpos dan mengisi array untuk unggahan.

Bisakah Anda melakukannya dengan Float64 juga? :)

Saya peduli dengan kualitas kode lebih dari satu operasi matriks per drawcall.

Juga, kami tidak banyak menggunakan invert. updateTransform() adalah masalah kita.

Saya peduli dengan kualitas kode lebih dari satu operasi matriks per drawcall.

Bagaimana kualitas kode Float64Array lebih tinggi? Saya mengerti kami mendapatkan lebih banyak presisi, tetapi saya tidak yakin saya mengikuti mengapa itu sangat penting mengingat kami tetap mengurangi ke presisi tunggal.

Juga, kami tidak menggunakan banyak invert. updateTransform() adalah masalah kita.

Ini adalah pembandingan baca/tulis dari penyimpanan data, operasi yang dilakukan pada nilai-nilai peralihan yang tidak relevan.

Saya peduli dengan kualitas kode lebih dari satu operasi matriks per drawcall.

Saya setuju dengan ini juga. Pertimbangkan bahwa "standarisasi" pada matriks, titik, & vektor berbasis array mungkin sebenarnya lebih merupakan peningkatan kualitas kode daripada kinerja ... Saya akan mempertimbangkan penggunaan kembali perpustakaan matriks/vektor js populer dan lebih banyak interoperabilitas dengan modul rendering populer untuk menjadi kemenangan kualitas kode yang besar.

Ini adalah pembandingan baca/tulis dari penyimpanan data,
operasi yang dilakukan pada nilai-nilai peralihan dalam tidak relevan.

Saya pikir Anda berdua benar. Ini adalah pembandingan umum penyimpanan data baca/tulis. Tapi Ivan memiliki poin yang sangat bagus; jika updateTransform() adalah operasi yang luar biasa, akan menarik untuk melihatnya.

Saya khawatir tentang benchmark mikro secara umum; dengan kumpulan data statis ini, saya bertanya-tanya apakah kita secara tidak sengaja akhirnya mengambil keuntungan dari pengoptimalan kompiler di javascript vms dalam tes ini. menjalankan tes dunia nyata akan jauh lebih mencerahkan (dengan mengorbankan lebih banyak pekerjaan untuk disiapkan.)

Saya setuju dengan ini juga. Pertimbangkan bahwa "standarisasi" pada matriks, titik, & vektor berbasis array mungkin sebenarnya lebih merupakan peningkatan kualitas kode daripada kinerja ... Saya akan mempertimbangkan penggunaan kembali perpustakaan matriks/vektor js populer dan lebih banyak interoperabilitas dengan modul rendering populer untuk menjadi kemenangan kualitas kode yang besar.

Saya untuk matriks presisi ganda "(a,b),(c,d),(tx,ty)", dengan konversi ke float32array untuk diunggah dan didukung oleh "posX,posY,pivotX, pivotY,scaleX,scaleY, geserX, geserY,rotZ". Saya akan tetap menggunakannya di fork saya, tetapi saya memilih untuk tidak berurusan dengan array matriks di master pixi juga. Itu standar saya.

Saya juga ragu apakah mungkin membuat orang menggunakan satu atau dua standar untuk matematika vec di js.

Bagaimana kualitas kode Float64Array lebih tinggi? Saya mengerti kami mendapatkan lebih banyak presisi, tetapi saya tidak yakin saya mengikuti mengapa itu sangat penting mengingat kami tetap mengurangi ke presisi tunggal.

Kami mengalikan transformasi kamera dengan transformasi sprite (untuk menggulir) di updateTransform. Hasil pas di layar hanya jika kecil, jadi angka akhirnya kecil, tetapi posisi sprite dan posisi kamera bisa besar. Solusi sisi pengguna:

1) menghitung segala sesuatu di sisinya. PIXI hanya berurusan dengan koordinat yang relatif kecil.
2) membagi dunia menjadi potongan-potongan dengan koordinat besar, sprite memiliki koordinat relatif kecil, namun itu tidak akan berfungsi untuk kamera subpiksel => kamera juga membutuhkan koordinat besar dan kecil.

Tidak apa-apa untuk memaksa pengguna melakukannya di sisinya jika ada proyek besar, tetapi untuk yang kecil itu hanya satu lagi sakit kepala.

Saya juga ragu apakah mungkin membuat orang menggunakan satu atau dua standar untuk matematika vec di js.

Saya tidak mengerti apa yang Anda maksud, bisakah Anda menjelaskannya?

Saya tidak mengerti apa yang Anda maksud, bisakah Anda menjelaskannya?

Aku tidak bisa, itu terlalu banyak untukku.

Kami memiliki orang-orang dengan pengalaman berbeda baik dalam pengoptimalan tingkat rendah. dan konstruksi bahasa, DSL-s. Kita membutuhkan standar yang memuaskan kita semua pada tingkat tertentu.

Dalam dua tahun terakhir, saya membuat dua garpu pixi (untuk v3 dan v4) dengan Transform yang berbeda, saya berurusan dengan "pixi-spine" yang memiliki transformasi lanjutannya sendiri dan saya membuat garpu ketiga. Dari sudut pandang "past ivan", array adalah yang terbaik karena bentuknya yang paling sederhana dan ada "gl-matrix".

Saya setuju dengan @ivanpopelyshev bahwa memelihara 64-bit itu penting. Saya mencoba mencari cara bagaimana kita melakukannya, secara efisien, tanpa membuat dan menyalin buffer setiap frame.

Mungkin kita menyimpannya sebagai Float64Array, dan ketika meng-upload menyalinnya ke Float32Array. Itu setidaknya memungkinkan kita menggunakan array yang diketik sebagai dukungan penyimpanan yang seharusnya lebih mudah untuk disalin ke/dari webworker.

Float64Array saat itu, saya hanya harus ingat untuk menggunakan (0,1), (3,4), (6,7) sebagai X,Y,translate

Semua hal menarik kawan, saya ingin kami membandingkan solusi yang kami usulkan dalam skenario pixi nyata - sesuatu seperti bunnymark.

Pengalaman saya di bidang ini adalah ketika saya dan @ivanpopelyshev terakhir kali beralih ke gl-matrix untuk bunny mark, kami menemukan itu berjalan jauh lebih lambat (seperti sepertiga lebih lambat!)

Itu beberapa saat yang lalu dan saya benar-benar lebih suka saya salah di sini!
Jika perbedaan kecepatan sekarang dapat diabaikan maka saya pikir rute yang diusulkan di atas adalah kartu as.

Pixi adalah SPEEED :P Mari kita pastikan kita menguji sebelum melakukan sepenuhnya untuk solusi apapun.

Kami masih membutuhkan benchmark Float64Array. Implementasi ini dapat diterima untuk saya, tetapi secara pribadi saya akan menggunakan matriks lama di garpu saya. Juga jangan lupa untuk menambahkan properti hanya untuk kompatibilitas.

Satu hal lagi: @mreinstein , salah satu standar yang saya ingat adalah PaperScript, ini adalah bahasa khusus untuk paper.js, menambahkan operasi titik langsung ke dalam bahasa. Jika JS memiliki lebih banyak gula sintaks, kami akan menggunakan sesuatu seperti itu juga.

Apakah ada yang bisa saya bantu dengan re: bunnymark yang diperbarui ini? Saya senang untuk menyumbangkan beberapa waktu dengan ini.

Saya akan sangat tertarik untuk mengikuti hal-hal hebat yang terjadi di sini. Terlepas dari hasilnya. Jika hal-hal berbasis array akhirnya masih jauh lebih lambat, saya sangat ingin tahu tentang _why_ di baliknya.

Sesuatu yang perlu diperhatikan kembali: pengujian perf ... chrome's v8 baru-baru ini (dalam v59) merilis beberapa perubahan yang cukup dramatis untuk v8 yang disebut turbofan. Seharusnya memiliki beberapa peningkatan kinerja yang signifikan.

https://v8project.blogspot.com/2017/05/launching-ignition-and-turbofan.html

mungkin menarik untuk menjalankan bunnymark yang diperbarui pada versi sebelum turbofan hadir vs sekarang, hanya untuk itu.

@GoodBoyDigital Saya memperbarui bangku untuk memasukkan Float64Array, dan secara konsisten lebih cepat untuk membaca/menulis ke array daripada objek. Jika menjadi lebih lambat di pixi maka sesuatu yang lain berubah, karena membaca/menulis ke toko dukungan Float64Array lebih cepat daripada objek.

https://jsperf.com/obj-vs-array-view-access/1
image

Hanya di Edge kecepatan objek cocok/melebihi Float64Array, dan itu sangat dekat.

Saya sudah menguji ini di env saya dan saya mendapatkan hasil yang serupa ... apa-apaan ini?! Mengapa array Float64 membaca/menulis secara signifikan lebih cepat daripada operasi array Float32 yang setara? Satu-satunya hal yang terlintas dalam pikiran adalah mungkin 64 bit float sejajar pada batas kata? saya bingung.

Terima kasih atas tawarannya @mreinstein ! Jika Anda dapat membantu kami dengan beberapa tes kinerja yang pasti akan mengakhiri seluruh perdebatan dengan fakta-fakta keras yang dingin!

Hal terbaik yang harus dilakukan adalah fork pixi dan kemudian ganti transformasi dengan kelas matriks gl-matrix atau @englercj . Untuk contoh ini, kita hanya benar-benar perlu membuat kumpulan sprite bekerja juga - bukan seluruh mesin!

Kemudian setelah kami memiliki versi tweak, kami dapat menguji kinerja di sini: https://pixijs.github.io/bunny-mark/
Kita bisa dipusingkan dengan tipe array yang berbeda.

@englercj itu luar biasa

@mreinstein hanya firasat, saya pikir ini mungkin ada hubungannya dengan konversi dari 64bit -> 32bit
sebagai angka di js adalah 64bit kan?

@GoodBoyDigital Saya pikir mungkin Anda benar. beralih ke mrs teman saya. google, saya menemukan ini:

https://stackoverflow.com/questions/15823021/when-to-use-float32array-instead-of-array-in-javascript

jawaban berperingkat teratas (saat ini dengan 44 suara) tampaknya masuk akal dan relevan.

Jika Anda dapat membantu kami dengan beberapa tes kinerja

Baiklah, senang bisa membantu dengan ini. :)

Hal terbaik untuk dilakukan adalah garpu pixi

@GoodBoyDigital @englercj dari mana cabang terbaik untuk bercabang saat ini?

kemudian ganti transformasi dengan kelas matriks gl-matrix atau @englercj .
Untuk contoh ini, kita hanya benar-benar perlu membuat kumpulan sprite bekerja juga - bukan seluruh mesin!

Bisakah Anda menguraikan ini sedikit lebih banyak? Saya tidak ingin mengubah seluruh mesin menjadi gl-matrix hanya untuk menjalankan bangku perf ... Saya tidak melihat hal-hal batch sprite di https://github.com/pixijs/bunny-mark Tampaknya ada PIXI.Container sebagai elemen root, yang ditambahkan kelinci. Apakah Anda mengatakan saya harus mulai dengan pixi.container, pixi.sprite dan bekerja mundur dari sana ke atas pohon ketergantungan untuk menemukan semua tempat di mana barang-barang transformasi perlu diganti? Bukan berarti saya tidak setuju, hanya ingin memastikan bahwa saya memiliki strategi yang tepat untuk meminimalkan pekerjaan yang tidak perlu.

updateTransform memiliki dua operasi matriks di dalamnya:

  1. komposisi dari posisi, poros, skala, rotasi - tidak dapat ditingkatkan.
  2. perkalian dengan matriks induk - dapat ditingkatkan.

saya sarankan untuk membuat kelas matriks dengan alat peraga "a,b,c,d,tx,ty" lama yang didukung oleh Float64Array, dan tulis ulang updateTransform. Juga, @mreinstein membuat cukup banyak hal untuk menjadi inti, saya sarankan kita menambahkannya, jadi dia memiliki akses ke cabang dan membangun pertanian.

jadi dia memiliki akses ke cabang dan membangun pertanian.

Setiap orang memiliki akses ke itu, fork + PR melakukan semua itu.

Saya ingin tahu hasil seperti apa yang Anda dapatkan di bunny mark.. ketika saya mencoba berbagai cabang (dev, rilis, lainnya) dari chrome dengan kelinci 100k default saya mendapatkan 10-16fps secara konsisten. Melakukan analisis kinerja pada kode yang berjalan lebih dari 8,75 detik:

screen shot 2017-07-02 at 11 58 03 am

Hampir semua waktu dihabiskan dalam panggilan javascript.

screen shot 2017-07-02 at 11 57 50 am

Dari waktu yang dihabiskan di javascript ini, sebagian besar waktu sebenarnya dihabiskan di Sprite.calculateVertices() . 4x lebih banyak daripada yang dihabiskan di TransformStatic.updateTransform()

Di firefox saya mendapatkan sekitar dua kali framerate, tetapi perincian waktu yang dihabiskan serupa; calculateVertices() menghabiskan sebagian besar waktu di kedua browser. Apakah ini diharapkan? Apakah Anda mendapatkan hasil yang serupa dalam menjalankan bunnymark Anda?

Ini diharapkan untuk kelinci. Dan operasi matriks yang sedang kita bicarakan dilakukan di dua tempat: upateTransform() untuk perkalian dan flush() SEKALI PER PANGGILAN. Tidak masalah dalam skala besar.

Saya bingung. :( Bagaimana saya bisa mengetahui kinerja benchmark itu? Saya mendapat kesan bahwa itu sebagian besar didasarkan pada fps murni yang dicapai. Jika itu benar, maka frame rate saya sedang _sangat_ dibatasi oleh perhitungan simpul. Melihat diagram pertama yang saya tempel di atas, rendering adalah sebagian kecil dari total waktu bingkai.pembaruan vertex dan transformasi melebihi total waktu bingkai.

Jika itu salah, dan fps bukanlah ukuran performa pixi build saya, kriteria apa yang saya gunakan untuk mengukur build tertentu?

Itu dapat dicekik baik pada CPU baik di sisi GPU (tidak ditampilkan),

Jika Anda memiliki FPS kurang dari 60 tetapi "idle" besar - GPU-nya.

Jika idle kecil, maka CPU-nya.

countVertices memiliki operasi matriks di dalamnya - hanya mengalikan empat sudut dengan matriks.

Hanya ide kecil untuk garpu TS: tambahkan transformasi yang sebaris properti untuk tipe matriks. Sayang sekali belum ada transformasi semacam itu untuk TS :(

Saya pikir itu bisa dilakukan untuk babel juga jika kita menemukan cara untuk membubuhi keterangan variabel matriks.

Aku tidak mengerti lagi apa yang sedang terjadi.

Alt text

Sesuatu yang perlu diingat: tujuan dari benchmark ini pertama-tama adalah untuk melihat apakah menggunakan objek vs gl-matrix akan menjadi hit kinerja yang besar, seperti yang diperkirakan. Terlepas dari perbedaan dalam hasil benchmark kami, kami tampaknya menunjukkan secara konsisten bahwa perf objek tidak lebih buruk daripada kebanyakan kasus array.

Saya juga ingin menghindari menarik kesimpulan kinerja tentang pixi secara umum di sini karena saya telah membuat profil tanda kelinci. Di Chrome, > 50% dari total waktu program dihabiskan di Sprite.calculateVertices() (40% ish), diikuti oleh TransformStatic.updateTransform() (11% ish) Firefox tampaknya berjalan dua kali lebih cepat, tetapi rasionya waktu yang dihabiskan dalam 2 fungsi tersebut masih konsisten.

Saya ingin menghindari topik yang terlalu jauh, tetapi saya akan mengatakan bahwa dalam melakukan pembuatan profil bunnymark ini, saya mulai berpikir bahwa penggunaan es5 getter/setter kami mungkin ada hubungannya dengan penurunan kinerja di chrome: https: //jsperf.com/es5-getters-setters-versus-getter-setter-methods/10

Apakah ada di antara kalian yang nongkrong santai di sini? Saya pikir akan lebih mudah untuk mengobrol dalam waktu semi-nyata daripada mengirim pesan di sini.

Apa yang Anda email @mreinstein ? Akan mengundang Anda untuk malas 👍

Berdasarkan apa yang dikatakan @englercj ternyata kami tidak melakukan ini. Penutupan.

Hanya pembaruan kecil: Saya memiliki matriks 3x3 alih-alih 3x2 di https://github.com/pixijs/pixi-projection/blob/master/src/Matrix2d.ts , berdasarkan Float64Array.

Utas ini telah dikunci secara otomatis karena tidak ada aktivitas terbaru setelah ditutup. Silakan buka edisi baru untuk bug terkait.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

gaccob picture gaccob  ·  3Komentar

softshape picture softshape  ·  3Komentar

neciszhang picture neciszhang  ·  3Komentar

lunabunn picture lunabunn  ·  3Komentar

readygosports picture readygosports  ·  3Komentar