إطار التزامن

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

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

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

تزامن صريح

تتيح المزامنة الصريحة للمنتجين والمستهلكين للمخازن المؤقتة للرسومات الإشارة عند الانتهاء من استخدام المخزن المؤقت. يتم تنفيذ المزامنة الصريحة في مساحة kernel.

تشمل مزايا المزامنة الصريحة ما يلي:

  • تباين أقل في السلوك بين الأجهزة
  • دعم أفضل لتصحيح الأخطاء
  • مقاييس الاختبار المحسنة

يحتوي إطار عمل المزامنة على ثلاثة أنواع من الكائنات:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

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

اتبع هذه الإرشادات عند تنفيذ sync_timeline :

  • قدم أسماء مفيدة لجميع برامج التشغيل والجداول الزمنية والأسوار لتبسيط تصحيح الأخطاء.
  • قم بتنفيذ عاملي timeline_value_str و pt_value_str في المخططات الزمنية لجعل إخراج التصحيح أكثر قابلية للقراءة.
  • قم بتنفيذ ملء driver_data لمنح مكتبات مساحة المستخدمين ، مثل مكتبة GL ، الوصول إلى بيانات الجدول الزمني الخاص ، إذا رغبت في ذلك. يسمح data_driver للموردين بتمرير معلومات حول sync_fence و sync_pts الثابتة لبناء أسطر أوامر بناءً عليها.
  • لا تسمح لمساحة المستخدمين بإنشاء سياج أو الإشارة إليه بشكل صريح. ينتج عن إنشاء إشارات / أسوار صراحة هجوم رفض الخدمة الذي يوقف وظائف خطوط الأنابيب.
  • لا تدخل إلى عناصر sync_timeline أو sync_pt أو sync_fence بشكل صريح. يوفر API جميع الوظائف المطلوبة.

sync_pt

sync_pt هي قيمة أو نقطة واحدة على مخطط sync_timeline . النقطة لها ثلاث حالات: نشطة ، ومشار إليها ، وخطأ. تبدأ النقاط في الحالة النشطة وتنتقل إلى حالة الإشارة أو حالات الخطأ. على سبيل المثال ، عندما لا يحتاج مستهلك الصورة إلى مخزن مؤقت ، يتم الإشارة إلى sync_pt حتى يعرف منتج الصور أنه من المقبول الكتابة في المخزن المؤقت مرة أخرى.

sync_fence

sync_fence عبارة عن مجموعة من قيم sync_pt التي غالبًا ما يكون لها sync_timeline مختلفة (مثل وحدة تحكم العرض ووحدة معالجة الرسومات). sync_fence و sync_pt و sync_timeline هي العناصر الأساسية الرئيسية التي تستخدمها برامج التشغيل ومساحة المستخدمين لتوصيل تبعياتهم. عندما يتم الإشارة إلى السياج ، يتم ضمان اكتمال جميع الأوامر الصادرة قبل السياج لأن برنامج تشغيل kernel أو كتلة الأجهزة ينفذ الأوامر بالترتيب.

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

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

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

لتنفيذ المزامنة الصريحة ، قم بتوفير ما يلي:

  • نظام فرعي لمساحة kernel يقوم بتنفيذ إطار عمل المزامنة لبرنامج تشغيل جهاز معين. برامج التشغيل التي يجب أن تكون مدركًا للسياج هي بشكل عام أي شيء يصل إلى مؤلف الأجهزة أو يتصل به. تشمل الملفات الرئيسية:
    • التنفيذ الأساسي:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • التوثيق في kernel/common/Documentation/sync.txt
    • مكتبة للتواصل مع مساحة النواة في platform/system/core/libsync
  • يجب أن يوفر البائع أسوار المزامنة المناسبة كمعلمات لوظائف ValidateDisplay ( validateDisplay() و presentDisplay() في طبقة تجريد الأجهزة.
  • اثنان من ملحقات GL ذات الصلة بالسياج ( EGL_ANDROID_native_fence_sync و EGL_ANDROID_wait_sync ) ودعم السياج في برنامج تشغيل الرسومات.

دراسة حالة: تنفيذ برنامج تشغيل العرض

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

/*
 * assumes buffer is ready to be displayed.  returns when buffer is no longer on
 * screen.
 */
void display_buffer(struct dma_buf *buffer);

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

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

/*
 * displays buffer when fence is signaled.  returns immediately with a fence
 * that signals when buffer is no longer displayed.
 */
struct sync_fence* display_buffer(struct dma_buf *buffer, struct sync_fence
*fence);

تكامل المزامنة

يشرح هذا القسم كيفية دمج إطار عمل مزامنة مساحة kernel مع أجزاء مساحة المستخدمين في إطار عمل Android وبرامج التشغيل التي يجب أن تتواصل مع بعضها البعض. يتم تمثيل كائنات Kernel-space كأوصاف ملفات في مساحة المستخدمين.

اتفاقيات التكامل

اتبع اصطلاحات واجهة Android HAL:

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

تتم إعادة تسمية كائن السياج في كل مرة يمر فيها من خلال BufferQueue. يسمح دعم سياج Kernel للأسوار بالحصول على سلاسل للأسماء ، لذلك يستخدم إطار عمل المزامنة اسم النافذة وفهرس المخزن المؤقت الذي يتم وضعه في قائمة الانتظار لتسمية السياج ، مثل SurfaceView:0 . هذا مفيد في تصحيح الأخطاء لتحديد مصدر حالة الجمود حيث تظهر الأسماء في إخراج /d/sync وتقارير الأخطاء.

ANativeWindow التكامل

ANativeWindow مدرك للسياج. dequeueBuffer و queueBuffer و cancelBuffer لها معلمات سياج.

تكامل OpenGL ES

يعتمد تكامل مزامنة OpenGL ES على امتدادات EGL:

  • يوفر EGL_ANDROID_native_fence_sync طريقة للالتفاف أو إنشاء واصفات ملف سياج Android أصلية في كائنات EGLSyncKHR .
  • يسمح EGL_ANDROID_wait_sync على جانب وحدة معالجة الرسومات بدلاً من جانب وحدة المعالجة المركزية ، مما يجعل وحدة معالجة الرسومات تنتظر EGLSyncKHR . الامتداد EGL_ANDROID_wait_sync هو نفس الامتداد EGL_KHR_wait_sync .

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

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

  • يقوم واصف ملف سياج صالح بتغليف واصف ملف سياج Android أصلي موجود في كائن EGLSyncKHR .
  • -1 ينشئ واصف ملف سياج Android أصلي من كائن EGLSyncKHR .

استخدم استدعاء الدالة DupNativeFenceFD() لاستخراج كائن EGLSyncKHR من واصف ملف سياج Android الأصلي. هذا له نفس نتيجة الاستعلام عن سمة المجموعة ، لكنه يلتزم بالاتفاقية القائلة بأن المستلم يغلق السياج (ومن هنا جاءت العملية المكررة). أخيرًا ، يؤدي تدمير كائن EGLSyncKHR إلى إغلاق سمة السياج الداخلي.

تكامل مؤلف الأجهزة

يتعامل مؤلف الأجهزة مع ثلاثة أنواع من أسوار المزامنة:

  • يتم تمرير أسوار الاستحواذ مع مخازن الإدخال المؤقتة إلى مكالمات setLayerBuffer و setClientTarget . هذه تمثل كتابة معلقة في المخزن المؤقت ويجب أن تشير قبل SurfaceFlinger أو يحاول HWC القراءة من المخزن المؤقت المرتبط لإجراء التكوين.
  • يتم استرداد أسوار التحرير بعد استدعاء العرض الحالي باستخدام getReleaseFences presentDisplay هذه تمثل قراءة معلقة من المخزن المؤقت السابق على نفس الطبقة. يشير سياج التحرير عندما لا يستخدم HWC المخزن المؤقت السابق لأن المخزن المؤقت الحالي قد حل محل المخزن المؤقت السابق على الشاشة. يتم تمرير أسوار التحرير مرة أخرى إلى التطبيق جنبًا إلى جنب مع المخازن المؤقتة السابقة التي سيتم استبدالها أثناء التكوين الحالي. يجب أن ينتظر التطبيق حتى يشير سياج التحرير قبل كتابة محتويات جديدة في المخزن المؤقت الذي تم إرجاعه إليها.
  • يتم إرجاع الأسوار الحالية ، واحدة لكل إطار ، كجزء من الدعوة إلى presentDisplay . تمثل الأسوار الحالية وقت اكتمال تكوين هذا الإطار ، أو بالتناوب ، عندما لم تعد هناك حاجة إلى نتيجة تكوين الإطار السابق. بالنسبة لشاشات العرض المادية ، يعرض presentDisplay الأسوار الحالية عندما يظهر الإطار الحالي على الشاشة. بعد إرجاع الأسوار الحالية ، من الآمن الكتابة إلى المخزن المؤقت الهدف SurfaceFlinger مرة أخرى ، إن أمكن. بالنسبة لشاشات العرض الافتراضية ، يتم إرجاع الأسوار الحالية عندما يكون من الآمن قراءتها من المخزن المؤقت للإخراج.