مراجعة تاريخية للمعادن

لقد نجحنا في توفير الخلفية الخاصة بعرض Metal لملايين المستخدمين، وأود أن أكتب قليلاً عن ذلك. هناك آراء متباينة حول Metal في الصناعة - يزعم البعض أن Metal لم تكن لتكون ضرورية لو أن Apple أولت مزيدًا من الاهتمام لـ OpenGL و Vulkan، بينما يقول البعض الآخر إنها أسهل واجهة برمجة تطبيقات رسومية (API) على الإطلاق. يتساءل البعض: لماذا نهتم بـ Metal، إذا كان بإمكاننا كتابة كود OpenGL أو Vulkan، واستخدام MoltenGL أو MoltenVK لتحقيق نفس النتيجة؟ إليكم أفكاري حول واجهة برمجة التطبيقات هذه.
لماذا Metal؟
عندما أعلنت Apple عن Metal في WWDC عام 2014، كانت ردة فعلي الأولية هي تجاهله. كان متاحًا فقط على أحدث الأجهزة، والتي لم يكن لدى معظم مستخدمينا. وعلى الرغم من أن Apple ادعت أن Metal حل مشكلات أداء وحدة المعالجة المركزية (CPU)، فإن القيام بالتحسين من أجل أصغر شريحة في السوق يعني بالنسبة لنا أن الفجوة بين أسرع الأجهزة وأبطأها ستتسع أكثر. في ذلك الوقت، كنا نستخدم OpenGL ES 2 على أجهزة Apple فقط، وبدأنا أيضًا في نقله إلى Android.
بعد مرور عامين ونصف، إليكم كيف تبدو حصة Metal في السوق بالنسبة لمستخدمينا:

هذا أكثر جاذبية بكثير مما كان عليه في السابق. لا يزال تطبيق Metal لا يساعد الأجهزة الأقدم، لكن سوق GL على iOS يستمر في التقلص. بالإضافة إلى ذلك، غالبًا ما يختلف المحتوى الذي نعرضه على الأجهزة القديمة عن المحتوى الذي يتم عرضه على الأجهزة الحديثة، لذا من المنطقي بالتأكيد بذل بعض الجهد لجعل هذه الأجهزة أسرع. نظرًا لأن كود iOS Metal الخاص بك سيعمل على Mac مع تغييرات قليلة جدًا، فقد يكون من المنطقي استخدامه على Mac أيضًا حتى لو كنت تركز على الأجهزة المحمولة (نحن حاليًا نقدم إصدارات Metal على iOS فقط).
أعتقد أنه من المفيد تحليل حصة السوق بمزيد من التفصيل. على iOS، ندعم Metal لنظام iOS 8.3 وما فوق. في حين أن هناك بعض المستخدمين الذين لا يمكنهم تشغيل Metal بسبب قيود إصدار نظام التشغيل، فإن معظم الـ 25٪ الذين لا يزالون يستخدمون GL يستخدمون ببساطة أجهزة قديمة مزودة بأجهزة SGX. كما أنها لا تحتوي على أي ميزات OpenGL ES 3، ونحن راضون عن تشغيل مسار عرض أقل جودة هناك (على الرغم من أننا نود أن تتحول جميع الأجهزة إلى Metal. لحسن الحظ، فإن تقسيم GL/Metal سيتحسن فقط). على نظام Mac، تعد واجهة برمجة تطبيقات Metal أحدث، ويلعب نظام التشغيل دورًا مهمًا للغاية. يجب عليك استخدام OSX 10.11+ لاستخدام Metal، ونصف مستخدمينا لديهم ببساطة نظام تشغيل أقدم. الأمر يتعلق بالبرمجيات أكثر من الأجهزة (95% من مستخدمي Mac لدينا يستخدمون OpenGL 3.2+).
لذا، بالنظر إلى حصة السوق، لا تزال هناك خيارات أخرى لا تتضمن الانتقال إلى Metal. أحدها هو استخدام MoltenGL فحسب، والذي سيستخدم كود OpenGL الذي لدينا بالفعل، ولكن من المفترض أن يكون أسرع؛ وخيار آخر هو الانتقال إلى Vulkan (للحصول على أداء أفضل على أجهزة الكمبيوتر الشخصية، وفي النهاية على Android)؛ أو استخدام MoltenVK. لقد قمت بتقييم MoltenGL بشكل موجز ولم أكن متحمسًا جدًا للنتائج. استغرق الأمر بعض الجهد لجعل كودنا يعمل على الإطلاق، وعلى الرغم من أن الأداء كان أفضل قليلاً مقارنةً بـ OpenGL القياسي، إلا أنني كنت أتوقع المزيد. أما بالنسبة لـ MoltenVK، فأعتقد أنه من الخطأ محاولة تنفيذ واجهة برمجة تطبيقات (API) منخفضة المستوى كطبقة فوق واجهة أخرى. فمن المؤكد أنك ستواجه عدم توافق في المعاوقة مما سيؤدي إلى أداء دون المستوى الأمثل. ربما سيكون أفضل من واجهة برمجة التطبيقات عالية المستوى التي كنت تستخدمها، ولكن من غير المرجح أن يكون أسرع ما يمكن، وهو ما يُفترض أنه سبب اختيارك لواجهة برمجة تطبيقات منخفضة المستوى في المقام الأول! هناك جانب مهم آخر وهو أن تنفيذ Metal أبسط بكثير من تنفيذ Vulkan - سنناقش ذلك لاحقًا - لذا، من ناحية ما، أفضل غلاف Metal -> Vulkan بدلاً من Vulkan -> Metal.
ومن الجدير بالذكر أيضًا أنه لا يوجد برنامج تشغيل GL على iOS 10 في أحدث أجهزة iPhone، على ما يبدو. يتم تنفيذ GL فوق Metal، مما يعني أن استخدام OpenGL يوفر عليك فقط القليل من جهد التطوير - ليس كثيرًا، بالنظر إلى أن وعد OpenGL بـ "اكتب مرة واحدة، شغّل في أي مكان" لا يعمل حقًا على الأجهزة المحمولة.
النقل
أود أن أقول إن النقل إلى Metal كان سهلاً بشكل عام. لدينا خبرة كبيرة في العمل مع واجهات برمجة تطبيقات رسومات مختلفة، تتراوح من واجهات برمجة تطبيقات عالية المستوى مثل Direct3D 9/11 إلى واجهات برمجة تطبيقات منخفضة المستوى على منصات أجهزة الألعاب. يمنحنا هذا ميزة فريدة تتمثل في القدرة على استخدام واجهة برمجة تطبيقات مثل Metal بسهولة، وهي واجهة عالية المستوى بشكل معقول في الوقت نفسه، ولكنها تترك أيضًا بعض المهام مثل مزامنة وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU) لمطور التطبيق.
كانت العقبة الوحيدة هي تجميع برامج التظليل الخاصة بنا. وبمجرد الانتهاء من ذلك وحان وقت كتابة الكود، أصبح من الواضح أن واجهة برمجة التطبيقات بسيطة للغاية وواضحة بذاتها لدرجة أن الكود كتب نفسه عمليًا. تمكنت من تشغيل النسخة التي تعرض معظم العناصر بطريقة غير مثالية في حوالي 10 ساعات في يوم واحد، وقضيت أسبوعين إضافيين في تنظيف الكود، وإصلاح مشكلات التحقق من الصحة، والتحليل والتحسين، واللمسات النهائية العامة. إن الحصول على تطبيق واجهة برمجة التطبيقات (API) في هذا الإطار الزمني يدل على جودة واجهة برمجة التطبيقات (API) ومجموعة الأدوات. أعتقد أن هناك عدة جوانب تساهم في ذلك:
- يمكنك تطوير الكود بشكل تدريجي، مع الحصول على تعليقات جيدة في كل مرحلة. بدأ كودنا بتجاهل كل تزامن بين وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU)، وكان غير مثالي حقًا في أجزاء معينة من إعداد الحالة، واستخدم تتبع المراجع المدمج للموارد، ولم يقم أبدًا بتشغيل وحدة المعالجة المركزية ووحدة معالجة الرسومات بالتوازي لتجنب مواجهة المشكلات. ثم حولت مرحلة التحسين/الصقل هذا إلى شيء يمكننا طرحه، دون أن نفقد أبدًا القدرة على العرض في هذه العملية.
- الأدوات متاحة لك؛ وهي تعمل وتعمل بشكل جيد. هذا ليس مفاجئًا كثيرًا للأشخاص الذين اعتادوا على Direct3D 11، ولكن هذه هي المرة الأولى على الأجهزة المحمولة التي أمتلك فيها محلل أداء وحدة المعالجة المركزية (CPU)، ومحلل أداء وحدة معالجة الرسومات (GPU)، ومصحح أخطاء وحدة معالجة الرسومات (GPU)، وطبقة التحقق من صحة واجهة برمجة تطبيقات وحدة معالجة الرسومات (GPU API)، والتي عملت جميعها بشكل جيد بالتزامن، واكتشفت معظم المشكلات أثناء التطوير وساعدت في تحسين الكود.
- على الرغم من أن واجهة برمجة التطبيقات (API) أقل مستوىً إلى حد ما من Direct3D 11، وتترك بعض القرارات الرئيسية ذات المستوى المنخفض للمطور (مثل تكوين مسار العرض أو التزامن)، إلا أنها لا تزال تستخدم نموذج موارد تقليدي حيث يحتوي كل مورد على "علامات استخدام" معينة تم إنشاؤها بها، ولكنها لا تتطلب حواجز خط الأنابيب أو انتقالات التخطيط، ونموذج ربط تقليدي حيث تحتوي كل مرحلة من مراحل التظليل على عدة فتحات يمكنك تخصيص الموارد لها بحرية. كلاهما مألوف وسهل الفهم ويتطلب كمية محدودة جدًا من الكود للبدء بسرعة.
هناك أمر آخر ساعدنا وهو أن واجهة API الخاصة بنا كانت جاهزة لواجهات برمجة التطبيقات (API) المشابهة لـ Metal. إنها بسيطة للغاية ولكنها تكشف عن تفاصيل كافية (مثل عمليات العرض) لتتمكن من كتابة تطبيق عالي الأداء بسهولة. لم أحتج في أي مرحلة من مراحل التنفيذ إلى حفظ/استعادة الحالة (تعاني العديد من واجهات برمجة التطبيقات من هذه المشكلة، خاصةً بسبب معالجة إعداد هدف العرض على أنه تغييرات في الحالة واستمرار ربط الموارد/الحالة خلال ذلك) أو اتخاذ قرارات معقدة بشأن عمر الموارد/التزامن. تقريبًا الجزء الوحيد "المعقد" من الكود المطلوب للعرض هو الذي ينشئ حالة خط أنابيب العرض عن طريق تجزئة البتات اللازمة لإنشاء واحدة - كائنات حالة خط الأنابيب ليست جزءًا من تجريد واجهة برمجة التطبيقات (API) لدينا. حتى ذلك بسيط جدًا وسريع. سأكتب المزيد عن واجهة برمجة التطبيقات (API) الخاصة بنا في منشور منفصل.

إذن، أسبوع لتجميع برامج التظليل، وأسبوعان للحصول على تطبيق محسّن ومصقول ((نعم، حسناً، وربما أسبوع لإصلاح بعض الأخطاء التي تم اكتشافها أثناء الاختبار)) - ما هي النتائج؟ النتائج رائعة. يفي Metal تماماً بوعده فيما يتعلق بالأداء. أولاً، أداء التوزيع أحادي الخيط أفضل بشكل ملحوظ من OpenGL (تقليص جزء توزيع الرسم في إطار العرض لدينا بمقدار 2-3 أضعاف حسب حجم العمل)، وهذا مع الأخذ في الاعتبار أن تطبيق OpenGL لدينا مضبوط جيدًا من حيث تقليل إعداد الحالة الزائدة والتوافق الجيد مع برنامج التشغيل باستخدام المسارات السريعة. لكن الأمر لا يتوقف عند هذا الحد - فاستخدام التعدد الخيطي في Metal أمر بسيط شريطة أن يكون كود العرض الخاص بك جاهزًا لذلك. لم ننتقل بعد إلى توزيع الرسم متعدد الخيوط، لكننا نقوم بالفعل بتحويل بعض الأجزاء الأخرى التي تُعد الموارد لتعمل خارج خيط العرض، وهو أمر سهل للغاية، على عكس OpenGL.
علاوة على ذلك، يتيح لنا Metal إصلاح بعض مشكلات الأداء الأخرى من خلال توفير أدوات موثوقة وسهلة الوصول. أحد الأجزاء المركزية في كود العرض لدينا هو النظام الذي يحسب بيانات الإضاءة على وحدة المعالجة المركزية (CPU) في الفضاء العالمي ويقوم بتحميلها إلى مناطق من نسيج ثلاثي الأبعاد (والذي يتعين علينا محاكاته على أجهزة OpenGL ES 2). التحديثات جزئية، لذا لا يمكننا نسخ النسيج بالكامل وعلينا الاعتماد على الطريقة التي ينفذ بها برنامج التشغيل ميزة "glTexSubImage3D". في مرحلة ما، حاولنا استخدام PBO لتحسين أداء التحديث، لكننا واجهنا مشكلات كبيرة في الاستقرار على جميع الأصعدة، سواء على Android أو iOS. في Metal، هناك طريقتان مدمجتان لتحميل منطقة - MTLTexture.replaceRegion التي يمكنك استخدامها إذا كانت وحدة معالجة الرسومات (GPU) لا تقرأ النسيج حاليًا، أو MTLBlitCommandEncoder (copyFromBufferToTexture أو copyFromTextureToTexture) التي يمكنها تحميل المنطقة بشكل غير متزامن في الوقت المناسب لبدء وحدة معالجة الرسومات (GPU) في استخدام النسيج.


وكملاحظة عامة أخيرة، فإن صيانة كود Metal لا تتطلب جهدًا كبيرًا أيضًا. كانت جميع الميزات الإضافية التي اضطررنا إلى إضافتها حتى الآن أسهل في الإضافة هناك مقارنة بأي واجهة برمجة تطبيقات أخرى ندعمها، وأتوقع أن يستمر هذا الاتجاه. كان هناك بعض القلق من أن إضافة واجهة برمجة تطبيقات أخرى سيتطلب صيانة مستمرة، ولكن بالمقارنة مع OpenGL، فإن هذا لا يتطلب الكثير من العمل. في الواقع، نظرًا لأننا لن نضطر إلى دعم OpenGL ES 3 على iOS بعد الآن، فهذا يعني أنه يمكننا تبسيط بعض كود OpenGL الذي لدينا أيضًا.
الاستقرار
اليوم على نظام iOS، يبدو Metal مستقرًا للغاية. لست متأكدًا من كيف كان الوضع عند إطلاقه في عام 2014، أو كيف هو الوضع على Mac اليوم، لكن يبدو أن كل من برامج التشغيل والأدوات الخاصة بنظام iOS قوية جدًا.
واجهنا مشكلة واحدة في برنامج التشغيل على نظام iOS 10 تتعلق بتحميل برامج التظليل المجمعة باستخدام Xcode 7 (والتي أصلحناها بالتحول إلى Xcode 8)، وتعطل برنامج التشغيل مرة واحدة على نظام iOS 9 تبين أنه ناتج عن سوء استخدام واجهة برمجة التطبيقات (API) الخاصة بـ "nextDrawable". بخلاف ذلك، لم نشهد أي أخطاء في الأداء أو أي تعطل. بالنسبة لواجهة برمجة تطبيقات جديدة نسبيًا، كان Metal قويًا للغاية في جميع المجالات.
بالإضافة إلى ذلك، فإن الأدوات التي تحصل عليها مع Metal متنوعة وغنية؛ على وجه التحديد، يمكنك استخدام:
- طبقة تحقق شاملة للغاية تحدد المشكلات الشائعة في استخدام واجهة برمجة التطبيقات. إنها تشبه بشكل أساسي تصحيح أخطاء Direct3D - وهو أمر مألوف في Direct3D ولكنه غير معروف تقريبًا في عالم OpenGL (من الناحية النظرية، من المفترض أن يحل "
ARB_debug_callback" هذه المشكلة؛ ولكن من الناحية العملية، غالبًا ما يكون غير متاح، وعندما يكون متاحًا، لا يكون مفيدًا بشكل كبير) - مصحح أخطاء GPU فعال يعرض جميع الأوامر التي أرسلتها مع حالتها، ومحتويات هدف العرض، ومحتويات النسيج، وما إلى ذلك. لا أعرف ما إذا كان يحتوي على مصحح أخطاء شادر فعال لأنني لم أحتج إلى ذلك أبدًا، ويمكن أن يكون فحص المخزن المؤقت أسهل قليلاً، لكنه يؤدي المهمة في الغالب.
- مُحلل أداء GPU فعال يعرض إحصائيات الأداء لكل تمريرة (الوقت، النطاق الترددي) وكذلك وقت التنفيذ لكل شادر. وبما أن GPU عبارة عن مُركب، فلا يمكنك بالطبع توقع توقيتات لكل استدعاء رسم. إن الحصول على هذا المستوى من الرؤية - خاصةً بالنظر إلى الافتقار التام لأي معلومات عن توقيت GPU في واجهات برمجة التطبيقات الرسومية على iOS - أمر رائع.
- تتبع خط زمني فعال لوحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU) (Metal System Trace) يعرض جدولة أحمال عمل عرض وحدة المعالجة المركزية ووحدة معالجة الرسومات (مماثل لـ GPUView ولكنه سهل الاستخدام بالفعل)، مع بعض الخصائص الفريدة لواجهة المستخدم.
- مترجم شادر غير متصل بالإنترنت يتحقق من صحة صيغة الشادر، ويقدم لك أحيانًا تحذيرات مفيدة، ويحول الشادر إلى كتلة ثنائية سريعة التحميل في وقت التشغيل ومُحسّنة بشكل معقول مسبقًا (مما يقلل من أوقات التحميل نظرًا لأن مترجم برنامج التشغيل يمكن أن يكون أسرع).
إذا كنت قادمًا من عالم Direct3D أو أجهزة الألعاب، فقد تعتبر كل واحدة من هذه الميزات أمرًا مفروغًا منه. صدقني، في OpenGL كل واحدة من هذه الميزات غير معتادة وتلقى إقبالاً كبيراً، خاصة على الأجهزة المحمولة حيث اعتدت على التعامل مع برامج تشغيل معطلة أحياناً، وعدم وجود تحقق من الصحة، وعدم وجود مصحح أخطاء GPU، وعدم وجود أداة تحليل أداء GPU مفيدة، وعدم القدرة على جمع بيانات جدولة GPU، والاضطرار إلى العمل بلغة شادر نصية لكل مورد محلل لغوي مختلف قليلاً.
الخلاصة
تعد Metal واجهة برمجة تطبيقات رائعة لكتابة الكود وتوزيع التطبيقات. فهي سهلة الاستخدام، وتتمتع بأداء يمكن التنبؤ به، وتحتوي على برامج تشغيل قوية ومجموعة أدوات متينة. وهي تتفوق على OpenGL في كل جانب باستثناء قابلية النقل، لكن الحقيقة هي أنه كان يجب عليك استخدام OpenGL على ثلاث منصات فقط (iOS وAndroid وMac). تدعم اثنتان من هذه المنصات الآن Metal؛ بالإضافة إلى ذلك، فإن وعد OpenGL بالقابلية للنقل لم يتحقق إلى حد كبير، حيث أن الكود الذي تكتبه على منصة ما غالبًا ما ينتهي به الأمر إلى عدم العمل على منصة أخرى لأسباب مختلفة.
إذا كنت تستخدم محركًا تابعًا لجهة خارجية مثل Unity أو UE4، فإن Metal مدعوم بالفعل هناك؛ وإذا لم تكن تستخدمه وتستمتع ببرمجة الرسومات أو تهتم بشدة بالأداء وتأخذ iOS أو Mac على محمل الجد، فإنني أحثك بشدة على تجربة Metal. لن تشعر بخيبة أمل.


