הטמעת Vulkan

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

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

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

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

מעבד Vulkan

מעבד Vulkan 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 ב-loader, שמעבירות את הבקשה לשכבה או לנהג המתאימים על סמך הארגומנט הראשון שלהן. הקריאה vkGet*ProcAddr() מחזירה את הפונקציות שמפניות אליהן הטרמפולינות (כלומר, היא מפעילה קריאה ישירה לקוד הליבה של ה-API). קריאה דרך מצביע הפונקציה, במקום דרך הסמלים המיוצאים, יעילה יותר כי היא מדלגת על הטרמפולינה וההעברה.

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

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

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

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

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

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

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

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

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

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

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

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

ב-Android אפשר להעביר שכבות עם שינויים בסביבת ה-build בין Android לפלטפורמות אחרות. פרטים על הממשק בין השכבות לבין מערך האפליקציות זמינים במאמר הארכיטקטורה של ממשקי מערך האפליקציות של Vulkan. שכבות האימות שמנוהלות על ידי Khronos מתארחות ב-Vulkan Validation Layers.

הגרסאות והיכולות של 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

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

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

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

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

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

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

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

גרסה 1.2 של Vulkan כוללת גם כמה תכונות קטנות ושיפורים בנוחות השימוש ב-API. כל השינויים שבוצעו בממשק ה-API של Vulkan בגרסה 1.2 מפורטים במאמר Core Revisions (Vulkan 1.2).

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

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

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

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

Vulkan 1.1 כולל גם כמה תכונות קטנות ושיפורים בממשק ה-API. כל השינויים שבוצעו ב-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 (היא חייבת להיות אחת מגרסאות 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

יכול להיות שיהיה צורך להקצות מאגרי swapchain להטמעות של Vulkan באמצעות דגלים פרטיים של שימוש ב-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 ואילך, ה-API vkGetSwapchainGrallocUsageANDROID() הוצא משימוש, אבל עדיין מתבצעת קריאה ל-vkGetSwapchainGrallocUsageANDROID() אם ה-driver לא מספק את 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:

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, כך שהתור יכול להמתין לסמפור והאפליקציה יכולה להמתין ל-fence.

שני האובייקטים מקבלים אותות כשהגדרה המקורית של הגדרת המכשול מקבלת אותות. אם הגדרת המכשול המקורית כבר קיבלה אותות, הסימון של הסימון יהיה במצב 'התקבל אות' כשהפונקציה הזו תחזיר. הנהג מקבל בעלות על מתאר קובץ הגדר, וסוגר את מתאר קובץ הגדר כשכבר אין בו צורך. הנהג חייב לעשות זאת גם אם לא סיפקו אובייקט סמפור או אובייקט גדר, וגם אם 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 במקום למתואר קובץ של גדר מקורית בפועל, כדי לציין שאין מה לחכות. מבצע הקריאה החוזרת הוא הבעלים של מתאר הקובץ שמוחזר ב-*pNativeFenceFd, והוא גם סוגר אותו.

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

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

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

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

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

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

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

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