הטמעת Vulkan

Vulkan הוא API חוצה פלטפורמות עם תקורה נמוכה, לגרפיקה תלת-ממדית עם ביצועים גבוהים. בדומה ל-OpenGL ES (GLES),‏ Vulkan מספקת כלים ליצירת גרפיקה באיכות גבוהה בזמן אמת באפליקציות. היתרונות של שימוש ב-Vulkan כוללים הפחתה בעומס יתר של CPU ותמיכה בשפה SPIR-V Binary Intermediate.

כדי להטמיע את Vulkan בהצלחה, המכשיר צריך לכלול:

  • הטוען של Vulkan, שמסופק על ידי Android.
  • מנהל התקן של Vulkan, שמסופק על ידי מערכות על שבב (SoC) כמו GPU IHV, שמטמיע את Vulkan API. כדי לתמוך בפונקציונליות של Vulkan, במכשיר Android צריך להיות חומרה של GPU עם יכולת Vulkan והמנהל התקן המשויך. ה-GPU צריך לתמוך גם ב-GLES 3.1 ומעלה. כדי לבקש תמיכה במנהלי התקנים, צריך לפנות לספק ה-SoC.

אם מכשיר כולל מנהל התקן של Vulkan, המכשיר צריך להצהיר על תכונות המערכת FEATURE_VULKAN_HARDWARE_LEVEL ו-FEATURE_VULKAN_HARDWARE_VERSION, עם גרסאות שמשקפות בצורה מדויקת את היכולות של המכשיר. כך אפשר לוודא שהמכשיר עומד בדרישות של מסמך הגדרת התאימות (CDD).

Vulkan loader

הכלי Vulkan loader platform/frameworks/native/vulkan הוא הממשק העיקרי בין אפליקציות Vulkan לבין מנהל ההתקן של Vulkan במכשיר. הטוען של Vulkan מותקן ב-/system/lib[64]/libvulkan.so. הטוען מספק את נקודות הכניסה של ליבת Vulkan API, את נקודות הכניסה של התוספים הנדרשים על ידי Android CDD, ועוד הרבה תוספים אופציונליים. תוספים של Window System Integration (WSI) מיוצאים על ידי טוען המערכת ומיושמים בעיקר בטוען המערכת ולא במנהל ההתקן. הטוען תומך גם בספירה ובטעינה של שכבות שיכולות לחשוף תוספים נוספים וליירט קריאות API ליבה בדרך אל מנהל ההתקן.

ה-NDK כולל ספריית stub‏ libvulkan.so לקישור. הספרייה מייצאת את אותם סמלים כמו טוען התגים. האפליקציות קוראות לפונקציות שמיוצאות מהספרייה האמיתית libvulkan.so כדי להיכנס לפונקציות של trampoline בטוען, שמופצות לשכבה או לדרייבר המתאימים על סמך הארגומנט הראשון שלהן. הקריאה vkGet*ProcAddr() מחזירה את מצביעי הפונקציה שאליהם מנתבים את ה-trampolines (כלומר, היא קוראת ישירות לקוד הליבה של ה-API). התקשרות דרך מצביעי הפונקציות, ולא דרך הסמלים המיוצאים, יעילה יותר כי היא מדלגת על ה-trampoline והשיגור.

ספירה וטעינה של מנהלי התקנים

כשיוצרים את תמונת המערכת, מערכת Android מצפה שהמערכת תדע אילו מעבדי GPU זמינים. טוען המערכת משתמש במנגנון HAL הקיים ב-hardware.h כדי לגלות ולטעון את מנהל ההתקן. הנתיבים המועדפים למנהלי התקנים של Vulkan ב-32 ביט וב-64 ביט הם:

/vendor/lib/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib/hw/vulkan.<ro.board.platform>.so
/vendor/lib64/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib64/hw/vulkan.<ro.board.platform>.so

ב-Android מגרסה 7.0 ואילך, נגזרת Vulkan‏ hw_module_t עוטפת מבנה hw_module_t יחיד. נתמך רק דרייבר אחד, והמחרוזת הקבועה HWVULKAN_DEVICE_0 מועברת אל open().

הנגזרת של Vulkan hw_device_t מתאימה למנהל התקן יחיד שיכול לתמוך בכמה מכשירים פיזיים. המבנה של hw_device_t יכול להתרחב גם לפונקציות של ייצוא vkGetGlobalExtensionProperties(), vkCreateInstance() ו-vkGetInstanceProcAddr(). הטוען יכול למצוא את כל הפונקציות האחרות VkInstance(), VkPhysicalDevice() ו-vkGetDeviceProcAddr() על ידי קריאה ל-vkGetInstanceProcAddr() של המבנה hw_device_t.

מגרסה Android 15, טוען המערכת תומך ב-APEX כדי לטעון את מנהל ההתקן של Vulkan. מגדירים את ro.vulkan.apex לשם של Vulkan APEX כדי לטעון את Vulkan מ-APEX.

גילוי וטעינה של שכבות

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

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

תרחישים לדוגמה לשימוש בשכבות:

  • שכבות בזמן הפיתוח – אסור להתקין שכבות אימות ו-shims לכלי מעקב/פרופילים/ניפוי באגים בקובץ האימג' של המערכת במכשירי ייצור. שכבות אימות ו-shims לכלים של מעקב, פרופיל וניפוי באגים צריכים להיות ניתנים לעדכון ללא תמונת מערכת. מפתחים שרוצים להשתמש באחת מהשכבות האלה במהלך הפיתוח יכולים לשנות את חבילת האפליקציה, למשל על ידי הוספת קובץ לספריית הספריות המקוריות שלהם. מהנדסי IHV ו-OEM שרוצים לאבחן כשלים בשליחת אפליקציות שלא ניתן לשנות, אמורה להיות להם גישה ל-builds של תמונת המערכת שאינם בייצור (עם הרשאות root), אלא אם ניתן לבצע באפליקציות האלה ניפוי באגים. מידע נוסף זמין במאמר Vulkan validation layers on Android.
  • שכבות שירות – השכבות האלה חושפות תוספים, כמו שכבה שמטמיעה מנהל זיכרון לזיכרון המכשיר. המפתחים בוחרים את השכבות ואת הגרסאות של השכבות האלה שבהן הם רוצים להשתמש באפליקציה שלהם. אפליקציות שונות שמשתמשות באותה שכבה עדיין יכולות להשתמש בגרסאות שונות. המפתחים בוחרים אילו מהשכבות האלה ייכללו בחבילת האפליקציה שלהם.
  • שכבות מוזרקות (משתמעות) – כוללות שכבות כמו שכבות-על של קצב פריימים, רשתות חברתיות ומשגרי משחקים שסופקו על ידי המשתמש או על ידי אפליקציה אחרת כלשהי ללא ידיעת האפליקציה או הסכמתה. הקבצים האלה מפרים את מדיניות האבטחה של Android ואין להם תמיכה.

באפליקציות שלא ניתן לבצע בהן ניפוי באגים, טוען השכבות מחפש שכבות רק בספרייה המקורית של האפליקציה ומנסה לטעון כל ספרייה עם שם שתואם לתבנית מסוימת (לדוגמה, libVKLayer_foo.so).

עבור אפליקציות שאפשר לבצע בהן ניפוי באגים, טוען השכבות מחפש שכבות ב-/data/local/debug/vulkan ומנסה לטעון כל ספרייה שתואמת לתבנית מסוימת.

ב-Android אפשר להעביר שכבות עם שינויים בסביבת הבנייה בין Android לפלטפורמות אחרות. פרטים על הממשק בין השכבות לבין טוען השכבות זמינים במאמר Architecture of the Vulkan Loader Interfaces. שכבות האימות שמתחזקת Khronos מתארחות בשכבות האימות של Vulkan.

גרסאות ויכולות של Vulkan API

בטבלה הבאה מפורטות גרסאות של Vulkan API לכמה מהדורות של Android.
גרסת Android גרסת Vulkan
Android 13 ‫Vulkan 1.3
‫Android 9 Vulkan 1.1
‫Android 7 Vulkan 1.0

סקירה כללית של הפונקציונליות של Vulkan 1.3

ב-Vulkan 1.3, מספר תוספים שהיו אופציונליים בעבר הופכים לחלק מהפונקציונליות הבסיסית של Vulkan. חלק גדול מהפונקציונליות הזו כלול במטרה להגביר את השליטה והגרנולריות בממשק התכנות של Vulkan. אין יותר צורך במופעים של מעבר רינדור חד-שלבי באובייקטים של מעבר רינדור או במאגרי מסגרות. אפשר לצמצם את המספר הכולל של אובייקטים של מצב צינור העיבוד, ובוצע שיפוץ של הסנכרון ב-API. ל-Vulkan 1.3 יש את אותן דרישות חומרה כמו ל-Vulkan 1.2,‏ 1.1 ו-1.0, ורוב ההטמעה נמצאת במנהל ההתקן הגרפי הספציפי ל-SoC, ולא במסגרת.

התכונות הכי חשובות של Vulkan 1.3 ל-Android הן:

  • תמיכה במופעים של מעבר רינדור חד-שלבי
  • תמיכה בהפסקת הפעלה מיידית של הצללה
  • גרנולריות מדויקת יותר לגבי יצירה, שיתוף ובקרה של צינורות

בנוסף, Vulkan 1.3 כולל כמה תכונות קטנות יותר ושיפורים בשימושיות של ה-API. כל השינויים שבוצעו ב-Core Vulkan API עם תיקון משני 1.3 מפורטים בכתובת Core Revisions (Vulkan 1.3).

סקירה כללית של הפונקציונליות של Vulkan 1.2

ב-Vulkan 1.2 הוספנו מספר תכונות והרחבות שמפשטות את ממשק ה-API. זה כולל מודל זיכרון מאוחד ומידע נוסף שאפשר לשלוף ממנהל התקן. ל-Vulkan 1.2 יש את אותן דרישות חומרה כמו ל-Vulkan 1.0 ו-1.1. כל ההטמעה מתבצעת במנהל ההתקן הגרפי הספציפי ל-SoC, ולא במסגרת.

התכונה הכי חשובה ב-Vulkan 1.2 ל-Android היא התמיכה באחסון של 8 ביט.

‫Vulkan 1.2 כולל גם כמה תכונות קטנות יותר ושיפורים בשימושיות של ה-API. כל השינויים שבוצעו ב-Vulkan API עם עדכון משני 1.2 מפורטים בעדכונים מרכזיים (Vulkan 1.2).

סקירה כללית של הפונקציונליות של Vulkan 1.1

‫Vulkan 1.1 כולל תמיכה בהפעלה הדדית של זיכרון/סנכרון, שמאפשרת ליצרני ציוד מקורי (OEM) לתמוך ב-Vulkan 1.1 במכשירים. בנוסף, תאימות של זיכרון/סנכרון מאפשרת למפתחים לקבוע אם יש תמיכה ב-Vulkan 1.1 במכשיר, ולהשתמש בה ביעילות אם יש תמיכה. ל-Vulkan 1.1 יש את אותן דרישות חומרה כמו ל-Vulkan 1.0, אבל רוב ההטמעה נמצאת במנהל ההתקן הגרפי הספציפי ל-SOC, ולא ב-framework.

התכונות הכי חשובות של Vulkan 1.1 ל-Android הן:

  • תמיכה בייבוא וייצוא של מאגרי זיכרון ואובייקטים של סנכרון מחוץ ל-Vulkan (לפעולה הדדית עם מצלמה, רכיבי codec ו-GLES)
  • תמיכה בפורמטים של YCbCr

‫Vulkan 1.1 כולל גם כמה תכונות קטנות יותר ושיפורים בשימושיות של ה-API. כל השינויים שבוצעו ב-Core Vulkan API עם תיקון משני 1.1 מפורטים בכתובת Core Revisions (Vulkan 1.1).

בחירת תמיכה ב-Vulkan

מכשירי Android צריכים לתמוך בערכת התכונות המתקדמת ביותר של Vulkan שזמינה, בתנאי שהם תומכים ב-ABI של 64 ביט ואין להם זיכרון נמוך.

מכשירים שמופעלים עם Android מגרסה 13 ואילך צריכים לתמוך ב-Vulkan 1.3.

מכשירים שמופעלים באמצעות Android מגרסה 10 ואילך צריכים לתמוך ב-Vulkan 1.1.

מכשירים אחרים יכולים לתמוך ב-Vulkan 1.3,‏ 1.2 ו-1.1.

תמיכה בגרסת Vulkan

מכשיר Android תומך בגרסת Vulkan אם מתקיימים התנאים הבאים:

  1. מוסיפים מנהל התקן של Vulkan שתומך בגרסת Vulkan הרלוונטית (אחת מהגרסאות 1.3,‏ 1.1 או 1.0) בנוסף לדרישות ה-CDD הנוספות של גרסת Android. אפשרות אחרת היא לעדכן מנהל התקן קיים של Vulkan עם מספר גרסה נמוך יותר של Vulkan.
  2. ב-Vulkan 1.3 או 1.1, מוודאים שתכונת המערכת שמוחזרת על ידי מנהל החבילות מחזירה true לגרסת Vulkan הנכונה.
    • ב-Vulkan 1.3, התכונה היא PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000).
    • ב-Vulkan 1.1 התכונה היא PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000).
    מנהל החבילות יחזיר true עבור Vulkan 1.3 ו-Vulkan 1.1 על ידי הוספת כלל, כפי שמוצג בהמשך, לקובץ device.mk המתאים.
    • מוסיפים את השורות הבאות ל-Vulkan 1.3:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_3.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
      
    • מוסיפים את השורה הבאה ל-Vulkan 1.1:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_1.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml

פרופיל Baseline של Android‏ (ABP)

מומלץ שכל מכשירי Android יתאימו לפרופיל Android Baseline 2022 העדכני, כפי שמתואר במדריך לפרופיל Android Baseline.

כל מכשיר שתומך ב-Android 14 ומעלה וב-Vulkan API, חייב לעמוד בכל הפונקציונליות שמוגדרת בפרופיל Android Baseline 2021. הרשימה המלאה של הפונקציות הנדרשות מפורטת בקובץ json של פרופיל Vulkan, אבל קבוצת משנה מרכזית של הפונקציות הנדרשות כוללת:

  • דחיסת טקסטורות באמצעות ASTC ו-ETC.
  • מרחבי צבע משתנים דרך VK_EXT_swapchain_colorspace.
  • הצללה לדוגמה ואינטרפולציה של דגימות מרובות באמצעות sampleRateShading.

שילוב של מערכת חלונות (WSI)

ב-libvulkan.so, הנהג מטמיע את התוספים הבאים של שילוב מערכת חלונות (WSI):

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, הוטמעה ב-Vulkan 1.1 ב-Android 10 בלבד
  • VK_GOOGLE_display_timing, הוטמעה לכל גרסת Vulkan ב-Android 10

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

דגלי שימוש ב-Gralloc

יכול להיות שיישומים של Vulkan יצטרכו להקצות מאגרי swapchain עם דגלי שימוש פרטיים ב-Gralloc שמוגדרים על ידי היישום. כשיוצרים swapchain, מערכת Android מבקשת מהדרייבר לתרגם את הפורמט המבוקש ואת דגלי השימוש בתמונה לדגלי שימוש ב-Gralloc באמצעות קריאה לפונקציה:

typedef enum VkSwapchainImageUsageFlagBitsANDROID {
    VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID = 0x00000001,
    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkSwapchainImageUsageFlagBitsANDROID;
typedef VkFlags VkSwapchainImageUsageFlagsANDROID;

VkResult VKAPI vkGetSwapchainGrallocUsage2ANDROID(
    VkDevice                          device,
    VkFormat                          format,
    VkImageUsageFlags                 imageUsage,
    VkSwapchainImageUsageFlagsANDROID swapchainUsage,
    uint64_t*                         grallocConsumerUsage,
    uint64_t*                         grallocProducerUsage
);

הפרמטרים format ו-imageUsage נלקחים מהמבנה VkSwapchainCreateInfoKHR. מנהל ההתקן צריך למלא את *grallocConsumerUsage ואת *grallocProducerUsage בדגלי השימוש של Gralloc שנדרשים לפורמט ולשימוש. דגלי השימוש שמוחזרים על ידי מנהל ההתקן משולבים עם דגלי השימוש שהצרכן של swapchain מבקש כשמקצים מאגרי נתונים.

ב-Android מגרסה 7.x, מתבצעת קריאה לגרסה קודמת של VkSwapchainImageUsageFlagsANDROID(), בשם vkGetSwapchainGrallocUsageANDROID(). ‫Android מגרסה 8.0 ואילך מוציא משימוש את vkGetSwapchainGrallocUsageANDROID() אבל עדיין קורא ל-vkGetSwapchainGrallocUsageANDROID() אם vkGetSwapchainGrallocUsage2ANDROID() לא מסופק על ידי מנהל ההתקן:

VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
    VkDevice            device,
    VkFormat            format,
    VkImageUsageFlags   imageUsage,
    int*                grallocUsage
);

vkGetSwapchainGrallocUsageANDROID() לא תומך בדגלים של שימוש ב-swapchain או בדגלים של שימוש מורחב ב-Gralloc.

תמונות עם גיבוי של Gralloc

VkNativeBufferANDROID הוא מבנה של תוסף vkCreateImage ליצירת תמונה שמגובה על ידי מאגר Gralloc. VkNativeBufferANDROID מסופק ל-vkCreateImage() בשרשרת המבנה VkImageCreateInfo. שיחות למספר vkCreateImage() עם VkNativeBufferANDROID מתרחשות במהלך השיחה למספר vkCreateSwapchainKHR. ההטמעה של WSI מקצה את מספר המאגרים המותאמים שנדרשים לשרשרת ההחלפה, ואז יוצרת VkImage לכל אחד מהם:

typedef struct {
    VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
    const void*                 pNext;

    // Buffer handle and stride returned from gralloc alloc()
    buffer_handle_t             handle;
    int                         stride;

    // Gralloc format and usage requested when the buffer was allocated.
    int                         format;
    int                         usage;
    // Beginning in Android 8.0, the usage field above is deprecated and the
    // usage2 struct below was added. The usage field is still filled in for
    // compatibility with Android 7.0 drivers. Drivers for Android 8.0
    // should prefer the usage2 struct, especially if the
    // android.hardware.graphics.allocator HAL uses the extended usage bits.
    struct {
        uint64_t                consumer;
        uint64_t                producer;
    } usage2;
} VkNativeBufferANDROID;

כשיוצרים תמונה שמגובה על ידי Gralloc, ‏VkImageCreateInfo מכיל את הנתונים הבאים:

  .sType               = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
  .pNext               = the above VkNativeBufferANDROID structure
  .imageType           = VK_IMAGE_TYPE_2D
  .format              = a VkFormat matching the format requested for the gralloc buffer
  .extent              = the 2D dimensions requested for the gralloc buffer
  .mipLevels           = 1
  .arraySize           = 1
  .samples             = 1
  .tiling              = VK_IMAGE_TILING_OPTIMAL
  .usage               = VkSwapchainCreateInfoKHR::imageUsage
  .flags               = 0
  .sharingMode         = VkSwapchainCreateInfoKHR::imageSharingMode
  .queueFamilyCount    = VkSwapchainCreateInfoKHR::queueFamilyIndexCount
  .pQueueFamilyIndices = VkSwapchainCreateInfoKHR::pQueueFamilyIndices

ב-Android מגרסה 8.0 ואילך, הפלטפורמה מספקת מבנה הרחבה של VkSwapchainImageCreateInfoKHR בשרשרת VkImageCreateInfo שמועברת אל vkCreateImage כשנדרשים דגלים לשימוש בתמונות של swapchain עבור ה-swapchain. מבנה התוסף מכיל את דגלי השימוש בתמונות של שרשרת ההחלפה:

typedef struct {
    VkStructureType                        sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
    const void*                            pNext;

    VkSwapchainImageUsageFlagsANDROID      usage;
} VkSwapchainImageCreateInfoANDROID;

ב-Android מגרסה 10 ואילך, הפלטפורמה תומכת ב-VK_KHR_swapchain v70, כך שאפליקציית Vulkan יכולה ליצור VkImage שמגובה בזיכרון של swapchain. האפליקציה קודם מתקשרת אל vkCreateImage עם מבנה VkImageSwapchainCreateInfoKHR שמשורשר למבנה VkImageCreateInfo. לאחר מכן האפליקציה קוראת ל-vkBindImageMemory2(KHR) עם מבנה VkBindImageMemorySwapchainInfoKHR שמשורשר למבנה VkBindImageMemoryInfo. הערך imageIndex שצוין במבנה VkBindImageMemorySwapchainInfoKHR חייב להיות אינדקס תקין של תמונה ב-swapchain. בינתיים, הפלטפורמה מספקת מבנה של תוסף VkNativeBufferANDROID עם מידע על מאגר Gralloc תואם לשרשרת VkBindImageMemoryInfo, כדי שהדרייבר יידע לאיזה מאגר Gralloc לקשר את VkImage.

הוספת תמונות

vkAcquireImageANDROID רוכש בעלות על תמונה ב-swapchain ומייבא גדר מקורית עם סימון חיצוני גם לאובייקט VkSemaphore קיים וגם לאובייקט VkFence קיים:

VkResult VKAPI vkAcquireImageANDROID(
    VkDevice            device,
    VkImage             image,
    int                 nativeFenceFd,
    VkSemaphore         semaphore,
    VkFence             fence
);

הפונקציה vkAcquireImageANDROID() מופעלת במהלך vkAcquireNextImageKHR כדי לייבא גדר מקורית לאובייקטים VkSemaphore ו-VkFence שסופקו על ידי האפליקציה (עם זאת, גם אובייקטים של סמפור וגם אובייקטים של גדר הם אופציונליים בקריאה הזו). יכול להיות שהדרייבר ישתמש בהזדמנות הזו גם כדי לזהות ולטפל בשינויים חיצוניים במצב של מאגר Gralloc. הרבה דרייברים לא יצטרכו לעשות שום דבר כאן. הקריאה הזו מעבירה את VkSemaphore ואת VkFence לאותו מצב המתנה כאילו הם אותתו על ידי vkQueueSubmit, כך שהתורים יכולים להמתין לסמפור והאפליקציה יכולה להמתין לגדר.

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

שחרור תמונות

vkQueueSignalReleaseImageANDROID מכין תמונה ב-swapchain לשימוש חיצוני, יוצר גדר מקומית ומתזמן את הגדר המקומית כך שיועבר אליה אות אחרי שסמפורי הקלט העבירו אות:

VkResult VKAPI vkQueueSignalReleaseImageANDROID(
    VkQueue             queue,
    uint32_t            waitSemaphoreCount,
    const VkSemaphore*  pWaitSemaphores,
    VkImage             image,
    int*                pNativeFenceFd
);

vkQueuePresentKHR() שיחות vkQueueSignalReleaseImageANDROID() בתור שצוין. הדרייבר צריך ליצור גידור מקומי שלא יאותת עד שכל הסמפורים waitSemaphoreCount ב-pWaitSemaphores יאותתו, ועד שכל העבודה הנוספת שנדרשת להכנת image להצגה תושלם.

אם הסמפורים של ההמתנה (אם יש כאלה) כבר אותתו, ו-queue כבר במצב סרק, מנהל ההתקן יכול להגדיר את *pNativeFenceFd ל--1 במקום ל-file descriptor מקורי של גידור, כדי לציין שאין למה לחכות. המתקשר הוא הבעלים של מתאר הקובץ וסוגר אותו שמוחזר ב-*pNativeFenceFd.

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

אם התמונה נוצרה באמצעות VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID, אז מנהל ההתקן צריך לאפשר קריאות חוזרות ל-vkQueueSignalReleaseImageANDROID() ללא קריאות ביניים ל-vkAcquireImageANDROID().

תמיכה בתמונות שניתן להציג

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

אם מנהל ההתקן לא תומך ב-Vulkan 1.1 או בתוסף VK_KHR_physical_device_properties2, טוען המערכת לא יציג תמיכה בתמונות משותפות שניתנות להצגה. אחרת, טוען הנתונים שולח שאילתה לגבי היכולות של הדרייבר על ידי קריאה ל-vkGetPhysicalDeviceProperties2() וכולל את המבנה הבא בשרשרת VkPhysicalDeviceProperties2::pNext:

typedef struct {
    VkStructureType sType; // must be VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID
    const void*     pNext;
    VkBool32        sharedImage;
} VkPhysicalDevicePresentationPropertiesANDROID;

אם מנהל ההתקן יכול לשתף בעלות על תמונה עם מערכת התצוגה, הוא מגדיר את חבר sharedImage ל-VK_TRUE.

אימות

יצרני ציוד מקורי יכולים לבדוק את ההטמעה של Vulkan באמצעות CTS, שכולל את הרכיבים הבאים:

  • בדיקות התאמה של Khronos Vulkan במודול CtsDeqpTestCases, שכוללות בדיקות פונקציונליות של API ל-Vulkan 1.0,‏ 1.1,‏ 1.2 ו-1.3.
  • מודול CtsGraphicsTestCases, שבודק שהמכשיר מוגדר בצורה נכונה ליכולות Vulkan שהוא תומך בהן.

מתג feature flag של Vulkan

כדי לחשוף דגל תכונה,android.software.vulkan.deqp.level נדרש מכשיר שתומך ב-Android 11 ואילך ובתכונת Vulkan API. הערך של דגל התכונה הזה הוא תאריך, שמקודד כמספר שלם. הוא מציין את התאריך שמשויך לבדיקות Vulkan dEQP שהמכשיר טוען שהוא עבר.

תאריך בפורמט YYYY-MM-DD מקודד כמספר שלם בן 32 ביט באופן הבא:

  • ביטים 0 עד 15 מאחסנים את השנה
  • ביטים 16-23 מכילים את החודש
  • הביטים 24-31 מאחסנים את היום

הערך המינימלי המותר לסימון התכונה הוא 0x07E30301, שמתאים לתאריך 2019-03-01, שהוא התאריך שמשויך לבדיקות Vulkan dEQP ל-Android 10. אם ערך דגל התכונה הוא לפחות הערך הזה, המכשיר טוען שהוא עבר את כל בדיקות ה-dEQP של Vulkan ב-Android 10.

הערך 0x07E40301 תואם לתאריך 2020-03-01, שהוא התאריך שמשויך לבדיקות Vulkan dEQP ל-Android 11. אם ערך דגל התכונה הוא לפחות הערך הזה, המכשיר טוען שהוא עבר את כל בדיקות ה-dEQP של Vulkan ב-Android 11.

הערך 0x07E60301 תואם לתאריך 2022-03-01, שהוא התאריך שמשויך לבדיקות Vulkan dEQP עבור Android 13. אם ערך דגל התכונה הוא לפחות הערך הזה, המכשיר טוען שהוא עבר את כל הבדיקות של Android 13 Vulkan dEQP.

מכשיר שחושף דגל תכונה ספציפי (כלומר 0x07E30301, 0x07E40301, 0x07E60301) טוען שהוא עבר את כל בדיקות ה-dEQP של Android Vulkan של דגל התכונה הזה (Android 10,‏ Android 11, ‏ Android 13 בהתאמה). יכול להיות שהמכשיר הזה יעבור את בדיקות dEQP של Vulkan מגרסת Android מאוחרת יותר.

‫Vulkan dEQP הוא חלק מ-Android CTS. מגרסה Android 11, רכיב ההרצה של בדיקת dEQP ב-CTS מודע לדגל התכונה android.software.vulkan.deqp.level, ומדלג על כל בדיקות dEQP של Vulkan שאותן – לפי דגל התכונה הזה – המכשיר לא טוען שהוא תומך בהן. הבדיקות האלה מדווחות כבדיקות שעברו בקלות.