WebGL से WebGPU तक

François Beaufort
François Beaufort

WebGL डेवलपर के रूप में, आपको WebGPU का इस्तेमाल शुरू करने में घबराहट और खुशी हो सकती है. WebGPU, WebGL का सबसे सही वर्शन है, जो वेब पर मॉडर्न ग्राफ़िक्स एपीआई को बेहतर बनाता है.

हमें यह जानकर भरोसा होता है कि WebGL और WebGPU के कई मुख्य सिद्धांत हैं. दोनों एपीआई की मदद से, GPU पर शेडर नाम के छोटे प्रोग्राम चलाए जा सकते हैं. WebGL, वर्टिक्स और फ़्रैगमेंट शेडर के साथ काम करता है. वहीं, WebGPU, कंप्यूट शेडर के साथ भी काम करता है. WebGL, OpenGL Shading Language (GLSL) का इस्तेमाल करता है, जबकि WebGPU, WebGPU Shading Language (WGSL) का इस्तेमाल करता है. हालांकि, दोनों भाषाएं अलग-अलग हैं, लेकिन इनमें मौजूद कॉन्सेप्ट ज़्यादातर एक जैसे हैं.

इस बात को ध्यान में रखते हुए, यह लेख WebGL और WebGPU के बीच के कुछ अंतरों को हाइलाइट करता है, ताकि आपको इस्तेमाल शुरू करने में मदद मिल सके.

ग्लोबल स्टेट

WebGL में बहुत सारी ग्लोबल स्टेटस होती हैं. कुछ सेटिंग सभी रेंडरिंग ऑपरेशन पर लागू होती हैं, जैसे कि कौनसी टेक्सचर और बफ़र बाउंड हैं. इस ग्लोबल स्टेट को अलग-अलग एपीआई फ़ंक्शन को कॉल करके सेट किया जाता है. यह स्थिति तब तक लागू रहती है, जब तक इसे बदला नहीं जाता. WebGL में ग्लोबल स्थिति, गड़बड़ियों का मुख्य स्रोत है, क्योंकि ग्लोबल सेटिंग को बदलना भूलना आसान हो जाता है. इसके अलावा, ग्लोबल स्टेट की वजह से कोड शेयर करना मुश्किल हो जाता है. ऐसा इसलिए, क्योंकि डेवलपर को इस बात का ध्यान रखना पड़ता है कि ग्लोबल स्टेट में ऐसा बदलाव न हो जिससे कोड के दूसरे हिस्सों पर असर पड़े.

WebGPU एक स्टेटलेस एपीआई है और यह ग्लोबल स्टेट को मैनेज नहीं करता. इसके बजाय, यह WebGL में वैश्विक रूप से मौजूद रेंडर करने की सभी स्थिति को एनकैप्सुलेट करने के लिए, पाइपलाइन के सिद्धांत का इस्तेमाल करता है. पाइपलाइन में, ब्लेंडिंग, टोपोलॉजी, और एट्रिब्यूट के इस्तेमाल से जुड़ी जानकारी होती है. पाइपलाइन में बदलाव नहीं किया जा सकता. अगर आपको कुछ सेटिंग में बदलाव करना है, तो आपको एक और पाइपलाइन बनानी होगी. WebGPU, निर्देशों को एक साथ बैच करने और उन्हें उसी क्रम में लागू करने के लिए, कंडेम एन्कोडर का भी इस्तेमाल करता है जिस क्रम में उन्हें रिकॉर्ड किया गया था. यह शैडो मैपिंग में काम का है. उदाहरण के लिए, जहां ऑब्जेक्ट के ऊपर एक ही पास से ऐप्लिकेशन कई कमांड स्ट्रीम रिकॉर्ड कर सकता है. जैसे, हर लाइट के शैडो मैप के लिए एक.

संक्षेप में, WebGL के ग्लोबल स्टेट मॉडल ने मज़बूत, कंपोज़ेबल लाइब्रेरी और ऐप्लिकेशन बनाने को मुश्किल और नाज़ुक बना दिया है, WebGPU ने जीपीयू को निर्देश भेजते समय, डेवलपर के लिए ज़रूरी स्थिति को काफ़ी कम कर दिया.

अब और सिंक न करें

आम तौर पर, जीपीयू पर, निर्देश भेजने और सिंक्रोनस रूप से उनका इंतज़ार करने में मुश्किल होती है. ऐसा इसलिए, क्योंकि इससे पाइपलाइन साफ़ हो सकती है और बबल बन सकता है. यह बात खास तौर पर WebGPU और WebGL के लिए ज़्यादा सही है. ये कई प्रोसेस वाले आर्किटेक्चर का इस्तेमाल करते हैं. इसमें GPU ड्राइवर, JavaScript से अलग प्रोसेस में चलता है.

उदाहरण के लिए, WebGL में gl.getError() को कॉल करने के लिए, JavaScript प्रोसेस से जीपीयू प्रोसेस तक सिंक्रोनस IPC की ज़रूरत होती है. दोनों प्रोसेस के बीच कम्यूनिकेशन होने की वजह से, सीपीयू साइड पर बबल बन सकता है.

इन बबल से बचने के लिए, WebGPU को पूरी तरह से असाइनोक्रोनस बनाया गया है. गड़बड़ी का मॉडल और अन्य सभी कार्रवाइयां, एक साथ नहीं होतीं. उदाहरण के लिए, जब कोई टेक्सचर बनाया जाता है, तो कार्रवाई तुरंत सफल होती है. भले ही, टेक्सचर असल में कोई गड़बड़ी हो. गड़बड़ी का पता सिर्फ़ असिंक्रोनस तरीके से लगाया जा सकता है. इस डिज़ाइन की मदद से, क्रॉस-प्रोसेस कम्यूनिकेशन को बुलबले से मुक्त रखा जाता है. साथ ही, ऐप्लिकेशन की परफ़ॉर्मेंस बेहतर बनती है.

कंप्यूट शेडर

कंप्यूट शेडर ऐसे प्रोग्राम होते हैं जो अलग-अलग कामों के लिए इस्तेमाल होने वाले कंप्यूटेशन के लिए जीपीयू पर चलते हैं. ये सिर्फ़ WebGPU में उपलब्ध हैं, WebGL में नहीं.

वेरटेक्स और फ़्रैगमेंट शेडर के उलट, ये सिर्फ़ ग्राफ़िक्स प्रोसेसिंग तक सीमित नहीं हैं. इनका इस्तेमाल कई तरह के टास्क के लिए किया जा सकता है. जैसे, मशीन लर्निंग, फ़िज़िक्स सिम्युलेशन, और साइंटिफ़िक कंप्यूटिंग. कंप्यूट शेडर को सैकड़ों या हज़ारों थ्रेड के साथ-साथ चलाया जाता है. इस वजह से, वे बड़े डेटासेट को प्रोसेस कर सकते हैं. GPU कंप्यूट के बारे में जानें. साथ ही, WebGPU के बारे में ज़्यादा जानकारी देने वाला यह लेख पढ़ें.

वीडियो फ़्रेम को प्रोसेस करना

JavaScript और WebAssembly का इस्तेमाल करके, वीडियो फ़्रेम को प्रोसेस करने में कुछ खामियां हैं. जैसे, जीपीयू मेमोरी से सीपीयू मेमोरी में डेटा कॉपी करने का खर्च. साथ ही, वर्कर और सीपीयू थ्रेड की मदद से मिल सकने वाली सीमित समानता. WebGPU में ऐसी सीमाएं नहीं हैं, क्योंकि WebCodecs API के साथ इसका बेहतरीन इंटिग्रेशन होने की वजह से यह वीडियो फ़्रेम प्रोसेस करने के लिए सबसे सही विकल्प है.

नीचे दिए गए कोड स्निपेट में, WebGPU में VideoFrame को बाहरी टेक्सचर के तौर पर इंपोर्ट करने और उसे प्रोसेस करने का तरीका बताया गया है. इस डेमो को आज़माएं.

// 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
}

डिफ़ॉल्ट रूप से ऐप्लिकेशन को एक डिवाइस से दूसरे डिवाइस पर ले जाने की सुविधा

WebGPU, limits का अनुरोध करने के लिए मजबूर करता है. डिफ़ॉल्ट रूप से, requestDevice() एक ऐसा GPUDevice दिखाता है जो हो सकता है कि फ़िज़िकल डिवाइस के हार्डवेयर की क्षमताओं से मेल न खाए. हालांकि, यह सभी जीपीयू के लिए एक सही और कम से कम कॉमन डेनोमिनेटर होता है. डेवलपर को डिवाइस की सीमाओं का अनुरोध करने की ज़रूरत होती है. इससे WebGPU यह पक्का करता है कि ऐप्लिकेशन ज़्यादा से ज़्यादा डिवाइसों पर चल सकें.

कैनवस मैनेज करना

WebGL आपके द्वारा WebGL संदर्भ बनाए जाने और संदर्भ विशेषताएं जैसे अल्फ़ा, एंटीएलिया, रंगस्पेस, गहराई, प्रिज़र्विंगBuffer या स्टेन्सिल देने के बाद अपने आप कैनवस प्रबंधित कर लेता है.

दूसरी ओर, WebGPU के लिए ज़रूरी है कि आप कैनवस को खुद मैनेज करें. उदाहरण के लिए, WebGPU में एंटी-एलियासिंग पाने के लिए, आपको एक मल्टीसैंपल टेक्सचर बनाना होगा और उसे रेंडर करना होगा. इसके बाद, मल्टीसैंपल टेक्सचर को सामान्य टेक्सचर में बदलें और उस टेक्सचर को कैनवस पर खींचें. मैन्युअल मैनेजमेंट की मदद से, एक ही GPUDevice ऑब्जेक्ट से जितने चाहें उतने कैनवस पर आउटपुट किया जा सकता है. इसके उलट, WebGL हर कैनवस के लिए सिर्फ़ एक कॉन्टेक्स्ट बना सकता है.

WebGPU के कई कैनवस के डेमो को देखें.

एक और बात, ब्राउज़र में फ़िलहाल हर पेज के लिए WebGL कैनवस की संख्या सीमित है. फ़िलहाल, Chrome और Safari एक साथ सिर्फ़ 16 WebGL कैनवस का इस्तेमाल कर सकते हैं. वहीं, Firefox में 200 कैनवस बनाए जा सकते हैं. वहीं, हर पेज पर WebGPU कैनवस की संख्या पर कोई सीमा नहीं है.

Safari, Chrome, और Firefox ब्राउज़र में WebGL कैनवस की ज़्यादा से ज़्यादा संख्या दिखाने वाला स्क्रीनशॉट
Safari, Chrome, और Firefox में WebGL कैनवस की ज़्यादा से ज़्यादा संख्या (बाएं से दाएं) - डेमो.

गड़बड़ी के बारे में मददगार मैसेज

WebGPU, एपीआई से दिखाए जाने वाले हर मैसेज के लिए एक कॉल स्टैक उपलब्ध कराता है. इसका मतलब है कि आपके पास यह देखने का विकल्प है कि आपके कोड में गड़बड़ी कहां हुई है. यह जानकारी, गड़बड़ियों को डीबग करने और उन्हें ठीक करने में काम की होती है.

WebGPU में गड़बड़ी के मैसेज होने पर, कॉल स्टैक की सुविधा मिलने के साथ-साथ उन्हें समझना भी आसान होता है. साथ ही, इन मैसेज पर कार्रवाई की जा सकती है. आम तौर पर, गड़बड़ी के मैसेज में गड़बड़ी की जानकारी और उसे ठीक करने के सुझाव शामिल होते हैं.

WebGPU की मदद से, हर WebGPU ऑब्जेक्ट के लिए पसंद के मुताबिक label भी दिया जा सकता है. इसके बाद, ब्राउज़र इस लेबल का इस्तेमाल GPUError मैसेज, कंसोल की चेतावनियों, और ब्राउज़र डेवलपर टूल में करता है.

नामों से इंडेक्स तक

WebGL में, कई चीज़ें नाम से जुड़ी होती हैं. उदाहरण के लिए, GLSL में myUniform नाम का यूनिफ़ॉर्म वैरिएबल तय किया जा सकता है और gl.getUniformLocation(program, 'myUniform') का इस्तेमाल करके उसकी जगह की जानकारी पाई जा सकती है. यह उस समय सबसे काम आता है, जब एक जैसे वैरिएबल का नाम गलत टाइप किया जाता है और आपको गड़बड़ी का मैसेज मिलता है.

दूसरी ओर, WebGPU में, सब कुछ पूरी तरह से बाइट ऑफ़सेट या इंडेक्स से जुड़ा होता है. इसे अक्सर जगह कहा जाता है. WGSL और JavaScript में कोड की जगहों को सिंक रखना आपकी ज़िम्मेदारी है.

मिपमैप जनरेट करना

WebGL में, टेक्सचर का लेवल 0 एमआईपी बनाया जा सकता है और फिर gl.generateMipmap() को कॉल किया जा सकता है. इसके बाद, WebGL आपके लिए अन्य सभी मील लेवल जनरेट कर देगा.

WebGPU में आपको खुद ही मिपमैप जनरेट करने होंगे. ऐसा करने के लिए, कोई बिल्ट-इन फ़ंक्शन उपलब्ध नहीं है. फ़ैसले के बारे में ज़्यादा जानने के लिए, स्पेसिफ़िकेशन की चर्चा देखें. एमआईपीमैप जनरेट करने के लिए, webgpu-utils जैसी लाइब्रेरी का इस्तेमाल किया जा सकता है. इसके अलावा, खुद भी एमआईपीमैप जनरेट करने का तरीका सीखा जा सकता है.

स्टोरेज बफ़र और स्टोरेज टेक्सचर

एक जैसे बफ़र, WebGL और WebGPU, दोनों के साथ काम करते हैं. इनकी मदद से, शेडर को सीमित साइज़ के एक जैसे पैरामीटर भेजे जा सकते हैं. स्टोरेज बफ़र, यूनिफ़ॉर्म बफ़र से काफ़ी मिलते-जुलते हैं. ये सिर्फ़ WebGPU पर काम करते हैं. साथ ही, ये यूनिफ़ॉर्म बफ़र से ज़्यादा बेहतर और सुविधाजनक होते हैं.

  • शेडर को भेजा गया स्टोरेज बफ़र डेटा, यूनिफ़ॉर्म बफ़र से काफ़ी बड़ा हो सकता है. स्पेसिफ़िकेशन के मुताबिक, यूनिफ़ॉर्म बफ़र बाइंडिंग का साइज़ 64 केबी तक हो सकता है (maxUniformBufferBindingSize देखें). हालांकि, WebGPU में स्टोरेज बफ़र बाइंडिंग का ज़्यादा से ज़्यादा साइज़ कम से कम 128 एमबी होता है (maxStorageBufferBindingSize देखें).

  • स्टोरेज बफ़र में डेटा सेव किया जा सकता है और ये कुछ ऐटॉमिक ऑपरेशन में काम करते हैं. हालांकि, यूनिफ़ॉर्म बफ़र सिर्फ़ रीड-ओनली मोड में होते हैं. इससे, एल्गोरिदम की नई क्लास लागू की जा सकती हैं.

  • स्टोरेज बफ़र बाइंडिंग, ज़्यादा सुविधाजनक एल्गोरिदम के लिए रनटाइम साइज़ वाले ऐरे के साथ काम करती हैं. वहीं, यूनिफ़ॉर्म बफ़र ऐरे के साइज़ को शेडर में उपलब्ध कराना होता है.

स्टोरेज टेक्सचर सिर्फ़ WebGPU में काम करते हैं. ये टेक्सचर के लिए वैसे ही हैं जैसे स्टोरेज बफ़र, यूनिफ़ॉर्म बफ़र के लिए होते हैं. ये सामान्य टेक्सचर के मुकाबले ज़्यादा फ़्लेक्सिबल होते हैं. साथ ही, ये रैंडम ऐक्सेस राइटिंग (और आने वाले समय में रीडिंग) के साथ काम करते हैं.

बफ़र और टेक्सचर में बदलाव

WebGL में, बफ़र या टेक्स्चर बनाया जा सकता है. इसके बाद, gl.bufferData() और gl.texImage2D() का इस्तेमाल करके, किसी भी समय इसका साइज़ बदला जा सकता है.

WebGPU में, बफ़र और टेक्सचर में बदलाव नहीं किया जा सकता. इसका मतलब है कि वीडियो बनाने के बाद, उनके साइज़, इस्तेमाल या फ़ॉर्मैट में बदलाव नहीं किया जा सकता. आपके पास सिर्फ़ उनके कॉन्टेंट में बदलाव करने का विकल्प होता है.

स्पेस के कॉन्फ़्रेंस में अंतर

WebGL में, Z क्लिप स्पेस की रेंज -1 से 1 तक होती है. WebGPU में, Z क्लिप स्पेस की रेंज 0 से 1 तक होती है. इसका मतलब है कि z वैल्यू 0 वाले ऑब्जेक्ट, कैमरे के सबसे नज़दीक होते हैं. वहीं, z वैल्यू 1 वाले ऑब्जेक्ट, कैमरे से सबसे दूर होते हैं.

WebGL और WebGPU में Z क्लिप स्पेस रेंज का इलस्ट्रेशन.
WebGL और WebGPU में Z क्लिप स्पेस की रेंज.

WebGL, OpenGL कन्वेंशन का इस्तेमाल करता है. इसमें Y ऐक्सिस ऊपर की ओर और Z ऐक्सिस दर्शक की ओर होता है. WebGPU, Metal कन्वेंशन का इस्तेमाल करता है. इसमें Y ऐक्सिस नीचे की ओर और Z ऐक्सिस स्क्रीन से बाहर होता है. ध्यान दें कि फ़्रेमबफ़र कोऑर्डिनेट, व्यूपोर्ट कोऑर्डिनेट, और फ़्रैगमेंट/पिक्सल कोऑर्डिनेट में Y ऐक्सिस की दिशा नीचे की ओर होती है. क्लिप स्पेस में, Y ऐक्सिस की दिशा अब भी WebGL की तरह ऊपर की ओर है.

धन्यवाद

इस लेख की समीक्षा करने के लिए, Corentin Wallez, Gregg Tavares, Stephen White, Ken Russell, और Rachel Andrew का धन्यवाद.

हमारा सुझाव है कि WebGPU और WebGL के बीच के अंतर के बारे में ज़्यादा जानने के लिए, WebGPUFundamentals.org पर जाएं.