WebGL'den WebGPU'ya

François Beaufort
François Beaufort

WebGL geliştiricisi olarak, modern grafik API'lerinin avantajlarını web'e getiren WebGL'nin halefi WebGPU'yu kullanmaya başlamak hem korkutucu hem de heyecan verici olabilir.

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ıza olanak tanır. WebGL, köşe ve parça gölgelendiricileri desteklerken WebGPU, hesaplama gölgelendiricilerini de destekler. WebGL, OpenGL Gölgelendirme Dili'ni (GLSL) kullanırken WebGPU, WebGPU Gölgelendirme Dili'ni (WGSL) kullanır. İki dil farklı olsa da temel kavramlar çoğunlukla aynıdır.

Bu makalede, WebGL ve WebGPU arasındaki bazı farklar vurgulanarak başlangıç yapmanıza yardımcı olunmaktadır.

Global durum

WebGL'de çok sayıda genel durum vardır. Bazı ayarlar (ör. hangi dokuların ve arabelleklerin bağlanacağı) 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. WebGL'deki genel durum, genel bir ayarı değiştirmeyi unutmanın kolay olması nedeniyle önemli bir hata kaynağıdır. Ayrıca, geliştiricilerin global durumu yanlışlıkla kodun diğer bölümlerini etkileyecek şekilde değiştirmemeye dikkat etmesi gerektiğinden global durum, kod paylaşımını zorlaştırır.

WebGPU, durum bilgisi olmayan bir API'dir ve genel bir durum bilgisini korumaz. Bunun yerine, WebGL'de genel olan tüm oluşturma durumunu kapsayacak şekilde ardışık düzen kavramını kullanır. Bir ardışık düzen, kullanılacak harmanlama, topoloji ve özellikler gibi bilgileri içerir. Ardışık düzen sabittir. Bazı ayarları değiştirmek istiyorsanız başka bir ardışık düzen oluşturmanız gerekir. WebGPU, komutları gruplandırmak 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 ışık gölge haritası için bir tane olmak üzere birden fazla komut akışı kaydedebildiği gölge haritalama işleminde yararlıdır.

Özetlemek gerekirse, WebGL'in genel durum modeli, güçlü ve birleştirilebilir kitaplıklar ile uygulamalar oluşturmayı zor ve kırılgan hale getirdiğinden WebGPU, geliştiricilerin GPU'ya komut gönderirken takip etmesi gereken durum miktarını önemli ölçüde azaltmıştır.

Senkronizasyon artık yok

GPU'larda komut gönderip bunları senkronize olarak beklemek genellikle verimli değildir. Bu işlem, ardışık düzeni temizleyip kabarcıklar oluşmasına 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'de geçerlidir.

Örneğin, WebGL'de gl.getError() çağrısı için JavaScript işleminden GPU işlemine ve geriye doğru senkronize bir IPC gerekir. Bu durum, iki işlem iletişim kurarken CPU tarafında bir balon oluşmasına neden olabilir.

Bu baloncukları önlemek için WebGPU tamamen eşzamansız olacak şekilde tasarlanmıştır. Hata modeli ve diğer tüm işlemler eşzamanlı olarak gerçekleşmez. Örneğin, bir doku oluşturduğunuzda doku aslında bir hata olsa bile işlem hemen başarılı görünür. Hatayı yalnızca eşzamansız olarak keşfedebilirsiniz. Bu tasarım, işlemler arası iletişimi kabarcıksız tutar ve uygulamalara güvenilir performans sağlar.

İşlem gölgelendiricileri

Hesaplama gölgelendiricileri, genel amaçlı hesaplamalar yapmak için GPU'da çalışan programlardır. Bunlar WebGL'de değil, yalnızca WebGPU'de kullanılabilir.

Nokta ve parçacık gölgelendiricilerden farklı olarak, grafik işlemeyle sınırlı değildir ve makine öğrenimi, fizik simülasyonu ve bilimsel hesaplama gibi çeşitli görevler için kullanılabilir. Bilgisayar gölgelendiricileri yüzlerce hatta binlerce iş parçacığı tarafından paralel olarak yürütülür. Bu da onları büyük veri kümelerini işleme konusunda son derece verimli kılar. GPU hesaplama hakkında daha fazla bilgi edinmek için WebGPU ile ilgili bu kapsamlı makaleyi inceleyin.

Video karesi işleme

JavaScript ve WebAssembly'i kullanarak video karelerini işlemenin bazı dezavantajları vardır: Verileri GPU belleğinden CPU belleğine kopyalamanın maliyeti ve çalışanlar ile CPU iş parçacıkları kullanılarak elde edilebilecek sınırlı paralellik. WebGPU bu sınırlamalara sahip değildir. Bu sayede WebCodecs API ile sıkı entegrasyonu sayesinde video karelerini işlemek için mükemmel bir seçimdir.

Aşağıdaki kod snippet'inde, bir VideoFrame'in WebGPU'da harici bir doku olarak nasıl içe aktarılacağı ve işlenmesi 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, limits istemenizi zorunlu kılar. Varsayılan olarak requestDevice(), fiziksel cihazın donanım özellikleriyle eşleşmeyen bir GPUDevice döndürür. Bunun yerine, tüm GPU'ların makul ve en düşük ortak paydasını döndürür. WebGPU, geliştiricilerin cihaz sınırlarını istemesini zorunlu kılarak uygulamaların mümkün olduğunca çok cihazda çalışmasını sağlar.

Tuvalleri işleme

WebGL bağlamı oluşturduktan ve alpha, antialias, colorSpace, depth, preserveDrawingBuffer veya stencil gibi bağlam özellikleri sağladıktan sonra WebGL, tuvali otomatik olarak yönetir.

Öte yandan WebGPU, kanvası kendinizin yönetmenizi gerektirir. Örneğin, WebGPU'da kenar yumuşatma elde etmek için çok örnekli bir doku oluşturur ve bu dokuda oluşturma işlemi yaparsınız. Ardından, çok örnekli dokuyu normal bir dokuya çözer ve bu dokuyu tuvale çizersiniz. Bu manuel yönetim, tek bir GPUDevice nesnesinden istediğiniz kadar kanvas oluşturmanıza olanak tanır. Buna karşılık WebGL, kanvas başına yalnızca bir bağlam oluşturabilir.

WebGPU Çoklu Tuvaller demosuna göz atın.

Ayrıca, tarayıcılarda şu anda sayfa başına WebGL kanvası sayısıyla ilgili bir sınır vardır. Bu makalenin yazıldığı sırada Chrome ve Safari aynı anda en fazla 16 WebGL kanvası kullanabilirken Firefox 200'e kadar kanvas oluşturabilir. Öte yandan, sayfa başına WebGPU kanvası sayısıyla ilgili bir sınırlama yoktur.

Safari, Chrome ve Firefox tarayıcılarında maksimum sayıda WebGL kanvası içeren ekran görüntüsü
Safari, Chrome ve Firefox'taki maksimum WebGL kanvası 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, hata ayıklama ve hataları düzeltme konusunda yararlı bir özelliktir.

WebGPU hata mesajları, çağrı yığınının yanı sıra kolay anlaşılır ve uygulanabilirdir. Hata mesajları genellikle hatanın açıklamasını ve hatanın nasıl düzeltileceğine dair öneriler içerir.

WebGPU, her 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 bağlanır. Örneğin, GLSL'de myUniform adlı bir tekdüze değişken tanımlayabilir ve gl.getUniformLocation(program, 'myUniform') kullanarak konumunu alabilirsiniz. Bu, üniforma değişkeninin adını yanlış yazarsanız hata almanız nedeniyle kullanışlıdır.

Öte yandan WebGPU'de her şey tamamen bayt ofseti veya dizine (genellikle konum olarak adlandırılır) bağlıdır. WGSL ve JavaScript'teki kod konumlarını senkronize tutmanın sorumluluğu size aittir.

Mipmap oluşturma

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

WebGPU'de mipmap'leri kendiniz oluşturmanız gerekir. Bunu yapacak yerleşik bir işlev yoktur. Karar hakkında daha fazla bilgi edinmek için özellik tartışmasına göz atın. MIP haritası oluşturmak için webgpu-utils gibi kullanışlı kitaplıkları kullanabilir veya bunu kendi başınıza nasıl yapacağınızı öğrenebilirsiniz.

Depolama tamponları ve depolama dokuları

Tekdüzen tamponlar hem WebGL hem de WebGPU tarafından desteklenir ve sınırlı boyuttaki sabit parametreleri gölgelendiricilere iletmenize olanak tanır. Tekdüze arabelleğe çok benzeyen depolama arabellekleri yalnızca WebGPU tarafından desteklenir ve tekdüze arabelleğe kıyasla daha güçlü ve esnektir.

  • Gölgelendiricilere iletilen depolama arabelleklerindeki veriler, tekdüze arabelleklerden çok daha büyük olabilir. Spesifikasyonda, tekdüzen arabellek bağlamalarının boyutunun en fazla 64 KB olabileceği belirtilse de (maxUniformBufferBindingSize bölümüne bakın) WebGPU'da depolama arabellek bağlamasının maksimum boyutu en az 128 MB'tır (maxStorageBufferBindingSize bölümüne bakın).

  • Depolama arabellekleri yazılabilirdir ve bazı atomik işlemleri destekler. Tekdüzen arabellekler ise yalnızca salt okunurdur. Bu sayede yeni algoritma sınıfları uygulanabilir.

  • Depolama arabellek bağlamaları, daha esnek algoritmalar için çalışma zamanında boyutlandırılmış dizileri destekler. Bununla birlikte, gölgelendiricide tek tip arabellek dizisi boyutları sağlanmalıdır.

Depolama alanı dokuları yalnızca WebGPU'de desteklenir ve dokular için depolama alanı arabelleklerinin tekdüzen arabelleklere olan benzerliğidir. Normal dokulardan daha esnektirler ve rastgele erişim yazma işlemlerini (ve gelecekte okuma işlemlerini de) desteklerler.

Arabellek ve doku değişiklikleri

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

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

Alan sözleşmesi farklılıkları

WebGL'de Z klip alanı aralığı -1 ile 1 arasındadır. WebGPU'de Z kırpma alanı aralığı 0 ile 1 arasındadır. Bu, 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'daki Z kırpma alanı aralıklarını gösteren görsel.
WebGL ve WebGPU'daki Z klip alanı aralıkları.

WebGL, Y ekseninin yukarı ve Z ekseninin izleyiciye doğru olduğu OpenGL kuralını kullanır. WebGPU, Y ekseninin aşağı ve Z ekseninin ekranın dışında olduğu Metal kuralını kullanır. Y ekseni yönünün, çerçeve ara belleği koordinatında, görüntü alanı koordinatında ve parça/piksel koordinatında aşağı olduğunu unutmayın. Klip alanında, Y ekseni yönü WebGL'de olduğu gibi yukarı doğrudur.

Teşekkür ederiz

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

WebGPU ile WebGL arasındaki farklara ayrıntılı bir şekilde göz atmak için WebGPUFundamentals.org adresini de ziyaret edebilirsiniz.