ספריית Android Frame Pacing, שנקראת גם Swappy, היא חלק מ-Android Game SDK. הוא עוזר למשחקי OpenGL ו-Vulkan להשיג רינדור חלק וקצב פריימים נכון ב-Android.
קצב פריימים הוא הסנכרון של הלוגיקה של המשחק ושל לולאת העיבוד שלו עם מערכת המשנה של התצוגה של מערכת ההפעלה ועם חומרת התצוגה הבסיסית. מערכת המשנה של התצוגה ב-Android תוכננה כך שהיא לא תציג ארטיפקטים ויזואליים מסוימים, כמו קריעה. מערכת המשנה של התצוגה מונעת קריעה על ידי הפעולות הבאות:
- אגירת מסגרות קודמות באופן פנימי
- זיהוי הגשות מאוחרות של פריים
- המשך הצגת הפריים הנוכחי כשמזוהה פריים מאוחר
זמני תצוגה לא עקביים של פריימים נגרמים כתוצאה מלולאת עיבוד של משחק שפועלת בקצב שונה מזה שחומרת התצוגה המקורית תומכת בו. בעיות מתעוררות כשלולאת העיבוד של המשחק פועלת לאט מדי עבור חומרת התצוגה הבסיסית, מה שמוביל לזמני תצוגה לא עקביים. לדוגמה, כשמשחק שפועל ב-30 fps מנסה לבצע רינדור במכשיר שתומך באופן טבעי ב-60 fps, לולאת הרינדור של המשחק גורמת לכך שפריים חוזר נשאר על המסך למשך 16 ms נוספים. סוג כזה של ניתוק יוצר חוסר עקביות משמעותי בזמני הפריים, כמו 33 ms, 16 ms ו-49 ms. סצנות מורכבות מדי מחמירות את הבעיה הזו כי הן גורמות לפריים להישאר על המסך למשך זמן ארוך יותר.
ספריית Frame Pacing מבצעת את המשימות הבאות:
- מפצה על גמגום שנובע מפריימים קצרים במשחק.
- הוספת חותמות זמן למצגת כדי שהפריימים יוצגו בזמן, ולא מוקדם מדי.
- משתמש בתוספי חותמת זמן של הצגה
EGL_ANDROID_presentation_time
ו-VK_GOOGLE_display_timing
.
- משתמשים ב-sync fences עבור פריימים ארוכים שמובילים לגמגום ולחביון.
- הפונקציה מוסיפה לאפליקציה מצבי המתנה. כך צינור העברת הנתונים של התצוגה יכול להתעדכן, במקום לאפשר ללחץ חוזר להצטבר.
- נעשה שימוש ב-sync fences (
EGL_KHR_fence_sync
ו-VkFence
).
- בוחר קצב רענון כדי לספק גמישות והצגה חלקה, אם המכשיר תומך בכמה קצבי רענון.
- מספק נתונים סטטיסטיים לניפוי באגים וליצירת פרופילים באמצעות frame stats.
במאמר מצבי הפעלה נתמכים מוסבר איך להגדיר את הספרייה כך שתפעל במצבים שונים בהתאם לצרכים שלכם.
כדי להטמיע באמצעות כלי לרינדור OpenGL או כלי לרינדור Vulkan, אפשר לעיין במאמרים הבאים:
מידע נוסף זמין במאמר בנושא ספריית Frame Pacing.
התערבות להגבלת קצב הפריימים לשנייה
התערבות להגבלת קצב הפריימים (FPS) מאפשרת למשחקים לפעול בקצב פריימים מתאים, באמצעות שינויים בצד הפלטפורמה בלבד, בלי לדרוש פעולה מצד המפתחים.
ההטמעה של אמצעי ההתערבות להגבלת קצב הפריימים (FPS) משתמשת ברכיבים הבאים.
GameManagerService
רכיב
GameManagerService שומר את כל המידע על מצב המשחק וההתערבות במשחק, לפי משתמש ולפי משחק. נתוני ה-FPS מאוחסנים ב-GameManagerService עם נתוני התערבות אחרים, כמו גורם ההקטנה של הרזולוציה, במיפוי <PACKAGE_NAME, Interventions>
לכל פרופיל משתמש.
הגישה לפרטי ה-FPS מתבצעת כשמשנים את מצב המשחק או כשמעדכנים את ההתערבות. A
UID
הוא ייחודי לכל PACKAGE_NAME
ולכל משתמש, ואפשר לתרגם אותו לזוג <UID, Frame Rate>
כדי לשלוח אותו ל-SurfaceFlinger.
SurfaceFlinger
הרכיב SurfaceFlinger כבר תומך בהגבלת קצב הפריימים של אפליקציה, כל עוד קצב הפריימים הוא מחלק של קצב הרענון של המסך. במקרה של VSync, SurfaceFlinger בודק את התוקף של ה-VSync עבור האפליקציה המוגבלת על ידי אימות של התאמה בין חותמת הזמן של ה-VSync לבין קצב הפריימים של האפליקציה. אם קצב הפריימים לא מסונכרן עם VSync, SurfaceFlinger מעכב את הפריים עד שקצב הפריימים ו-VSync מסונכרנים.
באיור הבא מתוארת האינטראקציה בין GameManagerService לבין SurfaceFlinger:

איור 1. אינטראקציה בין GameServiceManager לבין SurfaceFlinger.
ה-SurfaceFinger שומר על מיפוי של זוג <UID, Frame Rate>
כדי להגדיר עדיפות חדשה להגבלת קצב הפריימים. הערך UID
הוא ייחודי לכל משתמש ולכל משחק, כך שלכל משתמש במכשיר יחיד יכולות להיות הגדרות שונות של קצב פריימים באותו משחק. כדי להגביל את קצב הפריימים של משחק, GameServiceManager קורא ל-SurfaceFlinger כדי לבטל את קצב הפריימים עבור UID. באמצעות המנגנון הזה, SurfaceFlinger מעדכן את המיפוי בכל פעם שמצב המשחק משתנה או שההתערבות מתעדכנת. SurfaceFlinger מטפל בשינוי של FPS על ידי הצמדת מאגרי נתונים בהתאם.
מידע נוסף על הגבלת קצב הפריימים (FPS) זמין במאמר בנושא הגבלת קצב הפריימים (FPS).