من WebGL إلى WebGPU

فرانسوا بوفورت
فرانسوا بوفورت

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

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

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

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

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

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

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

عدم إجراء مزامنة بعد الآن

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

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

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

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

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

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

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

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

التعامل مع اللوحات

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

من ناحية أخرى، تتطلب 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 mip للزخرفة ثم طلب gl.generateMipmap(). بعد ذلك، سينشئ لك WebGL جميع مستويات mip الأخرى.

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

شكر وتقدير

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

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