WebGL'den WebGPU'ya

François Beaufort
François Beaufort

Bir WebGL geliştiricisi olarak, modern grafik API'lerinin ilerlemelerini web'e getiren WebGL'nin halefi WebGPU'yu kullanmaya başlamak konusunda hem korkmuş hem de heyecanlı olabilirsiniz.

WebGL ve WebGPU'nun birçok temel kavrama sahip olduğunu bilmek rahatlatıcıdır. 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, WebGPU ise işlem gölgelendiricilerini destekler. WebGL OpenGL Gölgelendirme Dili (GLSL), WebGPU ise WebGPU Gölgelendirme Dili (WGSL) kullanır. İki dil farklı olsa da temel kavramlar çoğunlukla aynıdır.

Bunu göz önünde bulundurarak, başlangıç yapmanıza yardımcı olmak için bu makalede WebGL ve WebGPU arasındaki bazı farklılıklar vurgulanmaktadır.

Küresel durum

WebGL'nin çok fazla küresel 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 durum etkin kalır. WebGL'deki global durum, genel bir ayarı değiştirmeyi unutmak kolay olduğu için önemli bir 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 etmeleri gerekir. Bu nedenle, genel durum kod paylaşımını zorlaştırır.

WebGPU, durum bilgisiz bir API'dir ve genel bir durumu sürdürmez. Bunun yerine, WebGL'de küresel olan tüm oluşturma durumunu kapsüllemek için 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 istiyorsanız başka bir ardışık düzen oluşturmanız gerekir. WebGPU ayrıca, komutları toplu olarak düzenlemek ve bunları kaydedildikleri sırayla yürütmek için komut kodlayıcıları kullanır. Bu, uygulamanın nesneler üzerinden tek bir geçişte her ışığın gölge haritası için bir tane olmak üzere birden fazla komut akışını kaydedebildiği gölge eşlemede yararlıdır.

Özetlemek gerekirse, WebGL'nin küresel durum modeli güçlü, derlenebilir kitaplıklar ve uygulamalar oluşturmayı zorlaştırır ve kırılgan hale getirirken WebGPU, geliştiricilerin GPU'ya komut gönderirken takip etmesi gereken durum miktarını önemli ölçüde azaltmıştır.

Başka senkronizasyon yok

GPU'larda, komutların gönderilmesi ve eşzamanlı olarak beklemek genellikle verimli olmaz. Aksi halde, ardışık düzen temizlenebilir ve 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'de geçerlidir.

Örneğin WebGL'de, gl.getError() işlevinin çağrılması için JavaScript işleminden, GPU işlemine ve son işleme kadar eşzamanlı bir IPC gerekir. Bu durum, iki işlem iletişim kurarken CPU tarafında baloncuk 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ş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ş gibi görünür. Hatayı yalnızca eşzamansız olarak keşfedebilirsiniz. Bu tasarım, işlemler arası iletişimin balonsuz şekilde yapılmasını sağlar ve uygulamalara güvenilir performans sunar.

Gölgelendiricileri hesapla

Compute gölgelendiriciler, genel amaçlı hesaplamalar yapmak için GPU'da çalışan programlardır. Yalnızca WebGPU'da kullanılabilirler, WebGL'de kullanılamazlar.

Köşe ve parça gölgelendiricilerin aksine, bunlar grafik işlemeyle sınırlı değildir ve makine öğrenimi, fizik simülasyonu ve bilimsel bilgi işlem gibi çok çeşitli görevler için kullanılabilir. Compute gölgelendiriciler, yüzlerce hatta binlerce iş parçacığı tarafından paralel olarak yürütülür. Bu da büyük veri kümelerinin işlenmesi için son derece verimli bir yöntemdir. WebGPU hakkındaki bu kapsamlı makalede GPU hesaplaması ve daha ayrıntılı bilgi edinin.

Video karesi işleme

JavaScript ve WebAssembly kullanarak video karelerini işlemenin bazı dezavantajları vardır: GPU belleğinden CPU belleğine veri kopyalama maliyeti ve çalışanlar ile CPU iş parçacıkları ile mümkün olan sınırlı paralellik. WebGPU'da bu tür sınırlamalar yoktur. Bu nedenle, WebCodecs API'siyle sıkı entegrasyonu sayesinde video karelerini işlemek için mükemmel bir seçenektir.

Aşağıdaki kod snippet'i, bir VideoFrame'in WebGPU'da harici doku olarak nasıl içe aktarılacağını ve işleneceğini göstermektedir. 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şmeyebilecek tüm GPU'ların makul ve en düşük ortak paydasını döndürür. WebGPU, geliştiricilerin cihaz sınırları istemesini zorunlu kılarak uygulamaların mümkün olduğunca çok cihazda çalışmasını sağlar.

Kanvas hazırlama

Bir WebGL bağlamı oluşturduktan ve alfa, antialias, colorSpace, depth, applyDrawingBuffer veya stencil gibi bağlam özelliklerini sağladıktan sonra WebGL, tuvali otomatik olarak yönetir.

Diğer yandan, WebGPU için tuvali sizin yönetmeniz gerekir. Örneğin, WebGPU'da anti yumuşatma sağlamak için çoklu örnek doku oluşturur ve bu dokuyu oluşturursunuz. Ardından, çoklu örnek dokuyu normal bir dokuya çözümler ve bu dokuyu zemine çizersiniz. Bu manuel yönetim, tek bir GPUDevice nesnesinden istediğiniz kadar tuval çıkışı yapmanıza olanak tanır. Öte yandan, WebGL her tuval için yalnızca bir bağlam oluşturabilir.

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

Ayrıca, tarayıcıların şu anda sayfa başına WebGL tuvali sayısıyla ilgili bir sınırı vardır. Bu yazının yazıldığı sırada Chrome ve Safari aynı anda en fazla 16 WebGL kanvasını kullanabiliyor. Firefox bu kanvasların en fazla 200 tanesini oluşturabilir. Diğer yandan, sayfa başına WebGPU tuvali sayısıyla ilgili 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 (soldan sağa) maksimum WebGL tuvali sayısı - demo.

Faydalı hata mesajları

WebGPU, API'den döndürülen her mesaj için bir çağrı yığını sağlar. Bu, hatanın kodunuzda nerede oluştuğunu hızlı bir şekilde görebileceğiniz anlamına gelir. Bu, hataları ayıklamak ve hataları düzeltmek için faydalı bir özelliktir.

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

WebGPU, her bir WebGPU nesnesi için özel 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 adında tek tip bir değişken tanımlayabilir ve gl.getUniformLocation(program, 'myUniform') kullanarak konumunu alabilirsiniz. Tek tip değişkenin adını yanlış yazarsanız hata aldığınız için bu özellik kullanışlıdır.

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

Mipmap oluşturma

WebGL'de bir doku için 0 mip seviyesinde bir değer oluşturup ardından gl.generateMipmap() komutunu çağırabilirsiniz. Ardından WebGL, diğer tüm MIp düzeylerini sizin için oluşturur.

WebGPU'da, MIpmaps'i kendiniz oluşturmanız gerekir. Bu işlemi yapan yerleşik bir işlev yoktur. Karar hakkında daha fazla bilgi edinmek için spesifikasyon tartışmalarını inceleyin. Mipmaps oluşturmak için webgpu-utils gibi kullanışlı kitaplıkları kullanabilir veya bunu kendiniz nasıl yapacağınızı öğrenebilirsiniz.

Depolama arabellekleri ve depolama dokuları

Tek tip arabellekler hem WebGL hem de WebGPU tarafından desteklenir ve gölgelendiricilere sınırlı boyutta sabit parametreler 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 arabellek verileri, tek tip arabelleklerden çok daha büyük olabilir. Teknik açıdan tek tip arabellek bağlamalarının boyutunun en fazla 64 KB olabileceği (bkz. maxUniformBufferBindingSize) olsa da depolama arabellek bağlamasının maksimum boyutu WebGPU'da en az 128 MB'tır (bkz. maxStorageBufferBindingSize).

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

  • Depolama arabellek 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 tek tip arabellekler için depolama arabellekleri olan dokularla ilgilidir. Normal dokulardan daha esnektir ve rastgele erişimle yazma işlemlerini (ve gelecekte de okumaları) desteklerler.

Arabellek ve doku değişiklikleri

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

WebGPU'da arabellekler ve dokular sabittir. Yani oluşturulduktan sonra boyut, kullanım veya biçimi değiştirilemez. Yalnızca içeriğini değiştirebilirsiniz.

Alan kuralı farklılıkları

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

WebGL ve WebGPU'daki Z klip alanı aralıklarının resmi.
WebGL ve WebGPU'daki Z klip alanı aralıkları.

WebGL, Y ekseninin yukarı ve Z ekseninin görüntüleyiciye doğru olduğu OpenGL kuralını kullanır. WebGPU, Y ekseninin aşağı doğru, Z ekseninin ise ekran dışında olduğu Metal kuralını kullanır. Y ekseni yönünün çerçeve arabelleği koordinatında, görüntü alanı koordinatında ve parça/piksel koordinatında aşağıya doğru olduğuna dikkat edin. Klip alanında, Y ekseninin yönü WebGL'deki gibi yukarılardadı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 ve WebGL arasındaki farklılıkların ayrıntılı bir şekilde incelenmesi için WebGPUFundamentals.org'u da öneririz.