پیاده‌سازی Vulkan

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

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

  • بارکننده Vulkan، ارائه‌شده توسط Android.
  • درایور Vulkan که توسط «سیستم روی تراشه» (SoC) مانند GPU IHV ارائه می‌شود و Vulkan API را پیاده‌سازی می‌کند. برای پشتیبانی از عملکرد Vulkan، دستگاه Android باید سخت‌افزار واحد پردازش گرافیکی (GPU) سازگار با Vulkan و درایور مربوطه را داشته باشد. «واحد پردازش گرافیکی» باید از 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، و بسیاری از افزونه‌های اختیاری اضافی را ارائه می‌دهد. افزونه‌های «یکپارچه‌سازی سیستم» (WSI) توسط بارکننده صادر می‌شوند و عمدتاً در بارکننده پیاده‌سازی می‌شوند نه در درایور. بارکننده همچنین از برشمردن و بار کردن لایه‌هایی که می‌توانند افزونه‌های اضافی را آشکار کنند و تماس‌های API اصلی را در مسیرشان به درایور رهگیری کنند پشتیبانی می‌کند.

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

شمارش و بار کردن درایور

وقتی تصویر سیستم ساخته می‌شود، Android انتظار دارد سیستم بداند کدام GPU-ها دردسترس هستند. بارکننده از سازوکار HAL موجود در hardware.h برای شناسایی و بار کردن درایور استفاده می‌کند. مسیرهای ترجیحی برای درایورهای ۳۲ بیتی و ۶۴ بیتی Vulkan عبارت‌اند از:

/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 بار شود.

اکتشاف و بار کردن لایه

بارکننده Vulkan از لایه‌های شمارشی و بارگذاری پشتیبانی می‌کند که می‌توانند افزونه‌های اضافی را نمایش دهند و تماس‌های میانای برنامه‌سازی کاربردی هسته را در مسیرشان به درایور رهگیری کنند. برنامه‌ها می‌توانند لایه‌هایی را در فایل APK خود بگنجانند. ‫Android لایه‌ها را در تصویر سیستم قرار نمی‌دهد.

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

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

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

برای برنامه‌های غیرقابل‌اشکال‌زدایی، بارکننده فقط در دایرکتوری کتابخانه بومی برنامه به‌دنبال لایه‌ها می‌گردد و تلاش می‌کند هر کتابخانه‌ای را که نام آن با الگوی خاصی مطابقت دارد (برای مثال، libVKLayer_foo.so) بار کند. این لایه‌ها در فضای نام برنامه بار می‌شوند. بنابراین، این کتابخانه‌ها باید با NDK ساخته شوند.

برای برنامه‌های قابل‌اشکال‌زدایی، بارکننده لایه‌ها را در /data/local/debug/vulkan جستجو می‌کند و تلاش می‌کند هر کتابخانه‌ای را که با الگوی خاصی مطابقت دارد بار کند. از Android 10 (سطح API 29) به بعد، Vulkan می‌تواند لایه‌های زمان توسعه را نیز از APK دیگری بار کند. در هر دو مورد، بارکننده بااستفاده از تنظیمات سیستم انتخاب می‌کند کدام لایه‌ها به‌صورت برنامه به برنامه فعال شوند. این لایه‌ها در vkEnumerateInstanceLayerProperties فهرست شده‌اند (یعنی برنامه ممکن است از آن‌ها مطلع باشد)، حتی اگر ممکن است بدون رضایت برنامه بارگیری شوند.

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

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

جدول زیر نسخه‌های Vulkan API را برای چند نسخه Android فهرست می‌کند.
نسخهٔ Android نسخه Vulkan
‫Android 16 Vulkan 1.4
Android 13 Vulkan 1.3
Android 9 Vulkan 1.1
Android 7 Vulkan 1.0

نمای کلی عملکرد Vulkan 1.4

Vulkan 1.4 تعدادی از افزونه‌های اختیاری قبلی را به عملکرد اصلی Vulkan تبدیل می‌کند. بسیاری از این عملکردها با هدف افزایش کنترل و جزئیات بر روی رابط برنامه‌نویسی Vulkan گنجانده شده‌اند. ‫Vulkan 1.4 در مقایسه با Vulkan 1.3، الزامات سخت‌افزاری را افزایش می‌دهد، و بیشتر پیاده‌سازی در درایور گرافیک مختص SoC انجام می‌شود، نه در چارچوب.

نمای کلی عملکرد 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 همچنین شامل چندین ویژگی کوچک‌تر و بهبود قابلیت استفاده از میانای برنامه‌سازی کاربردی است. همه تغییرات ایجادشده در «میانای برنامه‌سازی کاربردی» اصلی Vulkan با نسخه اصلاحی جزئی ۱.۳ را می‌توانید در نسخه‌های اصلاحی اصلی (Vulkan 1.3) پیدا کنید.

نمای کلی عملکرد Vulkan 1.2

Vulkan 1.2 تعدادی ویژگی و افزونه اضافه می‌کند که سطح میانای برنامه‌سازی کاربردی را ساده می‌کند. این شامل یک مدل حافظه یکپارچه و اطلاعات اضافی است که می‌توان از درایور دستگاه درخواست کرد. ‫Vulkan 1.2 همان الزامات سخت‌افزاری Vulkan 1.0 و 1.1 را دارد؛ همه پیاده‌سازی در درایور گرافیک مختص SoC است، نه چارچوب.

مهم‌ترین ویژگی Vulkan 1.2 برای Android پشتیبانی از فضای ذخیره‌سازی ۸ بیتی است.

‫Vulkan 1.2 همچنین شامل چندین ویژگی کوچک‌تر و بهبود در قابلیت استفاده از میانای برنامه‌سازی کاربردی است. همه تغییرات ایجادشده در میانای برنامه‌سازی کاربردی اصلی Vulkan با نسخه اصلاحی جزئی ۱.۲ را می‌توانید در نسخه‌های اصلاحی اصلی (Vulkan 1.2) پیدا کنید.

نمای کلی عملکرد Vulkan 1.1

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

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

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

‫Vulkan 1.1 همچنین شامل چندین ویژگی کوچک‌تر و بهبود در قابلیت استفاده از API است. همه تغییرات ایجادشده در «میانای برنامه‌سازی کاربردی» اصلی Vulkan با نسخه اصلاحی جزئی ۱.۱ را می‌توانید در نسخه‌های اصلاحی اصلی (Vulkan 1.1) پیدا کنید.

انتخاب پشتیبانی Vulkan

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

دستگاه‌هایی که با Android 16 و بالاتر عرضه می‌شوند باید از Vulkan 1.4 پشتیبانی کنند.

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

دستگاه‌هایی که با Android 10 عرضه می‌شوند باید از Vulkan 1.1 پشتیبانی کنند.

دستگاه‌های دیگر می‌توانند به‌طور اختیاری از Vulkan نسخه ۱.۴، ۱.۳، ۱.۲، و ۱.۱ پشتیبانی کنند.

از نسخه Vulkan پشتیبانی کنید

دستگاه Android درصورتی از نسخه Vulkan پشتیبانی می‌کند که شرایط زیر برقرار باشد:

  1. درایور Vulkan را که از نسخه Vulkan موردنظر پشتیبانی می‌کند (این نسخه باید یکی از نسخه‌های Vulkan 1.4،‏ 1.3،‏ 1.1، یا 1.0 باشد) همراه با الزامات CDD اضافی نسخه Android اضافه کنید. یا اینکه درایور Vulkan موجود با شماره نسخه Vulkan پایین‌تر را به‌روز کنید.
  2. برای Vulkan 1.4،‏ 1.3، یا 1.1، تأیید کنید که ویژگی سیستم برگشتی از مدیر بسته true را برای نسخه صحیح Vulkan برمی‌گرداند.
    • برای Vulkan 1.4، این ویژگی PackageManager#hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION, 0x404000) است.
    • برای 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.4،‏ 1.3، و 1.1 در فایل device.mk مناسب برمی‌گرداند.
    • مورد زیر را برای Vulkan 1.4 اضافه کنید:
      PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.vulkan.version-1_4.xml:
      $(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.vulkan.version.xml
    • مورد زیر را برای 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 2022» که در راهنمای نمایه پایه Android شرح داده شده است پیروی کنند.

هر دستگاهی که از Android 14 یا بالاتر و Vulkan API پشتیبانی می‌کند باید همه عملکردهای تعریف‌شده در نمایه Android Baseline 2021 را برآورده کند. فهرست کامل کارکردهای موردنیاز در فایل نمایه Vulkan json ذکر شده است، اما زیرمجموعه کلیدی کارکردهای موردنیاز شامل موارد زیر است:

  • بافت‌های فشرده ازطریق 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 ممکن است نیاز داشته باشند که بافرهای زنجیره مبادله با پرچم‌های استفاده خصوصی 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() را فرا می‌خواند:

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

‫vkGetSwapchainGrallocUsageANDROID() از پرچم‌های استفاده از زنجیره مبادله یا پرچم‌های استفاده از 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 نسخه ۷۰ پشتیبانی می‌کند، بنابراین برنامه Vulkan می‌تواند VkImage را بسازد که با حافظه زنجیره مبادله پشتیبانی می‌شود. برنامه ابتدا vkCreateImage را با ساختار VkImageSwapchainCreateInfoKHR که به ساختار VkImageCreateInfo زنجیر شده است فراخوانی می‌کند. سپس برنامه vkBindImageMemory2(KHR) را با ساختار VkBindImageMemorySwapchainInfoKHR که به ساختار VkBindImageMemoryInfo زنجیر شده است فراخوانی می‌کند. imageIndex مشخص‌شده در ساختار VkBindImageMemorySwapchainInfoKHR باید شاخص تصویر زنجیره مبادله معتبری باشد. در همین حال، پلاتفرم یک ساختار 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 برابر با -۱ باشد، انگار حصار بومی قبلاً علامت‌گذاری شده است.

تصاویر انتشار

vkQueueSignalReleaseImageANDROID تصویر زنجیره مبادله را برای استفاده خارجی آماده می‌کند، حصار بومی ایجاد می‌کند، و حصار بومی را زمان‌بندی می‌کند تا پس‌از سیگنال دادن چراغ‌های راهنمایی ورودی، سیگنال دهد:

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 هم‌رسانی کنند تا تأخیر را به حداقل برسانند. در 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، که شامل آزمایش‌های کاربردی میانای برنامه‌سازی کاربردی برای Vulkan 1.0،‏ 1.1،‏ 1.2،‏ 1.3، و 1.4 می‌شود.
  • واحد CtsGraphicsTestCases که بررسی می‌کند دستگاه برای قابلیت‌های Vulkan که پشتیبانی می‌کند به‌درستی پیکربندی شده باشد.

پرچم ویژگی Vulkan

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

تاریخی به‌شکل YYYY-MM-DD به‌صورت عدد صحیح ۳۲ بیتی به‌شکل زیر کدبندی می‌شود:

  • بیت‌های ۰ تا ۱۵ سال را ذخیره می‌کنند
  • بیت‌های ۱۶ تا ۲۳ ماه را ذخیره می‌کنند
  • بیت‌های ۲۴ تا ۳۱ روز را ذخیره می‌کنند

حداقل مقدار مجاز برای پرچم ویژگی 0x07E30301 است، که با تاریخ ۲۰۱۹-۰۳-۰۱ مطابقت دارد، یعنی تاریخی که با آزمایش‌های Vulkan dEQP برای Android 10 مرتبط است. اگر پرچم ویژگی حداقل این مقدار باشد، دستگاه ادعا می‌کند که همه آزمایش‌های Android 10 Vulkan dEQP را با موفقیت پشت سر گذاشته است.

مقدار 0x07E40301 با تاریخ ۲۰۲۰-۰۳-۰۱ مطابقت دارد، که تاریخ مرتبط با آزمون‌های Vulkan dEQP برای Android 11 است. اگر پرچم ویژگی حداقل این مقدار باشد، دستگاه ادعا می‌کند که همه آزمون‌های Android 11 Vulkan dEQP را می‌گذراند.

مقدار 0x07E60301 با تاریخ ۲۰۲۲-۰۳-۰۱ مطابقت دارد، که تاریخ مرتبط با آزمون‌های Vulkan dEQP برای Android 13 است. اگر پرچم ویژگی حداقل این مقدار باشد، دستگاه ادعا می‌کند که همه آزمون‌های dEQP مربوط به Android 13 Vulkan را می‌گذراند.

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

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