הטמעת Vulkan

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

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

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

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

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

ב-Android אפשר להעביר שכבות עם שינויים בסביבת ה-build בין Android לפלטפורמות אחרות. פרטים על הממשק בין השכבות לבין מערך האפליקציות זמינים במאמר הארכיטקטורה של ממשקי מערך האפליקציות של Vulkan. שכבות האימות המתוחזקות על ידי חרונוס מתארחות ב-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

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

התכונות החשובות ביותר של 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 ביט.

Vulkan 1.2 כולל גם כמה תכונות קטנות יותר ושיפורים בנוחות השימוש לממשקי 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

בהטמעות של Vulkan, יכול להיות שיהיה צורך להקצות מאגרי נתונים זמניים ב-salchain, באמצעות דגלי שימוש פרטיים שהוגדרו בהטמעה ב-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:

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

סימון תכונה של Vulkan

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

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

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

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

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

הערך 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 שלפי דגל התכונה הזה המכשיר לא תומך בהן. בדיקות כאלה ידווחו כמעבר פשוט.