من WebGL إلى WebGPU

François Beaufort
François Beaufort

بصفتك مطوّر WebGL، قد تشعر بالخوف والتشويق في الوقت نفسه لبدء استخدام WebGPU، وهو البديل لواجهة WebGL الذي يقدّم ميزات واجهة برمجة تطبيقات الرسومات الحديثة إلى الويب.

من المطمئن معرفة أنّ WebGL وWebGPU يتشاركان العديد من المفاهيم الأساسية. تتيح لك كلتا واجهات برمجة التطبيقات تشغيل برامج صغيرة تُعرف باسم "برامج معالجة الألوان" على وحدة معالجة الرسومات. يتيح WebGL استخدام برامج تشويش رؤوس الأشكال وبرامج تشويش الأجزاء، بينما يتيح WebGPU أيضًا استخدام برامج تشويش العمليات الحسابية. يستخدم WebGL لغة OpenGL Shading Language (GLSL)، بينما يستخدم WebGPU لغة WebGPU Shading Language (WGSL). على الرغم من اختلاف اللغتَين، إلا أنّ المفاهيم الأساسية متشابهة في أغلب الأحيان.

مع أخذ ذلك في الاعتبار، تُبرز هذه المقالة بعض الاختلافات بين WebGL وWebGPU لمساعدتك في البدء.

الحالة العامة

يحتوي WebGL على الكثير من الحالات الشاملة. تنطبق بعض الإعدادات على جميع عمليات التقديم، مثل العناصر التي يتم ربطها بالمواد والعناصر المخزّنة مؤقتًا. يمكنك ضبط هذه الحالة العامة من خلال طلب وظائف مختلفة لواجهة برمجة التطبيقات، وتظل سارية إلى أن تغيّرها. إنّ الحالة العامة في WebGL هي مصدر رئيسي للأخطاء، لأنّه من السهل نسيان تغيير أحد الإعدادات العامة. بالإضافة إلى ذلك، تجعل الحالة العامة مشاركة الرمز البرمجي أمرًا صعبًا، لأنّ المطوّرين عليهم الحذر من تغيير الحالة العامة عن طريق الخطأ بطريقة تؤثّر في أجزاء أخرى من الرمز البرمجي.

‫WebGPU هي واجهة برمجة تطبيقات لا تعتمد على الحالة، ولا تحافظ على حالة عامة. بدلاً من ذلك، يستخدم مفهوم مسار العرض لتضمين جميع حالات العرض التي كانت عالمية في WebGL. يحتوي مسار الإحالة الناجحة على معلومات، مثل عمليات الدمج والطوبولوجيا والسمات التي يجب استخدامها. مسار الإحالة الناجحة غير قابل للتغيير. إذا أردت تغيير بعض الإعدادات، عليك إنشاء مسار إحالة ناجحة آخر. يستخدم WebGPU أيضًا برامج ترميز الأوامر لتجميع الأوامر معًا وتنفيذها بالترتيب الذي تم تسجيلها به. يكون ذلك مفيدًا في ميزة "تعيين الظلال"، على سبيل المثال، حيث يمكن للتطبيق تسجيل تيارات أوامر متعددة في تمريرة واحدة على الأجسام، واحدة لكل خريطة ظل للضوء.

باختصار، بما أنّ نموذج الحالة الشاملة في WebGL جعل إنشاء مكتبات وتطبيقات قوية وقابلة للتجميع أمرًا صعبًا وحساسًا، قلّل WebGPU بشكل كبير من مقدار الحالة التي يحتاج المطوّرون إلى تتبُّعها أثناء إرسال الأوامر إلى وحدة معالجة الرسومات.

إيقاف المزامنة

في وحدات معالجة الرسومات، لا يكون إرسال الأوامر والانتظار عليها بشكل متزامن عادةً مجديًا، لأنّ ذلك قد يؤدي إلى تنظيف مسار الإرسال وتسبب فقاعات. وينطبق ذلك بشكل خاص على WebGPU وWebGL اللذَين يستخدمان بنية متعددة العمليات مع تشغيل برنامج تشغيل وحدة معالجة الرسومات في عملية منفصلة عن JavaScript.

في WebGL، على سبيل المثال، يتطلّب استدعاء gl.getError() استخدام IPC متزامن من عملية JavaScript إلى عملية وحدة معالجة الرسومات والعكس. ويمكن أن يؤدي ذلك إلى حدوث فقاعة على جانب وحدة المعالجة المركزية أثناء تواصل العمليتين.

لتجنُّب هذه الفقاعات، تم تصميم WebGPU ليكون غير متزامن تمامًا. يتم تنفيذ نموذج الخطأ وجميع العمليات الأخرى بشكل غير متزامن. على سبيل المثال، عند إنشاء نسيج، يبدو أنّ العملية قد نجحت على الفور، حتى إذا كان النسيج خطأً في الواقع. لا يمكنك اكتشاف الخطأ إلا بشكل غير متزامن. يحافظ هذا التصميم على خلوّ عملية التواصل بين العمليات من أي مشاكل ويمنح التطبيقات أداءً موثوقًا.

أدوات تظليل الحوسبة

برامج تظليل الحوسبة هي برامج يتم تشغيلها على وحدة معالجة الرسومات لإجراء عمليات حسابية للأغراض العامة. ولا تتوفّر هذه الوظائف إلا في WebGPU، وليس في WebGL.

وعلى عكس برامج تشفير قمة الالتقاط وبرامج تشفير أجزاء الصورة، لا تقتصر هذه البرامج على معالجة الرسومات، ويمكن استخدامها لمجموعة كبيرة من المهام، مثل التعلّم الآلي ومحاكاة الفيزياء والحساب العلمي. يتم تنفيذ برامج shaders الحسابية بشكل موازٍ من خلال مئات أو حتى آلاف سلاسل المهام، ما يجعلها فعالة جدًا في معالجة مجموعات البيانات الكبيرة. اطّلِع على مزيد من المعلومات عن المعالجة باستخدام وحدة معالجة الرسومات ومزيد من التفاصيل في هذه المقالة الشاملة عن WebGPU.

معالجة إطارات الفيديو

تتضمن معالجة لقطات الفيديو باستخدام JavaScript وWebAssembly بعض العيوب، مثل تكلفة نسخ البيانات من ذاكرة وحدة معالجة الرسومات إلى ذاكرة وحدة المعالجة المركزية، والتوازي المحدود الذي يمكن تحقيقه باستخدام وحدات العمل وخيوط وحدة المعالجة المركزية. لا تفرض WebGPU هذه القيود، ما يجعلها مناسبة تمامًا لمعالجة لقطات الفيديو بفضل دمجها الوثيق مع واجهة برمجة التطبيقات WebCodecs.

يوضّح مقتطف الرمز البرمجي التالي كيفية استيراد إطار فيديو كنسيج خارجي في WebGPU ومعالجته. يمكنك تجربة هذا الإصدار التجريبي.

// 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() تلقائيًا جهاز GPU قد لا يتطابق مع إمكانات الجهاز المادي، بل يعرض أدنى حدّ معقول من جميع وحدات معالجة الرسومات. من خلال مطالبة المطوّرين بطلب حدود الأجهزة، تضمن WebGPU تشغيل التطبيقات على أكبر عدد ممكن من الأجهزة.

معالجة لوحة الرسم

تدير WebGL اللوحة تلقائيًا بعد إنشاء سياق WebGL وتقديم سمات السياق، مثل alpha أو antialias أو colorSpace أو depth أو preserveDrawingBuffer أو stencil.

من ناحية أخرى، تتطلّب WebGPU منك إدارة اللوحة بنفسك. على سبيل المثال، لتحقيق ميزة إزالة التمويه في WebGPU، عليك إنشاء نسيج متعدد العيّنات وعرضه. بعد ذلك، يمكنك تحويل النسيج المتعدد النماذج إلى نسيج عادي ورسم هذا النسيج على اللوحة. تتيح لك هذه الإدارة اليدوية إمكانية الإخراج إلى أي عدد تريده من اللوحات من عنصر GPUDevice واحد. في المقابل، يمكن لواجهة برمجة التطبيقات WebGL إنشاء سياق واحد فقط لكلّ لوحة.

اطّلِع على العرض التجريبي لميزة "WebGPU Multiple Canvases".

يُرجى العِلم أنّ المتصفّحات تفرض حاليًا حدًا أقصى لعدد لوحات WebGL لكل صفحة. في وقت كتابة هذه المقالة، يمكن لمتصفّحَي Chrome وSafari استخدام ما يصل إلى 16 لوحة WebGL في الوقت نفسه، ويمكن لمتصفّح Firefox إنشاء ما يصل إلى 200 لوحة. من ناحية أخرى، ما مِن حدّ أقصى لعدد لوحات WebGPU لكل صفحة.

لقطة شاشة تعرض الحد الأقصى لعدد لوحات WebGL في متصفّحات Safari وChrome وFirefox
الحد الأقصى لعدد لوحات WebGL في Safari وChrome وFirefox (من اليمين إلى اليسار) - العرض التجريبي.

رسائل خطأ مفيدة

يوفّر WebGPU تسلسل استدعاء لكل رسالة يتم عرضها من واجهة برمجة التطبيقات. وهذا يعني أنّه يمكنك الاطّلاع بسرعة على مكان حدوث الخطأ في الرمز البرمجي، ما يساعد في تصحيح الأخطاء وإصلاحها.

بالإضافة إلى توفير تسلسل استدعاء الدوال البرمجية، تكون رسائل خطأ WebGPU سهلة الفهم وقابلة للتنفيذ. تتضمّن رسائل الخطأ عادةً وصفًا للخطأ واقتراحات حول كيفية إصلاحه.

يتيح لك WebGPU أيضًا تقديم label مخصّص لكل عنصر WebGPU. ويستخدم المتصفّح هذا التصنيف بعد ذلك في رسائل GPUError وتحذيرات وحدة التحكّم وأدوات مطوّري المتصفّح.

من الأسماء إلى الفهارس

في WebGL، يتم ربط العديد من العناصر بالأسماء. على سبيل المثال، يمكنك تحديد متغيّر موحّد يُسمى myUniform في GLSL والحصول على موقعه باستخدام gl.getUniformLocation(program, 'myUniform'). يُعدّ ذلك مفيدًا لأنّه سيظهر لك خطأ إذا أخطأت في كتابة اسم متغيّر الزيّ.

من ناحية أخرى، في WebGPU، يكون كل شيء مرتبطًا بالكامل من خلال إزاحة أو فهرس البايت (يُشار إليه غالبًا باسم الموقع). تقع على عاتقك مسؤولية مواءمة المواقع الجغرافية للرمز في WGSL وJavaScript.

إنشاء صور Mipmap

في WebGL، يمكنك إنشاء مستوى 0 من mip للّوحة ثمّ استدعاء gl.generateMipmap(). ستنشئ WebGL بعد ذلك جميع مستويات mip الأخرى نيابةً عنك.

في WebGPU، عليك إنشاء خرائط MIP بنفسك. لا تتوفّر دالة مضمّنة لإجراء ذلك. يمكنك الاطّلاع على مناقشة المواصفات لمعرفة المزيد من المعلومات عن القرار. يمكنك استخدام مكتبات مفيدة مثل webgpu-utils لإنشاء خرائط MIP أو التعرّف على كيفية إجراء ذلك بنفسك.

ذاكرة التخزين المؤقت ومواد تخزين الذاكرة

تتيح لك كلّ من WebGL وWebGPU استخدام وحدات التخزين المؤقتة الموحّدة، كما تتيح لك تمرير مَعلمات ثابتة بحجم محدود إلى أدوات تحسين الصورة. لا تتوفّر وحدات تخزين المؤقت إلا في WebGPU، وهي تشبه إلى حد كبير وحدات التخزين المؤقت الموحّدة، ولكنها أكثر فعالية ومرونة منها.

  • يمكن أن تكون بيانات تخزين المخزن المؤقت التي يتم تمريرها إلى وحدات التلوين أكبر بكثير من المخزن المؤقت الموحّد. على الرغم من أنّ المواصفات تنص على أنّ حجم عمليات ربط ذاكرة التخزين المؤقت الموحّدة يمكن أن يصل إلى 64 كيلوبايت (راجِع maxUniformBufferBindingSize)، فإنّ الحد الأقصى لحجم عملية ربط ذاكرة التخزين المؤقت هو 128 ميغابايت على الأقل في WebGPU (راجِع maxStorageBufferBindingSize).

  • يمكن الكتابة في مخازن التخزين المؤقت، وهي تتيح بعض العمليات الذرية، في حين أنّ المخازن المؤقتة الموحّدة متاحة للقراءة فقط. ويسمح ذلك بتنفيذ فئات جديدة من الخوارزميات.

  • تتوافق عمليات ربط مخازن العناصر المؤقتة مع صفائف بحجم وقت التشغيل لتقديم خوارزميات أكثر مرونة، في حين يجب توفير أحجام صفائف العناصر المؤقتة الموحّدة في برنامج التظليل.

لا تتوفّر نسيج التخزين إلا في WebGPU، وهو يمثّل بالنسبة إلى النسيج ما يمثّله مخزن التخزين بالنسبة إلى المخزن الموحّد. وهي أكثر مرونة من مواد النسيج العادية، وتسمح بالكتابة العشوائية (والقراءة أيضًا في المستقبل).

التغييرات في المخزن المؤقت والنسيج

في WebGL، يمكنك إنشاء ذاكرة تخزين مؤقت أو نسيج ثم تغيير حجمه في أي وقت باستخدام gl.bufferData() وgl.texImage2D() على التوالي على سبيل المثال.

في WebGPU، تكون المخازن المؤقتة والقوام غير قابلة للتغيير. وهذا يعني أنّه لا يمكنك تغيير حجمها أو استخدامها أو تنسيقها بعد إنشائها. ويمكنك تغيير المحتوى فقط.

الاختلافات في اصطلاحات المساحات

في WebGL، يتراوح نطاق مساحة المقطع على محور Z بين -1 و1. في WebGPU، يتراوح نطاق مساحة المقطع في محور Z بين 0 و1. وهذا يعني أنّ الأجسام التي تبلغ قيمة z فيها 0 هي الأقرب إلى الكاميرا، في حين أنّ الأجسام التي تبلغ قيمة z فيها 1 هي الأبعد.

صورة توضيحية لنطاقات مساحة المقطع العرضي للمحور Z في WebGL وWebGPU
تتراوح مساحات المقاطع في محور Z في WebGL وWebGPU.

يستخدم WebGL اصطلاح OpenGL، حيث يكون محور Y للأعلى ومحور Z باتجاه المشاهد. يستخدم WebGPU اصطلاح Metal، حيث يكون محور Y للأسفل ومحور Z خارج الشاشة. يُرجى العِلم أنّ اتجاه محور Y هو للأسفل في إحداثيات إطار التخزين المؤقت للصور وإحداثيات مساحة العرض وإحداثيات القطعة/البكسل. في مساحة المقطع، لا يزال اتجاه محور Y للأعلى كما هو في WebGL.

الشكر والتقدير

نشكر Corentin Wallez وGregg Tavares وStephen White وKen Russell وRachel Andrew على مراجعة هذه المقالة.

أنصحك أيضًا بزيارة WebGPUFundamentals.org للاطّلاع على تفاصيل أكثر حول الاختلافات بين WebGPU وWebGL.