WebGL'den WebGPU'ya

Furkan
François Beaufort

Bir WebGL geliştiricisi olarak, modern grafik API'lerinin ilerlemelerini web'e taşıyan WebGL'nin yerini alan WebGPU'yu kullanmaya başlamak sizi hem ürkütüyor hem de heyecanlandırıyor.

WebGL ve WebGPU'nun birçok temel kavramı paylaştığını bilmek güven vericidir. Her iki API de GPU'da gölgelendirici adı verilen küçük programları çalıştırmanızı sağlar. WebGL, köşe ve parça gölgelendiricileri, WebGPU ise bilgi işlem gölgelendiricileri destekler. WebGL, OpenGL Gölgelendirme Dili (GLSL) kullanırken WebGPU, WebGPU Gölgeleme Dili'ni (WGSL) kullanır. İki dil farklı olsa da temel kavramlar çoğunlukla aynıdır.

Bunu göz önünde bulundurarak, bu makalede, başlamanıza yardımcı olmak amacıyla WebGL ve WebGPU arasındaki bazı farklılıklar vurgulanmaktadır.

Global durum

WebGL'nin çok sayıda global durumu vardır. Hangi dokuların ve arabelleklerin bağlandığı gibi bazı ayarlar tüm oluşturma işlemleri için geçerlidir. Bu genel durumu, çeşitli API işlevlerini çağırarak ayarlarsınız ve siz değiştirene kadar geçerli kalır. Genel bir ayarı değiştirmeyi kolayca unutulduğundan WebGL'deki genel durum ana hata kaynağıdır. Ayrıca, geliştiricilerin genel durumu kodun diğer bölümlerini etkileyecek şekilde yanlışlıkla değiştirmemeye dikkat etmesi gerektiğinden, genel durum kod paylaşımını da zorlaştırır.

WebGPU, durum bilgisiz bir API'dir ve genel bir durumu korumaz. Bunun yerine, WebGL'de global olan oluşturma durumunun tümünü kapsayan ardışık düzen kavramını kullanır. Ardışık düzende kullanılacak harmanlama, topoloji ve özellikler gibi bilgiler bulunur. Ardışık düzenler sabittir. Bazı ayarları değiştirmek isterseniz başka bir ardışık düzen oluşturmanız gerekir. WebGPU, komutları birlikte toplu olarak toplamak ve kaydedildikleri sırayla yürütmek için komut kodlayıcıları da kullanır. Bu, örneğin, nesneler üzerinde tek bir geçişte, uygulamanın her bir ışığın gölge haritası için bir tane olmak üzere birden çok komut akışı kaydedebildiği gölge eşlemesinde kullanışlıdır.

Özetlemek gerekirse, WebGL'nin global durum modeli sağlam, özelleştirilebilir kitaplıklar ve uygulamalar oluşturmayı zor ve hassas hale getirdiğinden, WebGPU geliştiricilerin GPU'ya komut gönderirken takip etmeleri gereken durum miktarını önemli ölçüde azalttı.

Artık senkronize etme

GPU'larda, komut göndermek ve bunları eşzamanlı olarak beklemek genellikle verimsizdir. Bu yöntem, ardışık düzeni temizleyip baloncuklara neden olabilir. Bu durum özellikle, GPU sürücüsünün JavaScript'ten ayrı bir işlemde çalıştığı çok işlemli bir mimari kullanan WebGPU ve WebGL için geçerlidir.

Örneğin WebGL'de, gl.getError() çağrısı yapmak için JavaScript işleminden GPU işlemine ve GPU'ya kadar eş zamanlı bir IPC gerekir. Bu durum, iki işlem iletişim kurarken CPU tarafında baloncuklara neden olabilir.

Bu balonları önlemek için WebGPU tamamen eşzamansız olacak şekilde tasarlanmıştır. Hata modeli ve diğer tüm işlemler eşzamansız olarak gerçekleşir. Örneğin, bir doku oluşturduğunuzda, doku aslında bir hata olsa bile işlem hemen başarılı olmuş görünür. Hatayı yalnızca eşzamansız olarak bulabilirsiniz. Bu tasarım çapraz süreçlerle iletişimi mümkün kılar ve uygulamalara güvenilir performans sağlar.

Compute gölgelendiriciler

İşlem gölgelendiricileri, genel amaçlı hesaplamalar yapmak için GPU'da çalışan programlardır. Yalnızca WebGPU'da kullanılabilir, WebGL'de kullanılamaz.

Köşe ve parça gölgelendiricilerden farklı olarak, grafik işlemeyle sınırlı değildir ve makine öğrenimi, fizik simülasyonu ve bilimsel hesaplama gibi çok çeşitli görevler için kullanılabilirler. Hesap gölgelendiriciler, yüzlerce hatta binlerce iş parçacığı ile paralel olarak yürütülür ve bu da büyük veri kümelerinin işlenmesi için çok verimli bir çözüm sunar. WebGPU ile ilgili bu kapsamlı makalede GPU hesaplaması hakkında bilgi edinin ve daha ayrıntılı bilgi edinin.

Video karesi işleme

JavaScript ve WebAssembly kullanarak video karelerini işlemenin bazı dezavantajları vardır: Verilerin GPU belleğinden CPU belleğine kopyalanması maliyeti ve çalışanlar ile CPU iş parçacıklarıyla gerçekleştirilebilecek sınırlı paralellik. WebGPU'da bu sınırlamalar yoktur. Bu nedenle, WebCodecs API ile sıkı entegrasyonu sayesinde video karelerini işlemek için idealdir.

Aşağıdaki kod snippet'inde, bir VideoFrame'in WebGPU'da harici bir doku olarak nasıl içe aktarılacağı ve işleneceği gösterilmektedir. Bu demoyu deneyebilirsiniz.

// Init WebGPU device and pipeline...
// Configure canvas context...
// Feed camera stream to video...

(function render() {
  const videoFrame = new VideoFrame(video);
  applyFilter(videoFrame);
  requestAnimationFrame(render);
})();

function applyFilter(videoFrame) {
  const texture = device.importExternalTexture({ source: videoFrame });
  const bindgroup = device.createBindGroup({
    layout: pipeline.getBindGroupLayout(0),
    entries: [{ binding: 0, resource: texture }],
  });
  // Finally, submit commands to GPU
}

Varsayılan olarak uygulama taşınabilirliği

WebGPU, sizi limits isteğinde bulunmaya zorlar. Varsayılan olarak requestDevice(), fiziksel cihazın donanım özellikleriyle eşleşmeyen bir GPUCihazı döndürür. Bunun yerine tüm GPU'lar arasında makul ve en düşük ortak paydayı döndürür. WebGPU, geliştiricilerin cihaz sınırı istemesini zorunlu kılarak uygulamaların mümkün olduğunca çok cihazda çalışmasını sağlar.

Tuval işleme

WebGL, siz bir WebGL bağlamı oluşturduktan ve alfa, antialias, colorSpace, deeplink, keepDrawingBuffer veya stencil gibi bağlam özellikleri sağladığınızda tuvali otomatik olarak yönetir.

Öte yandan WebGPU, tuvali sizin yönetmenizi gerektirir. Örneğin, WebGPU'da kenar yumuşatma özelliğini uygulamak için bir çoklu örnek doku oluşturur ve bunu buna göre oluşturursunuz. Ardından, çok örnekli dokuyu normal bir dokuya çözer ve bu dokuyu zemine çizersiniz. Bu manuel yönetim, tek bir GPUDevice nesnesinden istediğiniz kadar kanvasın çıktısını almanıza olanak tanır. Buna karşılık, WebGL tuval başına yalnızca bir bağlam oluşturabilir.

WebGPU Birden Çok Tuval demosuna göz atın.

Ayrıca, tarayıcıların şu anda sayfa başına WebGL tuvallerinin sayısının sınırlandırılması olduğunu da belirtmek isteriz. Bu metin yazıldığında Chrome ve Safari, aynı anda en fazla 16 WebGL tuvalini kullanabiliyorken, Firefox 200 taneye kadar WebGL tuvalini oluşturabilir. Öte yandan, sayfa başına WebGPU kanvaslarının sayısında bir sınırlama yoktur.

Safari, Chrome ve Firefox tarayıcılarda maksimum sayıda WebGL tuvalini gösteren ekran görüntüsü
Safari, Chrome ve Firefox'ta maksimum WebGL tuval sayısı (soldan sağa) - demo.

Faydalı hata mesajları

WebGPU, API'den döndürülen her mesaj için bir çağrı yığını sağlar. Bu sayede, hatanın kodunuzda nerede oluştuğunu hızlıca görebilirsiniz. Bu da hata ayıklama ve hataları düzeltme konusunda fayda sağlar.

WebGPU hata mesajları, çağrı yığını sağlamanın yanı sıra kolayca anlaşılabilir ve işlem yapılabilir. Hata mesajları genellikle hatanın açıklamasını ve hatanın nasıl düzeltileceğine dair önerileri içerir.

WebGPU, her bir WebGPU nesnesi için özel bir label sağlamanıza da olanak tanır. Bu etiket daha sonra tarayıcı tarafından GPUError mesajlarında, konsol uyarılarında ve tarayıcı geliştirici araçlarında kullanılır.

Adlardan dizinlere

WebGL'de birçok şey adlarla birbirine bağlanır. Örneğin, GLSL'de myUniform adlı tek tip bir değişkeni tanımlayabilir ve gl.getUniformLocation(program, 'myUniform') kullanarak konumunu alabilirsiniz. Bu özellik, tek tip değişkenin adını yanlış yazarsanız hata almanıza yol açar.

Diğer yandan, WebGPU'da her şey tamamen bayt ofseti veya dizin (genellikle location olarak adlandırılır) ile bağlıdır. WGSL ve JavaScript'teki kod konumlarını senkronize etmek sizin sorumluluğunuzdadır.

Mipmap oluşturma

WebGL'de, bir dokunun seviye 0 mip'ini oluşturabilir ve daha sonra, gl.generateMipmap() işlevini çağırabilirsiniz. WebGL, sizin için diğer tüm mip düzeylerini oluşturur.

WebGPU'da mipmaps'i kendiniz oluşturmanız gerekir. Bunu yapacak yerleşik bir işlev yoktur. Karar hakkında daha fazla bilgi edinmek için özellikler tartışmasına göz atın. Mipmaps oluşturmak veya bunu kendiniz öğrenmek için webgpu-utils gibi kullanışlı kitaplıklardan yararlanabilirsiniz.

Depolama arabellekleri ve depolama dokuları

Tek tip arabellekler, hem WebGL hem de WebGPU tarafından desteklenir ve gölgelendiricilere sınırlı boyutlu sabit parametreleri iletmenize olanak tanır. Tek tip arabelleklere çok benzeyen depolama arabellekleri, yalnızca WebGPU tarafından desteklenir ve tek tip arabelleklerden daha güçlü ve esnektir.

  • Gölgelendiricilere aktarılan depolama arabellekleri verileri, tek tip arabelleklerden çok daha büyük olabilir. Spesifikasyonda, tek tip arabellek bağlamalarının en fazla 64 KB boyutunda olabileceği belirtilse de (bkz. maxUniformBufferBindingSize) WebGPU'da depolama arabelleği bağlamasının maksimum boyutu en az 128 MB'tır (maxStorageBufferBindingSize'e bakın).

  • Depolama arabellekleri yazılabilirdir ve bazı atomik işlemleri desteklerken tek tip arabellekler ise salt okunurdur. Bu, yeni algoritma sınıflarının uygulanmasına olanak tanır.

  • Depolama arabellekleri bağlamaları, daha esnek algoritmalar için çalışma zamanı boyutundaki dizileri destekler. Gölgelendiricide ise tek tip arabellek dizisi boyutlarının sağlanması gerekir.

Depolama dokuları yalnızca WebGPU'da desteklenir ve depolama arabelleklerini tek tip arabelleklere dokular oluşturmak için kullanılır. Normal dokulardan daha esnektirler, rastgele erişimle yazma işlemlerini destekler (ve gelecekte okumaları da destekler).

Arabellek ve doku değişiklikleri

WebGL'de, bir arabellek veya doku oluşturabilir ve daha sonra istediğiniz zaman boyutunu sırasıyla gl.bufferData() ve gl.texImage2D() ile değiştirebilirsiniz.

WebGPU'da arabellekler ve dokular sabittir. Yani, oluşturulduktan sonra boyutlarını, kullanımlarını veya biçimlerini değiştiremezsiniz. Yalnızca içeriklerini değiştirebilirsiniz.

Uzay kuralı farklılıkları

WebGL'de, Z klip alanı -1 ile 1 arasındadır. WebGPU'da Z klibi aralığı 0-1 arasındadır. Bu durum, z değeri 0 olan nesnelerin kameraya en yakın, z değeri 1 olan nesnelerin ise en uzak olduğu anlamına gelir.

WebGL ve WebGPU'da Z klip alanı aralıklarını gösteren görsel.
WebGL ve WebGPU'da Z klip alanı aralıkları.

WebGL, Y ekseninin yukarıda, Z ekseninin de görüntüleyiciye doğru olduğu OpenGL kuralını kullanır. WebGPU, Y ekseninin aşağıda, Z ekseninin ise ekranın dışında olduğu Metal yöntemini kullanır. Y ekseni yönünün framebuffer koordinatı, görüntü alanı koordinatı ve parça/piksel koordinatında aşağıda olduğuna dikkat edin. Klip alanında, Y ekseni yönü WebGL'deki gibi yukarıdadır.

Teşekkür

Bu makaleyi inceledikleri için Corentin Wallez, Gregg Tavares, Stephen White, Ken Russell ve Rachel Andrew'a teşekkür ederiz.

Ayrıca, WebGPU ile WebGL arasındaki farklılıkları ayrıntılı bir şekilde incelemek için WebGPUFundamentals.org sitesini ziyaret etmenizi de öneririz.