WebGL से WebGPU तक

फ्रांकोइस ब्यूफ़ोर्ट
फ्रांकोइस ब्यूफ़ोर्ट

WebGL डेवलपर होने के नाते, आप WebGL के उत्तराधिकारी, WebGPU का इस्तेमाल करने से घबरा सकते हैं. साथ ही, WebGPU की मदद से, वेब पर मॉडर्न ग्राफ़िक्स एपीआई की बेहतर सुविधाएं उपलब्ध कराती हैं.

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

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

ग्लोबल स्टेट

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

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

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

और ज़्यादा सिंक न करें

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

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

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

शेडर कंप्यूट करें

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

वर्टेक्स और फ़्रैगमेंट शेडर से अलग, ये ग्राफ़िक प्रोसेसिंग तक सीमित नहीं हैं और इनका इस्तेमाल मशीन लर्निंग, फ़िज़िक्स सिम्युलेशन, और साइंटिफ़िक कंप्यूटिंग जैसे कई कामों के लिए किया जा सकता है. कंप्यूट शेडर को सैकड़ों या हज़ारों थ्रेड के साथ-साथ चलाया जाता है. इस वजह से, वे बड़े डेटासेट को प्रोसेस करने में बेहतर तरीके से मदद करते हैं. जीपीयू कंप्यूट के बारे में ज़्यादा जानकारी पाने के साथ-साथ, 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 कॉन्टेक्स्ट बनाने और ऐल्फ़ा, एंटीएलिया, colorSpace, Deep, प्रिज़र्व ड्रॉइंगबफ़र या स्टेंसिल जैसे प्रसंग एट्रिब्यूट उपलब्ध कराने के बाद, WebGL अपने-आप कैनवस को मैनेज कर देता है.

दूसरी ओर, 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 देने की सुविधा भी देता है. इसके बाद, ब्राउज़र इस लेबल का इस्तेमाल जीपीयू एरर मैसेज, कंसोल की चेतावनियों, और ब्राउज़र डेवलपर टूल में करता है.

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

WebGL में, बहुत सी चीज़ें नाम से जुड़ी होती हैं. उदाहरण के लिए, आप जीएलएसएल में 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 तक होती है. इसका मतलब है कि 0 वाले z मान वाले ऑब्जेक्ट कैमरे के सबसे नज़दीक होते हैं, जबकि 1 के z मान वाले ऑब्जेक्ट सबसे दूर होते हैं.

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

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

स्वीकार हैं

इस लेख को पढ़ने के लिए कोरेंटिन वॉलेज़, ग्रेग तवारिस, स्टीफ़न व्हाइट, केन रसेल, और रेचल एंड्रू का धन्यवाद.

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