چارچوب همگام سازی

چارچوب همگام سازی به صراحت وابستگی های بین عملیات ناهمزمان مختلف در سیستم گرافیک اندروید را توصیف می کند. این فریم ورک یک API را ارائه می‌کند که اجزا را قادر می‌سازد زمان انتشار بافرها را نشان دهند. این فریم ورک همچنین اجازه می دهد تا اصول اولیه همگام سازی بین درایورها از هسته به فضای کاربر و بین خود فرآیندهای فضای کاربر منتقل شود.

به عنوان مثال، یک برنامه ممکن است کار را برای انجام در GPU در صف قرار دهد. GPU شروع به کشیدن آن تصویر می کند. اگرچه تصویر هنوز به حافظه کشیده نشده است، نشانگر بافر به همراه یک حصار به ترکیب‌کننده پنجره ارسال می‌شود که نشان می‌دهد چه زمانی کار GPU تمام می‌شود. سازنده پنجره زودتر شروع به پردازش می کند و کار را به کنترل کننده نمایش می دهد. به روشی مشابه، کار CPU زودتر از موعد انجام می شود. هنگامی که GPU تمام شد، کنترل کننده صفحه نمایش بلافاصله تصویر را نمایش می دهد.

چارچوب همگام‌سازی همچنین به پیاده‌کنندگان اجازه می‌دهد تا از منابع همگام‌سازی در اجزای سخت‌افزاری خود استفاده کنند. در نهایت، این فریم ورک برای کمک به اشکال زدایی، قابلیت مشاهده را در خط لوله گرافیکی فراهم می کند.

همگام سازی صریح

همگام‌سازی صریح به تولیدکنندگان و مصرف‌کنندگان بافرهای گرافیکی امکان می‌دهد پس از پایان استفاده از بافر سیگنال دهند. همگام سازی صریح در kernel-space پیاده سازی شده است.

مزایای همگام سازی صریح عبارتند از:

  • تغییرات رفتاری کمتر بین دستگاه ها
  • پشتیبانی از اشکال زدایی بهتر
  • معیارهای تست بهبود یافته

چارچوب همگام سازی دارای سه نوع شی است:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline یک جدول زمانی یکنواخت در حال افزایش است که فروشندگان باید برای هر نمونه درایور اجرا کنند، مانند زمینه GL، کنترل کننده نمایشگر، یا blitter 2 بعدی. sync_timeline کارهای ارسال شده به هسته را برای یک قطعه سخت افزاری خاص می شمارد. sync_timeline تضمین هایی را در مورد ترتیب عملیات ارائه می دهد و پیاده سازی های مخصوص سخت افزار را فعال می کند.

هنگام اجرای sync_timeline این دستورالعمل ها را دنبال کنید:

  • برای ساده‌سازی اشکال‌زدایی، نام‌های مفیدی برای همه درایورها، جدول‌های زمانی و حصارها ارائه کنید.
  • عملگرهای timeline_value_str و pt_value_str را در تایم لاین‌ها پیاده‌سازی کنید تا خروجی اشکال‌زدایی خواناتر شود.
  • Fill driver_data را پیاده سازی کنید تا در صورت تمایل به کتابخانه های فضای کاربران، مانند کتابخانه GL، دسترسی به داده های جدول زمانی خصوصی بدهید. data_driver به فروشندگان اجازه می دهد اطلاعات مربوط به sync_fence تغییرناپذیر و sync_pts برای ایجاد خطوط فرمان بر اساس آنها ارسال کنند.
  • اجازه ندهید که Userspace صریحاً حصاری ایجاد کند یا علامت دهد. ایجاد صریح سیگنال/حصار منجر به حمله انکار سرویس می شود که عملکرد خط لوله را متوقف می کند.
  • به طور واضح به عناصر sync_timeline ، sync_pt یا sync_fence دسترسی ندهید. API تمام توابع مورد نیاز را فراهم می کند.

sync_pt

sync_pt یک مقدار یا نقطه در یک sync_timeline است. یک نقطه سه حالت دارد: فعال، علامت دار و خطا. نقاط در حالت فعال شروع می شوند و به حالت های سیگنال یا خطا منتقل می شوند. به عنوان مثال، هنگامی که یک مصرف کننده تصویر دیگر نیازی به بافر ندارد، یک sync_pt سیگنال داده می شود تا تولید کننده تصویر بداند که اشکالی ندارد که دوباره در بافر بنویسد.

sync_fence

sync_fence مجموعه‌ای از مقادیر sync_pt است که اغلب دارای والدین sync_timeline مختلفی هستند (مانند کنترل‌کننده نمایشگر و GPU). sync_fence ، sync_pt ، و sync_timeline اصلی‌ترین اصول اولیه‌ای هستند که درایورها و فضای کاربران برای برقراری ارتباط با وابستگی‌های خود استفاده می‌کنند. هنگامی که یک حصار سیگنال می شود، تمام دستورات صادر شده قبل از حصار تضمین می شود که کامل باشند زیرا درایور هسته یا بلوک سخت افزار دستورات را به ترتیب اجرا می کند.

چارچوب همگام‌سازی به چندین مصرف‌کننده یا تولیدکننده اجازه می‌دهد تا زمانی که استفاده از یک بافر تمام شد، سیگنال دهند و اطلاعات وابستگی را با یک پارامتر تابع انتقال دهند. حصارها توسط یک توصیفگر فایل پشتیبانی می شوند و از فضای هسته به فضای کاربر منتقل می شوند. به عنوان مثال، یک حصار می‌تواند حاوی دو مقدار sync_pt باشد که نشان‌دهنده زمانی است که دو مصرف‌کننده تصویر جداگانه خواندن یک بافر را انجام می‌دهند. هنگامی که حصار علامت داده می شود، تولیدکنندگان تصویر می دانند که مصرف هر دو مصرف کننده تمام شده است.

حصارها مانند مقادیر sync_pt شروع به فعال کرده و بر اساس وضعیت نقاطشان تغییر حالت می دهند. اگر همه مقادیر sync_pt سیگنال شوند، sync_fence سیگنال می شود. اگر یک sync_pt در حالت خطا قرار گیرد، کل sync_fence یک حالت خطا دارد.

عضویت در sync_fence پس از ایجاد حصار غیر قابل تغییر است. برای به دست آوردن بیش از یک نقطه در یک حصار، یک ادغام انجام می شود که در آن نقاط از دو حصار مجزا به حصار سوم اضافه می شود. اگر یکی از آن نقاط در حصار مبدأ علامت داده شد و دیگری نبود، حصار سوم نیز در حالت علامت گذاری نخواهد بود.

برای پیاده سازی همگام سازی صریح، موارد زیر را ارائه دهید:

  • یک زیرسیستم فضای هسته که چارچوب همگام سازی را برای یک درایور سخت افزاری خاص پیاده سازی می کند. درایورهایی که باید از حصار آگاه باشند، عموماً هر چیزی هستند که به Hardware Composer دسترسی پیدا می کند یا با آن ارتباط برقرار می کند. فایل های کلیدی عبارتند از:
    • پیاده سازی اصلی:
      • kernel/common/include/linux/sync.h
      • kernel/common/drivers/base/sync.c
    • مستندات در kernel/common/Documentation/sync.txt
    • کتابخانه برای ارتباط با فضای هسته در platform/system/core/libsync
  • فروشنده باید حصارهای همگام سازی مناسب را به عنوان پارامترهای توابع validateDisplay() و presentDisplay() در HAL ارائه کند.
  • دو افزونه GL مرتبط با حصار ( EGL_ANDROID_native_fence_sync و EGL_ANDROID_wait_sync ) و پشتیبانی از حصار در درایور گرافیک.

مطالعه موردی: درایور نمایشگر را پیاده سازی کنید

برای استفاده از API که از عملکرد همگام سازی پشتیبانی می کند، یک درایور نمایشگر ایجاد کنید که دارای عملکرد بافر نمایشگر باشد. قبل از اینکه چارچوب همگام‌سازی وجود داشته باشد، این تابع اشیاء 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 پیچیده تر است. هنگام قرار دادن بافر روی نمایشگر، بافر با حصاری همراه است که نشان می دهد چه زمانی بافر آماده خواهد شد. می توانید پس از پاک شدن حصار صف بکشید و کار را آغاز کنید.

صف کشیدن و شروع کار بعد از پاک شدن حصار مانع هیچ چیز نمی شود. شما بلافاصله حصار خود را برمی گردانید، که تضمین می کند چه زمانی بافر از صفحه نمایش خاموش می شود. همانطور که بافرها را در صف قرار می دهید، کرنل وابستگی ها را با چارچوب همگام سازی فهرست می کند:

/*
 * 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);

ادغام همگام سازی

این بخش نحوه ادغام چارچوب همگام سازی هسته-فضای را با بخش های فضای کاربران چارچوب اندروید و درایورهایی که باید با یکدیگر ارتباط برقرار کنند، توضیح می دهد. اشیاء فضای هسته به عنوان توصیفگر فایل در فضای کاربر نمایش داده می شوند.

کنوانسیون های یکپارچه سازی

از قراردادهای رابط Android HAL پیروی کنید:

  • اگر API یک توصیفگر فایل ارائه می‌کند که به sync_pt اشاره دارد، درایور فروشنده یا HAL با استفاده از API باید توصیفگر فایل را ببندد.
  • اگر درایور فروشنده یا HAL یک توصیفگر فایل حاوی sync_pt را به یک تابع API ارسال کند، درایور فروشنده یا HAL نباید توصیفگر فایل را ببندد.
  • برای ادامه استفاده از توصیفگر فایل حصار، راننده فروشنده یا HAL باید توصیفگر را کپی کند.

یک شیء حصار هر بار که از BufferQueue عبور می کند تغییر نام می یابد. پشتیبانی از حصار هسته به حصارها امکان می‌دهد رشته‌هایی برای نام‌ها داشته باشند، بنابراین چارچوب همگام‌سازی از نام پنجره و شاخص بافری که برای نام‌گذاری حصار در صف قرار می‌گیرد، مانند 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 به جای CPU، امکان توقف در سمت GPU را فراهم می کند، و باعث می شود GPU منتظر EGLSyncKHR باشد. برنامه افزودنی EGL_ANDROID_wait_sync مانند برنامه افزودنی EGL_KHR_wait_sync است.

برای استفاده مستقل از این افزونه ها، پسوند EGL_ANDROID_native_fence_sync را به همراه پشتیبانی از هسته مرتبط پیاده سازی کنید. سپس، برنامه افزودنی EGL_ANDROID_wait_sync را در درایور خود فعال کنید. پسوند EGL_ANDROID_native_fence_sync از یک نوع شیء حصار اصلی EGLSyncKHR تشکیل شده است. در نتیجه، برنامه‌های افزودنی که برای انواع شی EGLSyncKHR موجود اعمال می‌شوند، لزوماً برای اشیاء EGL_ANDROID_native_fence اعمال نمی‌شوند و از تعاملات ناخواسته جلوگیری می‌کنند.

پسوند EGL_ANDROID_native_fence_sync از یک ویژگی توصیفگر فایل حصار بومی متناظر استفاده می‌کند که فقط در زمان ایجاد تنظیم می‌شود و نمی‌توان مستقیماً از یک شی همگام‌سازی موجود به‌طور مستقیم از آن درخواست کرد. این ویژگی را می توان روی یکی از دو حالت تنظیم کرد:

  • یک توصیف‌گر فایل حصار معتبر، توصیف‌گر فایل حصار Android موجود را در یک شی EGLSyncKHR می‌پیچد.
  • -1 یک توصیفگر فایل حصار اندروید بومی را از یک شی EGLSyncKHR ایجاد می کند.

از فراخوانی تابع DupNativeFenceFD() برای استخراج شی EGLSyncKHR از توصیفگر فایل حصار اصلی Android استفاده کنید. این همان نتیجه جستجوی ویژگی set است، اما به این قرارداد پایبند است که گیرنده حصار را می‌بندد (از این رو عملیات تکراری). در نهایت، از بین بردن شی EGLSyncKHR باعث بسته شدن ویژگی حصار داخلی می شود.

یکپارچه سازی آهنگساز سخت افزار

Hardware Composer سه نوع حصار همگام سازی را مدیریت می کند:

  • حصارهای Acquire به همراه بافرهای ورودی به فراخوانی setLayerBuffer و setClientTarget منتقل می شوند. اینها یک نوشتن معلق در بافر را نشان می دهند و باید قبل از اینکه SurfaceFlinger یا HWC برای خواندن از بافر مرتبط برای انجام ترکیب، سیگنال دهند.
  • حصارهای انتشار پس از تماس با presentDisplay با استفاده از تماس getReleaseFences بازیابی می شوند. اینها یک خواندن معلق از بافر قبلی در همان لایه را نشان می دهند. حصار رهاسازی سیگنال می دهد که HWC دیگر از بافر قبلی استفاده نمی کند زیرا بافر فعلی جایگزین بافر قبلی روی نمایشگر شده است. حصارهای انتشار به همراه بافرهای قبلی که در ترکیب فعلی جایگزین خواهند شد به برنامه بازگردانده می شوند. قبل از نوشتن محتوای جدید در بافری که به آن بازگردانده شده است، برنامه باید صبر کند تا حصار آزادسازی سیگنال دهد.
  • حصارهای حاضر ، یکی در هر فریم، به عنوان بخشی از تماس با presentDisplay بازگردانده می شوند. حصارهای فعلی نشان دهنده زمانی است که ترکیب این قاب کامل شده است، یا به طور متناوب، زمانی که نتیجه ترکیب بندی قاب قبلی دیگر مورد نیاز نیست. برای نمایشگرهای فیزیکی، presentDisplay حصارهای فعلی را هنگامی که قاب فعلی روی صفحه ظاهر می شود، برمی گرداند. پس از بازگرداندن حصارهای فعلی، در صورت وجود، می توانید دوباره به بافر هدف SurfaceFlinger بنویسید. برای نمایشگرهای مجازی، حصارهای موجود زمانی برمی گردند که خواندن از بافر خروجی ایمن باشد.