מסגרת סנכרון

מסגרת הסנכרון מתארת ​​במפורש תלות בין פעולות אסינכרוניות שונות במערכת הגרפיקה אנדרואיד. המסגרת מספקת API המאפשר לרכיבים לציין מתי משחררים מאגרים. המסגרת מאפשרת גם להעביר פרימיטיבים של סנכרון בין דרייברים מהקרנל למרחב המשתמש ובין תהליכי מרחב המשתמש עצמם.

לדוגמה, יישום עשוי לעמוד בתור עבודה לביצוע ב-GPU. ה-GPU מתחיל לצייר את התמונה הזו. למרות שהתמונה עדיין לא נמשכה לזיכרון, מצביע החיץ מועבר לקומפוזיטור החלון יחד עם גדר שמציינת מתי תסתיים עבודת ה-GPU. מרכיב החלון מתחיל בעיבוד מבעוד מועד ומעביר את העבודה לבקר התצוגה. באופן דומה, עבודת המעבד נעשית מבעוד מועד. ברגע שה-GPU מסתיים, בקר התצוגה מציג מיד את התמונה.

מסגרת הסנכרון גם מאפשרת למיישמים למנף משאבי סנכרון ברכיבי החומרה שלהם. לבסוף, המסגרת מספקת נראות לתוך צינור הגרפיקה כדי לסייע באיתור באגים.

סנכרון מפורש

סנכרון מפורש מאפשר ליצרנים ולצרכנים של מאגרים גרפיים לאותת כאשר הם מסיימים להשתמש במאגר. סנכרון מפורש מיושם ב-kernel-space.

היתרונות של סנכרון מפורש כוללים:

  • פחות שונות בהתנהגות בין מכשירים
  • תמיכה טובה יותר באגים
  • מדדי בדיקה משופרים

למסגרת הסינכרון יש שלושה סוגי אובייקטים:

  • sync_timeline
  • sync_pt
  • sync_fence

sync_timeline

sync_timeline הוא ציר זמן שהולך וגדל באופן מונוטוני שעל הספקים ליישם עבור כל מופע של מנהלי התקנים, כגון הקשר GL, בקר תצוגה או 2D bliter. sync_timeline סופר משימות שנשלחו לליבה עבור חומרה מסוימת. sync_timeline מספק ערבויות לגבי סדר הפעולות ומאפשר יישומים ספציפיים לחומרה.

פעל לפי ההנחיות הבאות בעת יישום sync_timeline :

  • ספק שמות שימושיים לכל מנהלי ההתקן, קווי הזמן והגדרות כדי לפשט את ניפוי הבאגים.
  • הטמע את האופרטורים timeline_value_str ו- pt_value_str זמן כדי להפוך את פלט ניפוי הבאגים לקריאה יותר.
  • הטמיע את ה-fill 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 (כגון עבור בקר התצוגה ו-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 של Android:

  • אם ה-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 מספק דרך לעטוף או ליצור מתארי קבצים מקוריים של גדר אנדרואיד באובייקטים של EGLSyncKHR .
  • EGL_ANDROID_wait_sync מאפשר עמידה בצד ה-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 משתמשת בתכונה מקורית של מתאר קובץ גדר שניתן להגדיר רק בזמן היצירה ולא ניתן לבצע שאילתה ישירות הלאה מאובייקט סנכרון קיים. ניתן להגדיר תכונה זו לאחד משני מצבים:

  • מתאר קובץ גדר חוקי עוטף מתאר קובץ גדר אנדרואיד מקורי באובייקט EGLSyncKHR .
  • -1 יוצר מתאר קובץ גדר אנדרואיד מקורי מאובייקט EGLSyncKHR .

השתמש בקריאת הפונקציה DupNativeFenceFD() כדי לחלץ את האובייקט EGLSyncKHR מתאר קובץ הגדר המקורי של Android. יש לזה אותה תוצאה כמו שאילתה על תכונת הסט, אך עומדת במוסכמה לפיה הנמען סוגר את הגדר (ומכאן הפעולה הכפולה). לבסוף, השמדת אובייקט EGLSyncKHR סוגרת את תכונת הגדר הפנימית.

שילוב חומרה מלחין

ה- Hardware Composer מטפל בשלושה סוגים של גדרות סנכרון:

  • גדרות רכישה מועברות יחד עם מאגרי קלט setLayerBuffer ו- setClientTarget . אלה מייצגים כתיבה ממתינה למאגר וחייבים לאותת לפני שה-SurfaceFlinger או ה-HWC מנסים לקרוא מהמאגר המשויך לביצוע קומפוזיציה.
  • גדרות שחרור מאוחזרות לאחר הקריאה ל- presentDisplay באמצעות הקריאה getReleaseFences . אלה מייצגים קריאה ממתינה מהמאגר הקודם באותה שכבה. גדר שחרור מאותתת כאשר ה-HWC אינו משתמש יותר במאגר הקודם מכיוון שהמאגר הנוכחי החליף את המאגר הקודם בתצוגה. גדרות שחרור מועברות חזרה לאפליקציה יחד עם המאגרים הקודמים שיוחלפו במהלך ההרכב הנוכחי. על האפליקציה להמתין עד שגדר שחרור מאותתת לפני כתיבת תוכן חדש למאגר שהוחזר לה.
  • גדרות נוכחות מוחזרות, אחת לכל מסגרת, כחלק מהקריאה ל- presentDisplay . גדרות נוכחיות מייצגות מתי ההרכב של המסגרת הזו הושלם, או לחילופין, כאשר אין עוד צורך בתוצאת ההרכב של המסגרת הקודמת. עבור תצוגות פיזיות, presentDisplay מחזירה גדרות נוכחות כאשר המסגרת הנוכחית מופיעה על המסך. לאחר החזרת גדרות קיימות, זה בטוח לכתוב שוב למאגר היעד של SurfaceFlinger, אם ישים. עבור תצוגות וירטואליות, גדרות נוכחיות מוחזרות כאשר זה בטוח לקרוא ממאגר הפלט.