אופטימיזציה של Godot Engine Vulkan ל-Android

תמונת הקמע של Godot Engine

סקירה כללית

Godot Engine הוא מנוע משחקים פופולרי בקוד פתוח לפלטפורמות מרובות, עם תמיכה חזקה ב-Android. אפשר להשתמש ב-Godot כדי ליצור משחקים כמעט בכל ז'אנר, והוא תומך גם בגרפיקה דו-ממדית וגם בגרפיקה תלת-ממדית. בגרסה 4 של Godot נוספה מערכת עיבוד חדשה עם תכונות מתקדמות ליצירת גרפיקה באיכות גבוהה. המרת הגרפיקת של Godot 4 מיועדת לממשקי API מודרניים של גרפיקה, כמו Vulkan.

קרן Godot שיתפה פעולה עם מומחי האופטימיזציה של הגרפיקה ב-Forge Interactive ועם Google כדי לנתח ולשפר את המרת הגרפיקת Vulkan ב-Godot 4, ולמזג את האופטימיזציות האלה בחזרה למאגר הפרויקט. האופטימיזציות עוזרות למפתחים לשפר את ה-renderers המותאמים אישית של Vulkan ב-Android.

שיטת האופטימיזציה והתוצאות

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

בבדיקה נעשה שימוש בכמה ארכיטקטורות פופולריות של GPU ב-Android. אופטימיזציות רבות הביאו לשיפורים כלליים, אבל לחלק מהן הייתה השפעה רבה יותר על ארכיטקטורות ספציפיות של GPU. סך כל פעולות האופטימיזציה הביאו להפחתה כללית של 10%-20% בזמני הרינדור של הפריימים ב-GPU.

אופטימיזציה כללית של Vulkan

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

תמיכה בהיסט דינמי של UBO

כשמקשרים קבוצת מתארים שמכילה אובייקט מאגר אחיד דינמי (UBO), Vulkan מאפשר לציין בפרמטרים של הקישור את ההיסטים הדינמיים ב-UBO. אפשר להשתמש בתכונה הזו כדי לארוז נתונים של כמה פעולות עיבוד תמונה ב-UBO יחיד, ולקשר מחדש את קבוצת התיאורים עם סטייה דינמית שונה כדי לבחור את הנתונים המתאימים לשַדר. המרתר של Godot Vulkan עודכן כך שיהיה אפשר להשתמש בהיסטים דינמיים במקום לאפס את ההיסט תמיד. השיפור הזה מאפשר לבצע אופטימיזציות יעילות בעתיד.

מאגרים של קבוצות של מתארים לינאריים

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

ככל האפשר, מאגרים של קבוצות מאפיינים נוצרים עכשיו כמאגרים לינאריים בלי להגדיר את VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. לאחר מכן, המאגרים לינאריים מתאפסים כמכלול לפי הצורך. העבודה הזו כוללת גם אופטימיזציה נוספת לקישורים של קבוצות של מתארי קבוצות, כשהדבר אפשרי, כדי לצמצם את מספר הקריאות הנפרדות ל-vkCmdBindDescriptorSets().

תמיכה במדגם שאינו ניתן לשינוי

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

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

אופטימיזציה שמתמקדת בניידים

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

האופטימיזציות כוללות:

  • החלפת השימוש בערכי push קבועים גדולים
  • הקצאת מאגר נתונים זמני באופן איטי
  • תמיכה במאגרים מתמידים
  • שינוי של מצב הפענוח של ASTC
  • סיבוב מראש של המסך

החלפת השימוש בערכי push קבועים גדולים

Push constants היא תכונה שמאפשרת להחדיר ערכי קבועים של תוכנית ה-shader הפעילה למאגר הפקודות. קבועי push הם נוחים כי הם לא דורשים יצירה ויישוב של מאגר, והם לא קשורים למאפיינים. עם זאת, ל-push constants יש גודל מקסימלי מוגבל, והם עלולים להשפיע לרעה על הביצועים בחומרה לנייד.

במהלך הבדיקה במכשירי Android, שיפרנו את הביצועים על ידי החלפת השימוש הקבוע ב-push של יותר מ-16 בייטים במאגרים אחידים. בשימוש ב-push constants, הביצועים של שגיאות שהשתמשו ב-16 בייטים או פחות של נתונים קבועים היו טובים יותר. בנוסף לשיקולים של ביצועים, לחומרה גרפית מסוימת יש יישור מינימלי של 64 בייטים למאגרים אחידים, שמפחית את יעילות הזיכרון בגלל הוספת שטח לא מנוצל בהשוואה לשימוש ב-push constants.

הקצאת מאגר נתונים זמני באופן איטי

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

ה-VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT נוסף במהלך היצירה של יעדי הרינדור המתאימים, כמו יעדי הצבע והעומק הראשיים, כדי למנוע הקצאת זיכרון מאגר שלא ישמש לעולם. נמדד חיסכון של כ-50 מגה-בייט של זיכרון RAM בזיהוי עצלות (lazy allocation) בסצנות לדוגמה.

תמיכה במאגר נתונים מתמיד

בחומרה של מכשירים ניידים נעשה שימוש בארכיטקטורת זיכרון מאוחדת (UMA) במקום בהבחנה בין זיכרון RAM ראשי לזיכרון RAM לצורכי גרפיקה. כשזיכרון ה-RAM הראשי וזיכרון ה-RAM של הגרפיקה נפרדים, צריך להעביר נתונים מזיכרון ה-RAM הראשי לזיכרון ה-RAM של הגרפיקה כדי שה-GPU יוכל להשתמש בהם. תהליך ההעברה הזה כבר מוטמע ב-Godot ברינדר של Vulkan באמצעות מאגרי תצוגה מקדימה. בחומרה של UMA,לא צריך מאגר ביניים להעברת נתונים (staging buffer) עבור סוגים רבים של נתונים. גם המעבד וגם המעבד הגרפי יכולים להשתמש בזיכרון. כדי למנוע את הצורך בשלב ההמתנה (staging) ככל האפשר, הטמענו ב-Forge תמיכה במאגרי נתונים זמניים משותפים ועקביים בחומרה נתמכת.

תמונות של סצנה ב-Godot שמוצגות בהן נתוני פרופיל עם מאגרים מתמידים מופעלים ועם מאגרים מתמידים מושבתים.
איור 1. ניתוח ההבדלים בין מאגרים מתמידים שפועלים לבין מאגרים מתמידים מושבתים בסצנה לדוגמה.

שינוי של מצב הפענוח של ASTC

דחיסת טקסטורה ניתנת להתאמה (ASTC) היא הפורמט המועדף לדחיסת טקסטורה מודרנית בחומרה לנייד. במהלך הדחיסה, ברירת המחדל של ה-GPU עשויה לפענוח texel לערכים ביניים עם רמת דיוק גבוהה יותר מהנדרש לדיוק חזותי, וכתוצאה מכך יעילות הטקסטורה תפחת. אם החומרה של היעד תומכת בכך, התוסף VK_EXT_astc_decode_mode משמש לציון ערכים לא מנורמלים של 8 ביט לכל רכיב במהלך פענוח, במקום ערכים של נקודה צפה באורך 16 ביט.

סיבוב מראש של המסך

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

שיפורים בניפוי באגים

בנוסף לביצוע אופטימיזציות של הביצועים, ב-The Forge שיפרו את חוויית ניפוי הבאגים של בעיות גרפיות במעבד הגרפיקה של Godot באמצעות התוספות הבאות:

  • הארכה של תקלה במכשיר
  • מיקומים באתר
  • סמנים לניפוי באגים

הארכה של תקלה במכשיר

כש-GPU נתקל בבעיה במהלך פעולות הרינדור, הנהג של Vulkan יכול להחזיר תוצאה של VK_ERROR_DEVICE_LOST מהקריאה ל-Vulkan API. כברירת מחדל, לא מוצג מידע נוסף על ההקשר של הסיבה לכך שהנהג החזיר את הערך VK_ERROR_DEVICE_LOST. התוסף VK_EXT_device_fault מספק מנגנון שמאפשר לנהג לספק מידע נוסף על אופי השגיאה. נוספה ל-Godot תמיכה בהפעלת התוסף של תקלה במכשיר (אם הוא זמין) ובדיווח על מידע שהוחזר על ידי מנהל ההתקן.

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

סמנים לניפוי באגים

אם הנהג תומך בסמנים לניפוי באגים, הם משמשים למתן שמות למשאבים. כך אפשר לשייך מחרוזות שקריאות למשתמש לפעולות כמו שלבי רינדור ולמשאבים כמו מאגרים וטקסטורות כשמשתמשים בכלי גרפיקה כמו RenderDoc. נוספה תמיכה בהערות של סמני ניפוי באגים למעבד הגרפיקה של Godot ב-Vulkan.

בלוג של Godot Engine – עדכון לגבי שיתוף הפעולה עם Google ו-Forge

בקשת משיכה משותפת בנושא Vulkan ב-Godot Engine