من WebGL إلى WebGPU

François Beaufort
François Beaufort

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

ومن المطمئن معرفة أنّ WebGL وWebGPU يتشاركان في العديد من المفاهيم الأساسية. تتيح لك واجهتا برمجة التطبيقات تشغيل برامج صغيرة تسمى برامج التظليل على وحدة معالجة الرسومات. يتوافق WebGL مع أدوات تظليل رأس القيم، بينما تتوافق WebGPU مع أدوات تظليل الحاسوب. يستخدم WebGL لغة تظليل OpenGL (GLSL) بينما تستخدم WebGPU لغة تظليل WebGPU (WGSL). على الرغم من اختلاف اللغتين، إلا أن المفاهيم الأساسية هي نفسها في الغالب.

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

حالة عامة

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

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

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

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

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

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

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

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

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

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

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

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

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

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

يدير WebGL لوحة الرسم تلقائيًا بعد إنشاء سياق WebGL وتوفير سمات السياق مثل ألفا أو مضادة أو لونين أو عمق أو الحفاظ على DrawingBuffer أو الاستنسل.

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

يمكنك الاطّلاع على العرض التوضيحي للوحات الرسومات المتعددة في WebGPU.

من الناحية الجانبية، تفرض المتصفحات حاليًا حدًا أقصى على عدد لوحات 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، تكون كل العناصر مرتبطة بشكل كامل من خلال إزاحة البايت أو الفهرس (يُسمى غالبًا location). وتقع على عاتقك مسؤولية الحفاظ على مزامنة مواقع الرمز في WGSL وJavaScript.

إنشاء صور Mipmap

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

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

المخازن المؤقتة للتخزين وزخارف التخزين

تتوافق المخزن المؤقت الموحَّد مع كل من 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 خارج الشاشة. لاحظ أن اتجاه المحور ص في أسفل إحداثي المخزن المؤقت للإطار، وإحداثيات إطار العرض، وإحداث الجزء/البكسل. في مساحة المقاطع، لا يزال اتجاه المحور ص لأعلى كما هو الحال في WebGL.

شكر وتقدير

شكرًا لـ "كورنتين واليز" و"غريغ تافاريس" و"ستيفن وايت" و"كين راسل" و"رايتشل أندرو" على مراجعة هذه المقالة.

أنصح أيضًا باستخدام WebGPUFundamentals.org للاطّلاع على مزيد من التفاصيل حول الاختلافات بين WebGPU وWebGL.