Apple Metal في MAPS.ME

الصورة مرحبا بالجميع!

يوجد في العالم عدد كبير من التطبيقات على OpenGL ، ويبدو أن Apple لا توافق تمامًا على ذلك. بدءًا من iOS 12 و MacOS Mojave ، تم إيقاف OpenGL. لقد دمجنا Apple Metal في MAPS.ME ونحن مستعدون لمشاركة خبرتنا ونتائجنا. سنخبرك بكيفية إعادة تصميم محرك الرسومات ، والصعوبات التي كان علينا مواجهتها ، والأهم من ذلك ، كم عدد إطارات FPS لدينا الآن.

كل من يهتم أو يفكر في إضافة دعم Apple Metal لمحرك الرسومات مرحبًا به في القطط.

العدد


تم تصميم محرك الرسومات الخاص بنا على أنه متعدد المنصات ، وبما أن OpenGL هو في الواقع واجهة برمجة التطبيقات الرسومية عبر الأنظمة الأساسية الوحيدة لمجموعة المنصات التي تهمنا (iOS و Android و MacOS و Linux) ، فقد اخترناها كأساس. لم نقدم مستوى إضافيًا من التجريد من شأنه إخفاء الميزات الخاصة بـ OpenGL ، ولكن لحسن الحظ ، تركنا إمكانية تنفيذه.

مع ظهور الجيل الجديد من واجهات برمجة التطبيقات الرسومية Apple Metal و Vulkan ، نظرنا بالطبع في إمكانية ظهورها في تطبيقنا ، ومع ذلك ، توقفنا عن طريق ما يلي:

  1. يمكن أن يعمل Vulkan فقط على Android و Linux ، ويمكن أن يعمل Apple Metal فقط على iOS و MacOS. لم نرغب في فقدان النظام الأساسي المشترك على مستوى واجهة برمجة التطبيقات الرسومية ، وهذا من شأنه أن يعقد عمليات التطوير والتصحيح ، ويزيد من حجم العمل.
  2. لا يمكن إنشاء تطبيق على Apple Metal وتشغيله على محاكي iOS (بالمناسبة ، حتى الآن) ، الأمر الذي سيعقد أيضًا تطورنا ولن يسمح لنا بالتخلص تمامًا من OpenGL.
  3. إطار Qt Framework ، الذي نستخدمه لإنشاء أدوات داخلية ، يدعم OpenGL فقط ( يتم دعم Vulkan الآن ).
  4. لم يكن لدى Apple Metal وليس لديه واجهة برمجة تطبيقات C ++ ، الأمر الذي سيجبرنا على التوصل إلى ملخصات ليس فقط لوقت التشغيل ، ولكن أيضًا لمرحلة بناء التطبيق ، عندما يتم تجميع جزء من المحرك في Objective-C ++ ، وآخر أكبر بكثير في C ++.
  5. لم نكن مستعدين لإنشاء محرك منفصل أو فرع رمز منفصل خاص بـ iOS.
  6. تم تقييم التنفيذ لمدة ستة أشهر على الأقل في عمل مطور رسومي واحد.

عندما أعلنت Apple في ربيع عام 2018 عن نقل OpenGL إلى حالة موقوفة ، أصبح من الواضح أنه لم يعد من الممكن التأجيل ، ويجب حل المشكلات المذكورة أعلاه بطريقة أو بأخرى. بالإضافة إلى ذلك ، نحن نعمل منذ فترة طويلة على تحسين سرعة التطبيق واستهلاك الطاقة ، وبدا أن Apple Metal قادرة على المساعدة.

اختيار القرار


على الفور لاحظنا MoltenVK . يحاكي هذا الإطار Vulkan API باستخدام Apple Metal ، وتم فتح كود المصدر الخاص به مؤخرًا. يبدو أن استخدام MoltenVK سيسمح باستبدال OpenGL بـ Vulkan ، ولن يضطر إلى التعامل مع التكامل المنفصل لـ Apple Metal على الإطلاق. بالإضافة إلى ذلك ، رفض مطورو Qt دعمًا منفصلاً للعرض على Apple Metal لصالح MoltenVK. ومع ذلك ، تم إيقافنا:

  • الحاجة إلى دعم أجهزة Android التي لا يتوفر عليها Vulkan ؛
  • عدم القدرة على البدء في محاكاة iOS دون وجود احتياطي على OpenGL ؛
  • عدم القدرة على استخدام أدوات Apple لتصحيح الأخطاء والتظليل والتشكيل المسبق للتجميع ، حيث تقوم MoltenVK بإنشاء تظليل في الوقت الفعلي لـ Apple Metal من أكواد مصدر SPIR-V أو GLSL ؛
  • الحاجة إلى انتظار التحديثات وإصلاح الأخطاء في MoltenVK عند إصدار إصدارات جديدة من Metal ؛
  • استحالة التحسين الدقيق الخاص بالمعدن ، ولكن ليس محددًا أو غير موجود لـ Vulkan.

اتضح أننا بحاجة إلى حفظ OpenGL ، مما يعني أنه لا يمكننا الاستغناء عن تجريد المحرك من واجهة برمجة التطبيقات الرسومية. سيتم استخدام Apple Metal و OpenGL ES ، وفي المستقبل Vulkan ، لإنشاء مكونات داخلية مستقلة لمحرك الرسومات ، والتي يمكن استبدالها بالكامل. سيلعب OpenGL دور خيار الرجوع عند عدم توفر Metal أو Vulkan لسبب أو لآخر.

كانت خطة التنفيذ على النحو التالي:

  1. إعادة بيع محرك الرسومات لاستخلاص واجهة برمجة التطبيقات للرسومات المستخدمة.
  2. تقدم إلى Apple Metal لإصدار iOS من التطبيق.
  3. ضع معايير مناسبة لتقديم السرعة واستهلاك الطاقة لمعرفة ما إذا كانت واجهات برمجة التطبيقات الرسومية الحديثة ذات المستوى المنخفض يمكن أن تفيد المنتج.

الاختلافات الرئيسية بين OpenGL والمعادن


لفهم كيفية تجريد واجهة برمجة التطبيقات الرسومية ، دعنا أولاً نحدد الاختلافات المفاهيمية الرئيسية بين OpenGL و Metal.

  1. يعتقد ، وليس بدون سبب ، أن Metal هي واجهة برمجة تطبيقات ذات مستوى أدنى. ومع ذلك ، هذا لا يعني أنه يجب عليك الكتابة في المجمع أو تنفيذ التنقيط بنفسك. يمكن تسمية Metal بواجهة برمجة تطبيقات منخفضة المستوى بمعنى أنها تؤدي عددًا صغيرًا جدًا من الإجراءات الضمنية ، أي أنه يجب كتابة جميع الإجراءات تقريبًا إلى المبرمج نفسه. يقوم OpenGL بالكثير من الأشياء بشكل ضمني ، بدءًا من دعم مرجع ضمني لسياق OpenGL وربط هذا السياق بالدفق الذي تم إنشاؤه فيه.
  2. في Metal ، التحقق من "لا" في الوقت الحقيقي للفرق. في وضع التصحيح ، يوجد التحقق بالطبع ، وهو أفضل بكثير من العديد من واجهات برمجة التطبيقات الأخرى ، ويرجع ذلك إلى حد كبير إلى تكامله المحكم مع Xcode. ولكن عندما يتم إرسال البرنامج إلى المستخدم ، لم يعد هناك أي التحقق من الصحة ، ببساطة يتعطل البرنامج على الخطأ الأول. وغني عن القول ، تعطل برنامج OpenGL فقط في الحالات القصوى. الممارسة الأكثر شيوعًا: تجاهل الخطأ والاستمرار في العمل.
  3. يمكن للمعادن ترجمة تظليل وبناء مكتبات منها. في OpenGL ، يتم تجميع التظليل من المصدر في عملية البرنامج ، لأن هذا هو المسؤول عن التنفيذ المحدد منخفض المستوى لـ OpenGL على جهاز معين. تؤدي الاختلافات و / أو الأخطاء في تنفيذ جامعي التظليل في بعض الأحيان إلى أخطاء رائعة ، خاصة على أجهزة Android من العلامات التجارية الصينية.
  4. يستخدم OpenGL بنشاط آلة الحالة ، والتي تضيف آثارًا جانبية على كل وظيفة تقريبًا. وبالتالي ، فإن دالات OpenGL ليست دالات خالصة ، وغالبًا ما يكون ترتيب الطلبات والمكالمات مهمًا. لا يستخدم المعدن الحالات بشكل ضمني ولا يحافظ عليها لفترة أطول مما هو ضروري للعرض. الدول موجودة ككائنات مسبقة الفشل.

إعادة بناء محرك الرسوم البيانية وتضمين المعادن


تتكون عملية إعادة هيكلة محرك الرسومات بشكل أساسي من إيجاد أفضل حل للتخلص من ميزات OpenGL التي يستخدمها محركنا بنشاط. تم تضمين التضمين المعدني ، بدءًا من إحدى المراحل ، بالتوازي.

  • كما ذكرنا من قبل ، فإن OpenGL API لديها كيان ضمني يسمى السياق. يرتبط السياق بسلسلة رسائل محددة ، وتجد الدالة OpenGL التي يتم استدعاؤها في سلسلة الرسائل هذه نفسها وتستخدم هذا السياق. لا يعمل Metal و Vulkan (نعم ، وواجهات برمجة التطبيقات الأخرى ، على سبيل المثال ، Direct3D) بهذه الطريقة ، فلديهم كائنات صريحة مماثلة تسمى الجهاز أو المثيل. يقوم المستخدم نفسه بإنشاء هذه الكائنات وهو مسؤول عن نقلها إلى أنظمة فرعية مختلفة. من خلال هذه الكائنات يتم إجراء جميع المكالمات لأوامر الرسوم.

    أطلقنا على كائننا المجرد سياقًا رسوميًا ، وفي حالة OpenGL ، فإنه ببساطة يزين مكالمات أوامر OpenGL ، وفي حالة Metal فإنه يحتوي على واجهة MTLDevice الجذر التي يتم من خلالها استدعاء الأوامر المعدنية.

    بالطبع ، اضطررت إلى توزيع هذا الكائن (وبما أننا نقدم عرضًا متعدد الخيوط ، ثم العديد من هذه الكائنات) عبر جميع الأنظمة الفرعية.

    قمنا بإخفاء إنشاء قوائم انتظار للأوامر ، وبرامج التشفير ، وإدارتها داخل السياق الرسومي ، حتى لا ننشر الكيانات التي لا توجد ببساطة في OpenGL.
  • لم يكن احتمال اختفاء التحقق من صحة الأوامر الرسومية على أجهزة المستخدم مرضيًا بشكل علني. لا يمكن لقسم ضمان الجودة تغطية مجموعة كبيرة من الأجهزة وإصدارات نظام التشغيل بالكامل. لذلك ، كان علينا إضافة سجلات تفصيلية حيث تلقينا سابقًا خطأ ذا معنى من واجهة برمجة التطبيقات الرسومية. بالطبع ، تمت إضافة هذا التحقق فقط إلى المواقع التي يحتمل أن تكون خطرة وحرجة لمحرك الرسومات ، حيث إن تغطية المحرك بالكامل برمز تشخيص أمر مستحيل عمليا ويضر بالأداء بشكل عام. الواقع الجديد هو أن اختبار المستخدم وتصحيح الأخطاء باستخدام السجلات أصبح الآن في الماضي ، على الأقل من حيث العرض.
  • كان نظام التظليل السابق الخاص بنا غير مناسب لإعادة البناء ؛ كان علي إعادة كتابته بالكامل. النقطة هنا ليست فقط التجهيز المسبق للتظليل والتحقق من صحتها في مرحلة تجميع المشروع. يستخدم OpenGL ما يسمى المتغيرات الموحدة لتمرير المعلمات إلى التظليل. لا يتوفر النقل المنظم للبيانات إلا مع OpenGL ES 3.0 ، وبما أننا ما زلنا ندعم OpenGL ES 2.0 ، فإننا ببساطة لم نستخدم هذه الطريقة. جعلنا المعدن نستخدم هياكل البيانات لتمرير المعلمات ، وبالنسبة لـ OpenGL ، كان علينا أن نبتكر حقول بنية رسم الخرائط لمتغيرات موحدة. بالإضافة إلى ذلك ، كان علي إعادة كتابة كل تظليل في لغة التظليل المعدنية.
  • عند استخدام أشياء الدولة ، كان علينا أن نذهب لخدعة. في OpenGL ، يتم تعيين جميع الحالات ، كقاعدة ، مباشرة قبل التقديم ، وفي Metal يجب أن يكون هذا كائنًا تم إنشاؤه والتحقق منه مسبقًا. من الواضح أن محركنا استخدم نهج OpenGL ، وكان إعادة البناء مع الإنشاء الأولي لكائنات الحالة يمكن مقارنته بإعادة كتابة كاملة للمحرك. لقص هذه العقدة ، أنشأنا ذاكرة تخزين مؤقت للحالة داخل السياق الرسومي. في المرة الأولى التي يتم فيها إنشاء مجموعة فريدة من معلمات الحالة ، يتم إنشاء كائن حالة في Metal ووضعه في ذاكرة التخزين المؤقت. للمرة الثانية واللاحقة ، يتم استرداد الكائن ببساطة من ذاكرة التخزين المؤقت. يعمل هذا في خرائطنا ، نظرًا لأن عدد المجموعات المختلفة من معلمات الحالة ليست كبيرة جدًا (حوالي 20-30). بالنسبة لمحرك رسومات اللعبة المعقد ، فإن هذه الطريقة بالكاد مناسبة.

ونتيجة لذلك ، بعد حوالي 5 أشهر من العمل ، تمكنا من إطلاق MAPS.ME لأول مرة مع العرض الكامل على Apple Metal. لقد حان الوقت لمعرفة ما حدث.

تقديم اختبار السرعة


تقنية تجريبية


استخدمنا أجيالًا مختلفة من أجهزة Apple في التجربة. تم تحديثهم جميعًا إلى iOS 12. تم تنفيذ نفس البرنامج النصي للمستخدم على التنقل على الخريطة (النقل والتحجيم). تم كتابة البرنامج النصي لضمان هوية كاملة تقريبًا للعمليات داخل التطبيق في كل مرة يتم تشغيلها على كل جهاز. كموقع اختبار ، اخترنا منطقة لوس أنجلوس - واحدة من أكثر المناطق تحميلًا في MAPS.ME.

أولاً ، تم تشغيل البرنامج النصي مع العرض على OpenGL ES 3.0 ، ثم على نفس الجهاز مع العرض على Apple Metal. بين البدء ، تم إلغاء تحميل التطبيق بالكامل من الذاكرة.
تم قياس المؤشرات التالية:

  • FPS (إطارات في الثانية) للإطار بأكمله ؛
  • FPS للجزء من الإطار الذي يعمل فقط في التقديم ، باستثناء إعداد البيانات والعمليات الأخرى لإطار بإطار ؛
  • النسبة المئوية للإطارات البطيئة (أكبر من 30 مللي ثانية تقريبًا) ، أي تلك التي يمكن أن تنظر إليها العين البشرية على أنها هزات.

عند قياس FPS ، تم استبعاد الرسم مباشرة على شاشة الجهاز ، لأن المزامنة الرأسية مع معدل تحديث الشاشة لا تسمح بالحصول على نتائج موثوقة. لذلك ، تم رسم الإطار في النسيج في الذاكرة. لمزامنة وحدة المعالجة المركزية ووحدة معالجة الرسومات ، استخدم OpenGL مكالمة إضافية لـ glFinish ، بينما استخدمت Apple Metal waitUntilCompleted لـ MTLFrameCommandBuffer .

آيفون 6siPhone 7+آيفون 8
OpenglمعدنOpenglمعدنOpenglمعدن
Fps106160159221196298
FPS (التقديم فقط)157596247597271833
جزء الإطارات البطيئة (<30 إطارًا في الثانية)4.13٪1.25٪5.45٪0.76٪1.5٪0.29٪

iPhone XiPad Pro 12.9 "
OpenglمعدنOpenglمعدن
Fps145210104137
FPS (التقديم فقط)248705147463
جزء الإطارات البطيئة (<30 إطارًا في الثانية)0.15٪0.15٪17.52٪4.46٪

آيفون 6siPhone 7+آيفون 8iPhone XiPad Pro 12.9 "
تسريع الإطار المعدني (N مرات)1،51.391،521.451.32
تسريع التقديم على المعدن (N times)3.782.413.072.843.15
تحسن في الإطارات البطيئة (مرات N)3.37.175.1713.93

تحليل النتائج


في المتوسط ​​، كان مكاسب أداء الإطار باستخدام Apple Metal 43٪. تم إصلاح الحد الأدنى للقيمة على iPad Pro 12.9 '- 32٪ ، والحد الأقصى - 52٪ على iPhone 8. هناك تبعية: فكلما انخفضت دقة الشاشة ، تجاوزت Apple Metal OpenGL ES 3.0.

إذا قمنا بتقييم جزء الإطار المسؤول مباشرة عن العرض ، فقد زاد متوسط ​​سرعة العرض على Apple Metal 3 مرات. يشير هذا إلى تنظيم أفضل بكثير ، ونتيجة لذلك ، كفاءة واجهة برمجة تطبيقات Apple Metal مقارنة بـ OpenGL ES 3.0.

تم تقليل عدد الإطارات البطيئة (أكثر من 30 مللي ثانية) على Apple Metal بنحو 4 مرات. هذا يعني أن إدراك الرسوم المتحركة والتحرك حول الخريطة أصبح أكثر سلاسة. تم تسجيل أسوأ نتيجة على iPad Pro 12.9 'بدقة 2732 × 2048 بكسل: يوفر OpenGL ES 3.0 حوالي 17.5٪ من الإطارات البطيئة ، في حين أن Apple Metal - 4.5٪ فقط.

اختبار القوة


تقنية تجريبية


تم اختبار استهلاك الطاقة على iPhone 8 على نظام التشغيل iOS 12. تم تنفيذ سيناريو المستخدم نفسه - التنقل في الخريطة (الانتقال والقياس) لمدة ساعة واحدة. تم كتابة البرنامج النصي لضمان هوية شبه كاملة للعمليات داخل التطبيق في كل بداية. كما تم اختيار منطقة لوس أنجلوس كموقع للاختبار.

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

لم يتغير سطوع الشاشة في جميع الحالات. تم تنفيذ أية عمليات أخرى باستثناء النظام و MAPS.ME. تم تشغيل وضع الطائرة ، وتم إيقاف Wi-Fi و GPS. بالإضافة إلى ذلك ، تم إجراء العديد من قياسات التحكم.

ونتيجة لذلك ، لكل مؤشر من المؤشرات ، تم تشكيل مقارنة بين المعدن وبين OpenGL ، ثم تم حساب متوسط ​​النسب للحصول على تقدير مجمع واحد.

Openglمعدنربح
استنزاف البطارية32٪28٪12.5٪
التنميط استخدام البطارية في Xcode1.95٪1.83٪6.16٪

تحليل النتائج


في المتوسط ​​، تحسن استهلاك الطاقة في إصدار العرض على Apple Metal قليلاً. لا يتأثر استهلاك الطاقة لتطبيق GPU الخاص بنا كثيرًا ، حوالي 2٪ ، لأنه لا يمكن استدعاء MAPS.ME بشكل كبير من حيث استخدام GPU. ربما يتم تحقيق مكاسب صغيرة من خلال تقليل التكاليف الحسابية عند إعداد التعليمات لوحدة معالجة الرسومات على وحدة المعالجة المركزية ، والتي ، للأسف ، لا يمكن تمييزها بمساعدة أدوات التنميط.

ملخص


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

بالنسبة للسؤال عما إذا كان مشروعنا يحتاج حقًا إلى العرض على Apple Metal ، فنحن مستعدون للإجابة بالإيجاب. لا نحب الابتكار كثيرًا ، أو أنه يمكن لشركة Apple التخلي عن OpenGL أخيرًا. إنه فقط عام 2018 ، وظهر برنامج OpenGL في عام 1997 البعيد ، فقد حان الوقت لاتخاذ الخطوة التالية.

PS حتى أطلقنا الميزة على جميع أجهزة iOS. لتمكينه يدويًا ، اكتب ?metal في شريط البحث وأعد تشغيل التطبيق. لإرجاع العرض إلى OpenGL ، أدخل الأمر ?gl وأعد تشغيل التطبيق.

PPS MAPS.ME هو مشروع مفتوح المصدر. يمكنك قراءة شفرة المصدر على جيثب .

Source: https://habr.com/ru/post/ar430850/


All Articles