مكتبة تسجيل معدل سرعة الإطارات جزء من حزمة تطوير ألعاب Android.

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

خلفية

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

  • تخزِّن مؤقتًا الإطارات السابقة للإطارات داخليًا.
  • لرصد عمليات إرسال اللقطات المتأخرة
  • تكرار عرض الإطارات السابقة عند رصد الإطارات المتأخرة

تُعلم اللعبة SurfaceFlinger، المكوِّن داخل النظام الفرعي للعرض، بأنها أرسلت جميع طلبات السحب المطلوبة لإطار ما (عن طريق طلب eglSwapBuffers أو vkQueuePresentKHR). يُعلم SurfaceFlinger مدى توفّر الإطار لأجهزة العرض باستخدام مزلاج. بعد ذلك تعرض أجهزة العرض الإطار المحدد. حيث يتم وضع علامات على أجهزة العرض بمعدل ثابت، على سبيل المثال 60 هرتز، وإذا لم يكن هناك إطار جديد عندما يحتاج الجهاز إلى إطار، فسيعرض الجهاز الإطار السابق مرة أخرى.

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

الحلول غير الأمثل

تم استخدام الحلول التالية لمستوى سرعة عرض الإطارات في الألعاب سابقًا وتؤدي عادةً هذه الحلول إلى عدم اتّساق أوقات عرض اللقطات وزيادة وقت استجابة الإدخال.

إرسال اللقطات بالسرعة التي تسمح بها واجهة برمجة تطبيقات العرض

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

استخدام "مصمم رقصات Android" وحده

تستخدم الألعاب أيضًا ميزة "مصمم رقصات Android" للمزامنة. وهذا المكوِّن، المتوفر في لغة Java من واجهة برمجة التطبيقات 16 وفي لغة C++ من واجهة برمجة التطبيقات 24، يوفّر مؤشرات منتظمة بالوتيرة نفسها التي يستخدمها النظام الفرعي للعرض. لا تزال هناك تفاصيل حول موعد تسليم هذه العلامة مقارنةً بجهاز VSYNC الفعلي، وتختلف هذه الإزاحة باختلاف الجهاز. قد يستمر الازدحام المؤقت للإطارات الطويلة.

مزايا مكتبة Frame Pacing

تستخدم مكتبة Frame Pacing مصمم رقصات Android للمزامنة والتعامل مع التباين في تسليم العلامات من أجلك. وهو يستخدم طوابع زمنية للعرض التقديمي للتأكد من تقديم الإطارات في الوقت المناسب ومزامنة السياجات لتجنب ازدحام المخزن المؤقت. تستخدم المكتبة مصمم رقصات NDK إذا كان متاحًا، ثم تعود إلى مصمم رقصات Java في حال عدم توفّره.

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

طريقة العمل

توضح الأقسام التالية كيفية تعامل مكتبة Frame Pacing مع إطارات الألعاب الطويلة والقصيرة لتحقيق السرعة الصحيحة في معدل عرض الإطارات.

المعدل الصحيح لوتيرة عرض اللقطة عند 30 هرتز

عند العرض عند 30 هرتز على جهاز 60 هرتز، يظهر الوضع المثالي على Android في الشكل 1. يعمل SurfaceFlinger على تثبيت مخازن رسومية جديدة عند توفّرها (يشير NB في الرسم التخطيطي إلى أنّه لا يوجد مخزن مؤقت ويتم تكرار السابق).

وتيرة الإطار المثالية عند 30 هرتز على جهاز 60 هرتز

الشكل 1. وتيرة الإطار المثالية عند 30 هرتز على جهاز 60 هرتز

إطارات قصيرة في الألعاب تؤدي إلى التلعثم

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

إطارات ألعاب قصيرة

الشكل 2. يتسبب إطار اللعبة القصير C في عرض الإطار B لإطار واحد فقط، متبوعًا بإطارات C متعددة،

تحل مكتبة معدل سرعة الإطارات هذه المشكلة باستخدام الطوابع الزمنية للعروض التقديمية. تستخدم المكتبة إضافات الطوابع الزمنية للعرض التقديمي EGL_ANDROID_presentation_time وVK_GOOGLE_display_timing كي لا يتم عرض الإطارات مبكرًا، كما هو موضَّح في الشكل 3.

الطوابع الزمنية للعرض التقديمي

الشكل 3. تم تقديم إطار اللعبة "ب" مرّتين للحصول على عرض أكثر سلاسة.

الإطارات الطويلة تؤدي إلى التقطع ووقت الاستجابة

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

إطارات ألعاب طويلة

الشكل 4. الإطار الطويل B يعطي سرعة غير صحيحة لإطارَين: A وB

تحلّ المكتبة ذلك باستخدام سياجات المزامنة (EGL_KHR_fence_sync و VkFence) لإضافة فترات انتظار في التطبيق تسمح لتدفق العرض بالتدفق، بدلاً من زيادة الضغط على الشاشة الخلفية. لا يزال الإطار A يقدم إطارًا إضافيًا، لكن الإطار B يقدم الآن بشكل صحيح، كما هو موضح في الشكل 5.

تمت إضافة انتظارات إلى طبقة التطبيق

الشكل 5. ينتظر الإطاران "ج" و"د" العرض إلى أن يتم تقديمهما.

أوضاع التشغيل المتوافقة

يمكنك تهيئة مكتبة معدل سرعة الإطارات لتعمل في أحد الأوضاع الثلاثة التالية:

  • تم إيقاف الوضع التلقائي + مسار التعلّم
  • الوضع التلقائي مفعَّل + مسار التعلّم
  • تفعيل الوضع التلقائي + وضع مسار التعلّم التلقائي (خط الأنابيب/خط الأنابيب)

يمكنك تجربة الوضع التلقائي ووضع مسارات التعلّم، ولكن تبدأ بإيقافها وتضمين ما يلي بعد إعداد Swappy:

  swappyAutoSwapInterval(false);
  swappyAutoPipelineMode(false);
  swappyEnableStats(false);
  swappySwapIntervalNS(1000000000L/yourPreferredFrameRateInHz);

وضع مسار التعلّم

لتنسيق أعباء عمل المحرّك، تستخدم المكتبة عادةً نموذج تتابع يفصل بين أحمال عمل وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU) عبر حدود VSYNC.

وضع مسار التعلّم

الشكل 6. وضع مسار التعلّم

وضع غير مسار التعلّم

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

وضع غير مسار التعلّم

الشكل 7. وضع غير مسار التعلّم

وضع "تلقائي"

لا تعرف معظم الألعاب كيفية اختيار الفاصل الزمني للتبديل، وهو المدة التي يتم عرض كل إطار خلالها (على سبيل المثال، 33.3 مللي ثانية لـ 30 هرتز). على بعض الأجهزة، يمكن عرض لعبة ما بمعدل 60 لقطة في الثانية على جهاز آخر، بينما تتم إعادة عرض اللعبة إلى قيمة أقل على جهاز آخر. يقيس الوضع التلقائي أوقات وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات من أجل تنفيذ ما يلي:

  • اختيار الفواصل الزمنية للتبديل تلقائيًا: يمكن للألعاب التي ترسل 30 هرتز في بعض المشاهد و60 هرتز في بعض المشاهد الأخرى أن تسمح للمكتبة بضبط هذا الفاصل الزمني بشكل ديناميكي.
  • إيقاف مسار التعلّم للإطارات الفائقة السرعة: يقدّم وقت الاستجابة الأمثل لإدخال شاشة الإدخال في جميع الحالات.

معدّلات إعادة التحميل المتعددة

توفر الأجهزة التي تتيح معدلات تحديث متعددة مرونة أكبر في اختيار فاصل تبديل يبدو سلسًا:

  • على الأجهزة التي تعمل بتردد 60 هرتز: 60 لقطة في الثانية / 30 لقطة في الثانية / 20 لقطة في الثانية
  • على الأجهزة 60 هرتز + 90 هرتز: 90 لقطة في الثانية / 60 لقطة في الثانية / 45 لقطة في الثانية / 30 لقطة في الثانية
  • على الأجهزة 60 هرتز + 90 هرتز + 120 هرتز: 120 لقطة في الثانية / 60 لقطة في الثانية / 45 لقطة في الثانية / 40 لقطة في الثانية / 30 لقطة في الثانية

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

للحصول على مزيد من المعلومات حول وتيرة عرض الإطارات المتعدّدة لمعدَّل التحديث، يُرجى الاطّلاع على مشاركة المدونة عرض معدّل التحديث المرتفع على Android.

إحصاءات اللقطات

تقدم مكتبة معدل سرعة الإطارات الإحصاءات التالية لأغراض تصحيح الأخطاء وتحديد الملفات الشخصية:

  • المدرج التكراري لعدد مرات تحديث الشاشة لإطار انتظره في قائمة انتظار المكون بعد اكتمال العرض.
  • مدرج تكراري لعدد مرات إعادة تحميل الشاشة التي تم تمريرها بين وقت العرض التقديمي المطلوب والوقت الحالي الفعلي.
  • مدرج تكراري لعدد عمليات إعادة تحميل الشاشة التي تم تمريرها بين إطارين متتاليين.
  • مدرج تكراري لعدد مرات إعادة تحميل الشاشة التي تم إجراؤها بين بداية عمل وحدة المعالجة المركزية (CPU) لهذا الإطار والوقت الحالي الفعلي.

الخطوة التالية

يمكنك الاطّلاع على أحد الأدلة التالية لدمج مكتبة Android Frame Pacing في لعبتك: