Vulkan را اجرا کنید

Vulkan یک API کم سربار و چند پلتفرمی برای گرافیک سه بعدی با کارایی بالا است. مانند OpenGL ES (GLES) ، Vulkan ابزارهایی را برای ایجاد گرافیک با کیفیت بالا و در زمان واقعی در برنامه ها ارائه می دهد. از مزایای استفاده از Vulkan می توان به کاهش سربار CPU و پشتیبانی از زبان SPIR-V Binary Intermediate اشاره کرد.

برای اجرای موفقیت آمیز Vulkan، یک دستگاه باید شامل موارد زیر باشد:

  • لودر Vulkan ارائه شده توسط اندروید.
  • یک درایور 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) مطابقت دارد.

لودر ولکان

platform/frameworks/native/vulkan رابط اصلی بین برنامه‌های Vulkan و درایور Vulkan دستگاه است. لودر Vulkan در /system/lib[64]/libvulkan.so نصب شده است. لودر نقاط ورودی هسته Vulkan API، نقاط ورودی برنامه‌های افزودنی مورد نیاز Android CDD و بسیاری از برنامه‌های افزودنی اختیاری را فراهم می‌کند. پسوندهای Window System Integration (WSI) توسط لودر صادر می‌شوند و عمدتاً به جای درایور در لودر پیاده‌سازی می‌شوند. لودر همچنین از شمارش و بارگذاری لایه‌ها پشتیبانی می‌کند که می‌توانند افزونه‌های اضافی را در معرض دید قرار دهند و تماس‌های API هسته را در مسیر خود به درایور رهگیری کنند.

NDK شامل یک کتابخانه خرد libvulkan.so برای پیوند است. کتابخانه همان نمادهای لودر را صادر می کند. برنامه ها توابع صادر شده از کتابخانه libvulkan.so واقعی را فراخوانی می کنند تا توابع ترامپولین را در لودر وارد کنند، که بر اساس اولین آرگومان خود به لایه یا درایور مناسب ارسال می شود. فراخوانی vkGet*ProcAddr() نشانگرهای تابعی را که ترامپولین ها به آن ها ارسال می کنند برمی گرداند (یعنی مستقیماً به کد API اصلی فراخوانی می کند). فراخوانی از طریق نشانگرهای تابع، به جای نمادهای صادر شده، کارآمدتر است زیرا از ترامپولین و ارسال عبور می کند.

شمارش راننده و بارگیری

هنگامی که تصویر سیستم ساخته شد، اندروید انتظار دارد که سیستم بداند کدام 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

در اندروید 7.0 و بالاتر، مشتق Vulkan hw_module_t یک ساختار hw_module_t را می‌پیچد. فقط یک درایور پشتیبانی می شود و رشته ثابت HWVULKAN_DEVICE_0 به open() منتقل می شود.

مشتق Vulkan hw_device_t مربوط به یک درایور است که می تواند چندین دستگاه فیزیکی را پشتیبانی کند. ساختار hw_device_t می تواند به صادرات توابع vkGetGlobalExtensionProperties() ، vkCreateInstance() و vkGetInstanceProcAddr() گسترش یابد. لودر می تواند با فراخوانی VkInstance() vkGetInstanceProcAddr ساختار hw_device_t ، تمام توابع دیگر VkInstance، VkPhysicalDevice() و vkGetDeviceProcAddr() vkGetInstanceProcAddr() ) را پیدا کند.

کشف و بارگذاری لایه

لودر Vulkan از شمارش و بارگذاری لایه‌هایی پشتیبانی می‌کند که می‌توانند افزونه‌های اضافی را در معرض دید قرار دهند و تماس‌های API هسته‌ای را در مسیر خود به درایور متوقف کنند. آندروید شامل لایه‌هایی روی تصویر سیستم نمی‌شود. با این حال، برنامه ها ممکن است دارای لایه هایی در APK خود باشند.

هنگام استفاده از لایه ها، به خاطر داشته باشید که مدل امنیتی و سیاست های اندروید به طور قابل توجهی با سایر پلتفرم ها متفاوت است. به طور خاص، اندروید اجازه بارگذاری کد خارجی را در یک فرآیند غیراشکال‌پذیر در دستگاه‌های تولیدی (غیر روت) نمی‌دهد، همچنین به کدهای خارجی اجازه نمی‌دهد حافظه، وضعیت و غیره فرآیند را بررسی یا کنترل کند. این شامل ممنوعیت ذخیره سازی هسته، ردپای API و غیره در دیسک برای بازرسی بعدی است. فقط لایه‌هایی که به‌عنوان بخشی از برنامه‌های غیرقابل رفع اشکال ارائه می‌شوند در دستگاه‌های تولیدی فعال هستند و درایورها نباید عملکردی ارائه دهند که این خط‌مشی‌ها را نقض می‌کند.

موارد استفاده برای لایه ها عبارتند از:

  • لایه‌های زمان توسعه - لایه‌های اعتبارسنجی و شیم‌های ابزارهای ردیابی/پروفایل/اشکال‌زدایی نباید روی تصویر سیستم دستگاه‌های تولید نصب شوند. لایه‌های اعتبارسنجی و شیم‌های ابزارهای ردیابی/پروفایل/اشکال‌زدایی باید بدون تصویر سیستم قابل به‌روزرسانی باشند. برنامه‌نویسانی که می‌خواهند از یکی از این لایه‌ها در طول توسعه استفاده کنند، می‌توانند بسته برنامه را تغییر دهند، برای مثال، با افزودن یک فایل به فهرست کتابخانه‌های بومی خود. مهندسان IHV و OEM که می‌خواهند خرابی‌ها را در ارسال برنامه‌های غیرقابل تغییر تشخیص دهند، فرض می‌شود که به ساخت‌های غیرتولیدی (ریشه‌دار) تصویر سیستم دسترسی دارند، مگر اینکه این برنامه‌ها قابل اشکال‌زدایی باشند. برای اطلاعات بیشتر به لایه‌های اعتبارسنجی Vulkan در Android مراجعه کنید.
  • لایه‌های کاربردی - این لایه‌ها پسوندها را نشان می‌دهند، مانند لایه‌ای که یک مدیر حافظه را برای حافظه دستگاه پیاده‌سازی می‌کند. توسعه دهندگان لایه ها و نسخه هایی از آن لایه ها را برای استفاده در برنامه خود انتخاب می کنند. برنامه های مختلف با استفاده از یک لایه ممکن است همچنان از نسخه های مختلف استفاده کنند. توسعه دهندگان انتخاب می کنند که کدام یک از این لایه ها را در بسته برنامه خود ارسال کنند.
  • لایه‌های تزریقی (ضمنی) - شامل لایه‌هایی مانند نرخ فریم، شبکه اجتماعی و پوشش‌های راه‌انداز بازی است که توسط کاربر یا برخی برنامه‌های دیگر بدون اطلاع یا رضایت برنامه ارائه می‌شود. اینها خط‌مشی‌های امنیتی Android را نقض می‌کنند و پشتیبانی نمی‌شوند.

برای برنامه‌های غیراشکال‌پذیر، لودر لایه‌ها را فقط در فهرست راهنمای کتابخانه اصلی برنامه جستجو می‌کند و سعی می‌کند هر کتابخانه‌ای را با نامی مطابق با یک الگوی خاص بارگیری کند (مثلاً libVKLayer_foo.so ).

برای برنامه‌های قابل اشکال‌زدایی، لودر لایه‌ها را در /data/local/debug/vulkan جستجو می‌کند و تلاش می‌کند هر کتابخانه‌ای را که با یک الگوی خاص مطابقت دارد بارگیری کند.

اندروید اجازه می دهد لایه ها با تغییرات محیطی بین اندروید و سایر پلتفرم ها منتقل شوند. برای جزئیات بیشتر در مورد رابط بین لایه ها و لودر، به معماری واسط های لودر Vulkan مراجعه کنید. لایه‌های اعتبار سنجی حفظ شده توسط Khronos در لایه‌های اعتبارسنجی Vulkan میزبانی می‌شوند.

نسخه ها و قابلیت های Vulkan API

جدول زیر نسخه های Vulkan API را برای چندین نسخه اندروید فهرست می کند.
نسخه اندروید نسخه Vulkan
اندروید 13 Vulkan 1.3
اندروید 9 Vulkan 1.1
اندروید 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 برای اندروید عبارتند از:

  • پشتیبانی از نمونه های پاس رندر تک گذر
  • پشتیبانی برای خاتمه فوری فراخوانی سایه زن
  • دانه بندی دقیق تر در ایجاد، اشتراک گذاری و کنترل خط لوله

Vulkan 1.3 همچنین شامل چندین ویژگی کوچکتر و بهبود قابلیت استفاده API است. همه تغییرات ایجاد شده در هسته 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 برای اندروید پشتیبانی از حافظه 8 بیتی است.

Vulkan 1.2 همچنین شامل چندین ویژگی کوچکتر و بهبود قابلیت استفاده API است. تمام تغییرات ایجاد شده در هسته Vulkan API با ویرایش جزئی 1.2 را می توان در Core Revisions (Vulkan 1.2) پیدا کرد.

مروری بر عملکرد Vulkan 1.1

Vulkan 1.1 شامل پشتیبانی از حافظه/همگام سازی interop است که OEM ها را قادر می سازد از Vulkan 1.1 در دستگاه ها پشتیبانی کنند. علاوه بر این، تعامل حافظه/همگام‌سازی به توسعه‌دهندگان این امکان را می‌دهد تا تعیین کنند که آیا Vulkan 1.1 در یک دستگاه پشتیبانی می‌شود یا خیر، و در صورت وجود، از آن به طور موثر استفاده کنند. Vulkan 1.1 دارای الزامات سخت افزاری مشابه با Vulkan 1.0 است، اما بیشتر پیاده سازی در درایور گرافیک SOC خاص است، نه در چارچوب.

مهمترین ویژگی های Vulkan 1.1 برای اندروید عبارتند از:

  • پشتیبانی از وارد کردن و صادر کردن بافرهای حافظه و اشیاء همگام سازی از خارج از Vulkan (برای تعامل با دوربین، کدک ها و GLES)
  • پشتیبانی از فرمت های YCbCr

Vulkan 1.1 همچنین شامل چندین ویژگی کوچکتر و بهبود قابلیت استفاده API است. همه تغییرات ایجاد شده در هسته Vulkan API با ویرایش جزئی 1.1 را می توان در Core Revisions (Vulkan 1.1) پیدا کرد.

پشتیبانی Vulkan را انتخاب کنید

دستگاه‌های اندرویدی باید از پیشرفته‌ترین مجموعه ویژگی‌های Vulkan در دسترس پشتیبانی کنند، مشروط بر اینکه از ABI 64 بیتی پشتیبانی کنند و حافظه کم نداشته باشند.

دستگاه هایی که با اندروید 13 و بالاتر راه اندازی می شوند باید از Vulkan 1.3 پشتیبانی کنند.

دستگاه هایی که از طریق اندروید 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، اطمینان حاصل کنید که ویژگی سیستمی که توسط مدیر بسته بازگردانده شده است، برای نسخه صحیح vulkan true .
    • برای Vulkan 1.3 ویژگی PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x403000) است.
    • برای Vulkan 1.1 ویژگی PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x401000) است.
    مدیر بسته برای Vulkan 1.3 و Vulkan 1.1 با افزودن قاعده‌ای که به شکل زیر نشان داده شده است، به یک فایل device.mk مناسب true خواهد گشت.
    • موارد زیر را برای 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
      

نمایه خط پایه 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 فقط در اندروید 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() را منسوخ می کند، اما اگر vkGetSwapchainGrallocUsage2ANDROID() vkGetSwapchainGrallocUsageANDROID() توسط درایور ارائه نشده باشد، همچنان vkGetSwapchainGrallocUsageANDROID() را فراخوانی می کند:

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 تعداد بافرهای داخلی درخواست شده برای swapchain را تخصیص می دهد، سپس یک 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

در اندروید 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;

در اندروید 10 و بالاتر، این پلتفرم از VK_KHR_swapchain v70 پشتیبانی می کند، بنابراین برنامه Vulkan می تواند یک VkImage ایجاد کند که توسط حافظه swapchain پشتیبانی می شود. این برنامه ابتدا vkCreateImage با ساختار VkImageSwapchainCreateInfoKHR که به ساختار VkImageCreateInfo زنجیر شده است فراخوانی می کند. سپس برنامه vkBindImageMemory2(KHR) را با ساختار VkBindImageMemorySwapchainInfoKHR که به ساختار VkBindImageMemoryInfo زنجیر شده است فراخوانی می کند. imageIndex مشخص شده در ساختار VkBindImageMemorySwapchainInfoKHR باید یک فهرست تصویر swapchain معتبر باشد. در همین حال، پلتفرم یک ساختار افزونه VkNativeBufferANDROID با اطلاعات بافر Gralloc مربوطه به زنجیره VkBindImageMemoryInfo ارائه می‌کند، بنابراین راننده بداند VkImage را به کدام بافر Gralloc متصل کند.

به دست آوردن تصاویر

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 تنظیم کند، که نشان می دهد چیزی برای انتظار وجود ندارد. تماس‌گیرنده توصیف‌گر فایل بازگردانده شده در *pNativeFenceFd را در اختیار دارد و می‌بندد.

بسیاری از درایورها می توانند پارامتر تصویر را نادیده بگیرند، اما برخی ممکن است نیاز به آماده سازی ساختارهای داده سمت CPU مرتبط با بافر Gralloc برای استفاده توسط مصرف کنندگان تصویر خارجی داشته باشند. آماده سازی محتویات بافر برای استفاده توسط مصرف کنندگان خارجی باید به صورت ناهمزمان به عنوان بخشی از انتقال تصویر به VK_IMAGE_LAYOUT_PRESENT_SRC_KHR انجام شود.

اگر تصویر با VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID ایجاد شده باشد، درایور باید اجازه دهد که vkQueueSignalReleaseImageANDROID() به طور مکرر بدون تماس های میانجی به vkAcquireImageANDROID() فراخوانی شود.

پشتیبانی از تصویر قابل ارائه به اشتراک گذاشته شده

برخی از دستگاه‌ها می‌توانند مالکیت یک تصویر واحد را بین خط لوله نمایش و اجرای Vulkan به اشتراک بگذارند تا تأخیر را به حداقل برسانند. در اندروید 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 تنظیم می کند.

اعتبار سنجی

OEM ها می توانند اجرای Vulkan خود را با استفاده از CTS آزمایش کنند که شامل موارد زیر است:

  • تست‌های انطباق Khronos Vulkan در ماژول CtsDeqpTestCases ، که شامل تست‌های API عملکردی برای Vulkan 1.0، 1.1، 1.2 و 1.3 است.
  • ماژول CtsGraphicsTestCases ، که آزمایش می کند که دستگاه به درستی برای قابلیت های 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 است. اگر پرچم ویژگی حداقل این مقدار باشد، دستگاه ادعا می‌کند که تمام تست های Android 10 Vulkan dEQP را پشت سر بگذارید.

مقدار 0x07E40301 مربوط به تاریخ 01-03-2020 است، که تاریخ مرتبط با تست‌های Vulkan dEQP برای Android 11 است. اگر پرچم ویژگی حداقل این مقدار باشد، دستگاه ادعا می‌کند که تمام تست‌های Vulkan dEQP Android 11 را با موفقیت پشت سر گذاشته است.

مقدار 0x07E60301 مربوط به تاریخ 01-03-2022 است، که تاریخ مرتبط با تست‌های Vulkan dEQP برای Android 13 است. اگر پرچم ویژگی حداقل این مقدار باشد، دستگاه ادعا می‌کند که تمام تست‌های Vulkan dEQP Android 13 را با موفقیت پشت سر گذاشته است.

دستگاهی که پرچم ویژگی خاصی را نشان می‌دهد ( یعنی 0x07E30301 ، 0x07E40301 ، 0x07E60301 ) ادعا می‌کند که تمام تست‌های Android Vulkan dEQP آن پرچم ویژگی (به ترتیب Android 10، Android 11، Android 13) را گذرانده است. این دستگاه ممکن است آزمایش‌های Vulkan dEQP را از نسخه‌های بعدی اندروید انجام دهد.

Vulkan dEQP بخشی از Android CTS است. از Android 11، مؤلفه اجرای آزمایشی dEQP CTS از پرچم ویژگی android.software.vulkan.deqp.level آگاه است و از هر آزمایش Vulkan dEQP که - طبق این پرچم ویژگی - دستگاه ادعای پشتیبانی نمی کند، صرف نظر می کند. چنین آزمون هایی به عنوان گذراندن پیش پا افتاده گزارش می شوند.