Vulkan लागू करना

Vulkan, ज़्यादा परफ़ॉर्मेंस वाले 3D ग्राफ़िक के लिए, कम ओवरहेड वाला क्रॉस-प्लैटफ़ॉर्म एपीआई है. OpenGL ES (GLES) की तरह, Vulkan भी ऐप्लिकेशन में बेहतर क्वालिटी वाले रीयल-टाइम ग्राफ़िक बनाने के लिए टूल उपलब्ध कराता है. Vulkan का इस्तेमाल करने के फ़ायदों में, सीपीयू के ओवरहेड को कम करना और SPIR-V बाइनरी इंटरमीडिएट भाषा के लिए सहायता शामिल है.

Vulkan को सही तरीके से लागू करने के लिए, डिवाइस में ये चीज़ें होनी चाहिए:

  • Android की ओर से उपलब्ध कराया गया Vulkan लोडर.
  • Vulkan ड्राइवर, जिसे GPU IHV जैसे SoC उपलब्ध कराते हैं. यह Vulkan API को लागू करता है. Vulkan की सुविधाओं का इस्तेमाल करने के लिए, Android डिवाइस में Vulkan के साथ काम करने वाला जीपीयू हार्डवेयर और उससे जुड़ा ड्राइवर होना चाहिए. GPU में GLES 3.1 और इसके बाद के वर्शन भी काम करने चाहिए. ड्राइवर से जुड़ी सहायता पाने के लिए, अपने एसओसी वेंडर से संपर्क करें.

अगर किसी डिवाइस में Vulkan ड्राइवर शामिल है, तो डिवाइस को FEATURE_VULKAN_HARDWARE_LEVEL और FEATURE_VULKAN_HARDWARE_VERSION सिस्टम फ़ीचर के बारे में बताना होगा. साथ ही, ऐसे वर्शन के बारे में बताना होगा जो डिवाइस की क्षमताओं को सही तरीके से दिखाते हों. इससे यह पक्का करने में मदद मिलती है कि डिवाइस, कंपैटबिलिटी डेफ़िनिशन डॉक्यूमेंट (सीडीडी) के मुताबिक है.

Vulkan लोडर

Vulkan लोडर platform/frameworks/native/vulkan, Vulkan ऐप्लिकेशन और डिवाइस के Vulkan ड्राइवर के बीच मुख्य इंटरफ़ेस होता है. Vulkan लोडर /system/lib[64]/libvulkan.so पर इंस्टॉल है. लोडर, Vulkan API के मुख्य एंट्री पॉइंट, Android CDD के लिए ज़रूरी एक्सटेंशन के एंट्री पॉइंट, और कई अन्य वैकल्पिक एक्सटेंशन उपलब्ध कराता है. विंडो सिस्टम इंटिग्रेशन (डब्ल्यूएसआई) एक्सटेंशन, लोडर एक्सपोर्ट करता है. साथ ही, इन्हें मुख्य रूप से ड्राइवर के बजाय लोडर में लागू किया जाता है. लोडर, उन लेयर को भी लोड कर सकता है जो ज़्यादा एक्सटेंशन दिखा सकती हैं. साथ ही, ड्राइवर को भेजे जाने वाले मुख्य एपीआई कॉल को इंटरसेप्ट कर सकती हैं.

एनडीके में, लिंक करने के लिए स्टब libvulkan.so लाइब्रेरी शामिल होती है. लाइब्रेरी, लोडर की तरह ही सिंबल एक्सपोर्ट करती है. ऐप्लिकेशन, libvulkan.so लाइब्रेरी से एक्सपोर्ट किए गए फ़ंक्शन को कॉल करते हैं, ताकि लोडर में ट्रैम्पोलिन फ़ंक्शन डाले जा सकें. ये फ़ंक्शन, पहले आर्ग्युमेंट के आधार पर सही लेयर या ड्राइवर को भेजे जाते हैं. vkGet*ProcAddr() कॉल, उन फ़ंक्शन पॉइंटर को दिखाता है जिन्हें ट्रैम्पोलिन डिसपैच करते हैं. इसका मतलब है कि यह सीधे तौर पर कोर एपीआई कोड को कॉल करता है. एक्सपोर्ट किए गए सिंबल के बजाय, फ़ंक्शन पॉइंटर के ज़रिए कॉल करना ज़्यादा असरदार होता है. ऐसा इसलिए, क्योंकि यह ट्रैम्पोलिन और डिस्पैच को स्किप कर देता है.

ड्राइवर की गिनती और उसे लोड करना

सिस्टम इमेज बनाने के दौरान, Android को यह पता होना चाहिए कि कौनसे GPU उपलब्ध हैं. ड्राइवर का पता लगाने और उसे लोड करने के लिए, लोडर hardware.h में मौजूद HAL मेकेनिज़्म का इस्तेमाल करता है. 32-बिट और 64-बिट 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() फ़ंक्शन तक बढ़ाया जा सकता है. लोडर, hw_device_t स्ट्रक्चर के vkGetInstanceProcAddr() को कॉल करके, अन्य सभी VkInstance(), VkPhysicalDevice(), और vkGetDeviceProcAddr() फ़ंक्शन ढूंढ सकता है.

Android 15 से, लोडर APEX के साथ काम करता है, ताकि Vulkan ड्राइवर को लोड किया जा सके. Vulkan को APEX से लोड करने के लिए, ro.vulkan.apex को Vulkan APEX के नाम पर सेट करें.

लेयर ढूंढना और लोड करना

Vulkan लोडर, उन लेयर को गिनने और लोड करने की सुविधा देता है जो अतिरिक्त एक्सटेंशन दिखा सकती हैं. साथ ही, ड्राइवर तक पहुंचने के दौरान कोर एपीआई कॉल को इंटरसेप्ट कर सकती हैं. Android, सिस्टम इमेज में लेयर शामिल नहीं करता. हालांकि, ऐप्लिकेशन अपने APK में लेयर शामिल कर सकते हैं.

लेयर का इस्तेमाल करते समय, ध्यान रखें कि Android के सुरक्षा मॉडल और नीतियां, अन्य प्लैटफ़ॉर्म से काफ़ी अलग होती हैं. खास तौर पर, Android प्रोडक्शन (नॉनरूटेड) डिवाइसों पर, डीबग नहीं की जा सकने वाली प्रोसेस में बाहरी कोड लोड करने की अनुमति नहीं देता. साथ ही, यह बाहरी कोड को प्रोसेस की मेमोरी, स्थिति वगैरह की जांच करने या उसे कंट्रोल करने की अनुमति भी नहीं देता. इसमें बाद में जांच करने के लिए, डिस्क पर कोर डंप, एपीआई ट्रेस वगैरह सेव करने पर पाबंदी शामिल है. प्रोडक्शन डिवाइसों पर, सिर्फ़ उन लेयर को चालू किया जाता है जिन्हें डीबग नहीं किया जा सकता. साथ ही, ड्राइवर को ऐसी सुविधा नहीं देनी चाहिए जिससे इन नीतियों का उल्लंघन होता हो.

लेयर के इस्तेमाल के उदाहरणों में ये शामिल हैं:

  • डेवलपमेंट के दौरान इस्तेमाल होने वाली लेयर — प्रोडक्शन डिवाइसों की सिस्टम इमेज पर, पुष्टि करने वाली लेयर और ट्रेसिंग/प्रोफ़ाइलिंग/डीबग करने वाले टूल के लिए शिम इंस्टॉल नहीं किए जाने चाहिए. ट्रेसिंग/प्रोफ़ाइलिंग/डीबगिंग टूल के लिए, पुष्टि करने वाली लेयर और शिम को सिस्टम इमेज के बिना अपडेट किया जा सकता है. डेवलपमेंट के दौरान इनमें से किसी लेयर का इस्तेमाल करने वाले डेवलपर, ऐप्लिकेशन पैकेज में बदलाव कर सकते हैं. उदाहरण के लिए, वे अपनी नेटिव लाइब्रेरी डायरेक्ट्री में कोई फ़ाइल जोड़ सकते हैं. जिन IHV और OEM इंजीनियरों को ऐसे ऐप्लिकेशन की शिपिंग से जुड़ी समस्याओं का पता लगाना है जिन्हें बदला नहीं जा सकता उनके पास सिस्टम इमेज के नॉनप्रोडक्शन (रूट किए गए) बिल्ड का ऐक्सेस होना चाहिए. हालांकि, अगर उन ऐप्लिकेशन को डीबग किया जा सकता है, तो ऐसा ज़रूरी नहीं है. ज़्यादा जानकारी के लिए, Android पर Vulkan की पुष्टि करने वाली लेयर देखें.
  • उपयोगिता लेयर — ये लेयर एक्सटेंशन को दिखाती हैं. जैसे, डिवाइस की मेमोरी के लिए मेमोरी मैनेजर को लागू करने वाली लेयर. डेवलपर, अपने ऐप्लिकेशन में इस्तेमाल करने के लिए लेयर और उन लेयर के वर्शन चुनते हैं. एक ही लेयर का इस्तेमाल करने वाले अलग-अलग ऐप्लिकेशन, अब भी अलग-अलग वर्शन का इस्तेमाल कर सकते हैं. डेवलपर यह चुनते हैं कि उन्हें अपने ऐप्लिकेशन पैकेज में इनमें से कौनसी लेयर शामिल करनी हैं.
  • इंजेक्ट की गई (इंप्लिसिट) लेयर — इनमें ऐसी लेयर शामिल होती हैं, जैसे कि फ़्रेम रेट, सोशल नेटवर्क, और गेम लॉन्चर ओवरले. इन्हें उपयोगकर्ता या कोई अन्य ऐप्लिकेशन, ऐप्लिकेशन की जानकारी या सहमति के बिना उपलब्ध कराता है. ये Android की सुरक्षा नीतियों का उल्लंघन करते हैं. इसलिए, इनका इस्तेमाल नहीं किया जा सकता.

जिन ऐप्लिकेशन को डीबग नहीं किया जा सकता उनके लिए, लोडर सिर्फ़ ऐप्लिकेशन की नेटिव लाइब्रेरी डायरेक्ट्री में लेयर खोजता है. साथ ही, किसी खास पैटर्न (उदाहरण के लिए, libVKLayer_foo.so) से मेल खाने वाले नाम वाली लाइब्रेरी को लोड करने की कोशिश करता है.

डिबग किए जा सकने वाले ऐप्लिकेशन के लिए, लोडर इन फ़ोल्डर में लेयर खोजता है: /data/local/debug/vulkan. साथ ही, किसी खास पैटर्न से मेल खाने वाली लाइब्रेरी को लोड करने की कोशिश करता है.

Android, लेयर को Android और अन्य प्लैटफ़ॉर्म के बीच बिल्ड-एनवायरमेंट में बदलाव के साथ पोर्ट करने की सुविधा देता है. लेयर और लोडर के बीच इंटरफ़ेस के बारे में जानकारी पाने के लिए, Vulkan Loader Interfaces का आर्किटेक्चर देखें. Khronos की ओर से मैनेज की जाने वाली पुष्टि करने वाली लेयर, Vulkan Validation Layers में होस्ट की जाती हैं.

Vulkan API के वर्शन और सुविधाएं

यहां दी गई टेबल में, Android के अलग-अलग वर्शन के लिए Vulkan API के वर्शन दिए गए हैं.
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 प्रोग्रामिंग इंटरफ़ेस पर कंट्रोल और ग्रेन्यूलैरिटी बढ़ाने के मकसद से शामिल किया गया है. सिंगल-पास रेंडर पास इंस्टेंस को अब रेंडर पास ऑब्जेक्ट या फ़्रेमबफ़र की ज़रूरत नहीं होती. पाइपलाइन के स्टेट ऑब्जेक्ट की कुल संख्या कम की जा सकती है. साथ ही, एपीआई में सिंक्रनाइज़ेशन को बेहतर बनाया गया है. Vulkan 1.3 के लिए, हार्डवेयर से जुड़ी वही ज़रूरी शर्तें हैं जो Vulkan 1.2, 1.1, और 1.0 के लिए हैं. साथ ही, ज़्यादातर सुविधाएं SoC के हिसाब से ग्राफ़िक्स ड्राइवर में लागू की जाती हैं, न कि फ़्रेमवर्क में.

Android के लिए, Vulkan 1.3 की सबसे अहम सुविधाएं ये हैं:

  • सिंगल-पास रेंडर पास इंस्टेंस के लिए सहायता
  • शेडर इन्वोकेशन को तुरंत बंद करने की सुविधा
  • पाइपलाइन बनाने, शेयर करने, और कंट्रोल करने के लिए ज़्यादा विकल्प

Vulkan 1.3 में कई छोटी सुविधाएं भी शामिल हैं. साथ ही, एपीआई के इस्तेमाल को बेहतर बनाया गया है. Vulkan 1.3 के माइनर रिविज़न के साथ, कोर Vulkan API में किए गए सभी बदलावों के बारे में जानने के लिए, कोर रिविज़न (Vulkan 1.3) पर जाएं.

Vulkan 1.2 की सुविधाओं के बारे में खास जानकारी

Vulkan 1.2 में कई सुविधाएं और एक्सटेंशन जोड़े गए हैं. इससे एपीआई का इस्तेमाल करना आसान हो जाता है. इसमें एक यूनिफ़ाइड मेमोरी मॉडल और ऐसी अतिरिक्त जानकारी शामिल होती है जिसे डिवाइस ड्राइवर से क्वेरी किया जा सकता है. Vulkan 1.2 के लिए, हार्डवेयर से जुड़ी वही ज़रूरी शर्तें हैं जो Vulkan 1.0 और 1.1 के लिए हैं. सभी सुविधाएं, SoC के हिसाब से ग्राफ़िक्स ड्राइवर में लागू की जाती हैं, न कि फ़्रेमवर्क में.

Android के लिए Vulkan 1.2 की सबसे अहम सुविधा, 8-बिट स्टोरेज के लिए सहायता है.

Vulkan 1.2 में कई छोटी सुविधाएं भी शामिल हैं. साथ ही, इसमें एपीआई के इस्तेमाल को बेहतर बनाने से जुड़े सुधार भी किए गए हैं. 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 के लिए हैं. हालांकि, ज़्यादातर इंप्लीमेंटेशन, फ़्रेमवर्क में नहीं, बल्कि एसओसी के हिसाब से ग्राफ़िक्स ड्राइवर में होता है.

Android के लिए, Vulkan 1.1 की सबसे अहम सुविधाएं ये हैं:

  • Vulkan के बाहर से मेमोरी बफ़र और सिंक्रनाइज़ेशन ऑब्जेक्ट इंपोर्ट और एक्सपोर्ट करने की सुविधा (कैमरा, कोडेक, और GLES के साथ इंटरऑप के लिए)
  • YCbCr फ़ॉर्मैट के लिए सहायता

Vulkan 1.1 में कई छोटी सुविधाएं भी शामिल हैं. साथ ही, इसमें एपीआई के इस्तेमाल को बेहतर बनाने से जुड़े सुधार भी किए गए हैं. Vulkan 1.1 के मुख्य एपीआई में किए गए सभी बदलावों के बारे में जानने के लिए, Core Revisions (Vulkan 1.1) पर जाएं.

Vulkan के साथ काम करने की सुविधा चुनें

Android डिवाइसों में, Vulkan की सबसे नई सुविधाओं का इस्तेमाल किया जा सकता है. हालांकि, इसके लिए ज़रूरी है कि डिवाइस में 64-बिट ABI का इस्तेमाल किया जा रहा हो और उसमें कम मेमोरी न हो.

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 वर्शन में से कोई एक होना चाहिए. साथ ही, 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 के लिए true दिखाएगा. इसके लिए, वह 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

Android बेसलाइन प्रोफ़ाइल (एबीपी)

हमारा सुझाव है कि सभी Android डिवाइस, Android Baseline 2022 की नई प्रोफ़ाइल के मुताबिक हों. इसके बारे में Android Baseline प्रोफ़ाइल गाइड में बताया गया है.

Android 14 या इसके बाद के वर्शन और Vulkan API के साथ काम करने वाले किसी भी डिवाइस को, Android Baseline 2021 प्रोफ़ाइल में बताई गई सभी सुविधाओं को पूरा करना होगा. ज़रूरी सुविधाओं की पूरी सूची, Vulkan प्रोफ़ाइल json फ़ाइल में दी गई है. हालांकि, ज़रूरी सुविधाओं के मुख्य सबसेट में ये शामिल हैं:

  • ASTC और ETC की मदद से कंप्रेस किए गए टेक्सचर.
  • VK_EXT_swapchain_colorspace के ज़रिए वैरिएबल कलरस्पेस.
  • sampleRateShading की मदद से, सैंपल शेडिंग और मल्टीसैंपल इंटरपोलेशन.

विंडो सिस्टम इंटिग्रेशन (डब्ल्यूएसआई)

libvulkan.so में, ड्राइवर इन विंडो सिस्टम इंटिग्रेशन (डब्ल्यूएसआई) एक्सटेंशन को लागू करता है:

  • VK_KHR_surface
  • VK_KHR_android_surface
  • VK_KHR_swapchain
  • VK_KHR_driver_properties, जिसे सिर्फ़ Android 10 में Vulkan 1.1 के लिए लागू किया गया है
  • VK_GOOGLE_display_timing, Android 10 में Vulkan के किसी भी वर्शन के लिए लागू किया गया

VkSurfaceKHR और VkSwapchainKHR ऑब्जेक्ट और ANativeWindow के साथ होने वाली सभी कार्रवाइयों को प्लैटफ़ॉर्म मैनेज करता है. इन्हें ड्राइवर के साथ शेयर नहीं किया जाता. WSI को लागू करने के लिए, VK_ANDROID_native_buffer एक्सटेंशन पर निर्भर रहना पड़ता है. यह एक्सटेंशन, ड्राइवर के साथ काम करना चाहिए. इस एक्सटेंशन का इस्तेमाल सिर्फ़ WSI को लागू करने के लिए किया जाता है. इसे ऐप्लिकेशन के लिए उपलब्ध नहीं कराया जाता.

Gralloc के इस्तेमाल से जुड़े फ़्लैग

Vulkan को लागू करने के लिए, स्वैपचेन बफ़र को लागू करने के लिए तय किए गए निजी Gralloc के इस्तेमाल के फ़्लैग के साथ असाइन करने की ज़रूरत पड़ सकती है. स्वैपचेन बनाते समय, 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 स्ट्रक्चर से लिए जाते हैं. ड्राइवर को फ़ॉर्मैट और इस्तेमाल के लिए ज़रूरी Gralloc के इस्तेमाल के फ़्लैग के साथ *grallocConsumerUsage और *grallocProducerUsage भरना चाहिए. ड्राइवर से मिले इस्तेमाल के फ़्लैग को, स्वैपचेन उपभोक्ता के अनुरोध किए गए इस्तेमाल के फ़्लैग के साथ जोड़ दिया जाता है. ऐसा बफ़र असाइन करते समय किया जाता है.

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, Gralloc बफ़र की मदद से इमेज बनाने के लिए vkCreateImage एक्सटेंशन स्ट्रक्चर है. VkNativeBufferANDROID को VkImageCreateInfo स्ट्रक्चर चेन में vkCreateImage() को दिया गया है. 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 और इसके बाद के वर्शन में, प्लैटफ़ॉर्म vkCreateImage को VkImageCreateInfo चेन में VkSwapchainImageCreateInfoKHR एक्सटेंशन स्ट्रक्चर उपलब्ध कराता है. ऐसा तब होता है, जब स्वैपचेन के लिए स्वैपचेन इमेज के इस्तेमाल के फ़्लैग की ज़रूरत होती है. एक्सटेंशन स्ट्रक्चर में स्वैपचेन इमेज के इस्तेमाल के फ़्लैग शामिल हैं:

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 बना सकता है. ऐप्लिकेशन पहले vkCreateImage को कॉल करता है. इसमें VkImageSwapchainCreateInfoKHR स्ट्रक्चर, VkImageCreateInfo स्ट्रक्चर से जुड़ा होता है. इसके बाद, ऐप्लिकेशन vkBindImageMemory2(KHR) को कॉल करता है. इसमें VkBindImageMemorySwapchainInfoKHR स्ट्रक्चर, VkBindImageMemoryInfo स्ट्रक्चर से जुड़ा होता है. VkBindImageMemorySwapchainInfoKHR स्ट्रक्चर में बताया गया imageIndex, स्वैपचेन इमेज का मान्य इंडेक्स होना चाहिए. इस बीच, प्लैटफ़ॉर्म VkBindImageMemoryInfo चेन को VkNativeBufferANDROID एक्सटेंशन स्ट्रक्चर के साथ-साथ, उससे जुड़ी Gralloc बफ़र की जानकारी भी देता है. इससे ड्राइवर को यह पता चलता है कि VkImage को किस Gralloc बफ़र के साथ बाइंड करना है.

इमेज पाना

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 बाहरी इस्तेमाल के लिए स्वैपचेन इमेज तैयार करता है, नेटिव फ़ेंस बनाता है, और नेटिव फ़ेंस को इनपुट सेमाफ़ोर के सिग्नल देने के बाद सिग्नल देने के लिए शेड्यूल करता है:

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

दी गई कतार में vkQueuePresentKHR() कॉल vkQueueSignalReleaseImageANDROID(). ड्राइवर को एक नेटिव फ़ेंस बनाना होगा. यह तब तक सिग्नल नहीं देगा, जब तक waitSemaphoreCount में मौजूद सभी pWaitSemaphores सिग्नल नहीं देते. साथ ही, image को प्रज़ेंटेशन के लिए तैयार करने से जुड़ा कोई भी ज़रूरी काम पूरा नहीं हो जाता.

अगर इंतज़ार करने वाले सेमाफ़ोर (अगर कोई है) पहले से ही सिग्नल दे चुके हैं और queue पहले से ही निष्क्रिय है, तो ड्राइवर, नेटिव फ़ेंस फ़ाइल डिस्क्रिप्टर के बजाय *pNativeFenceFd को -1 पर सेट कर सकता है. इससे पता चलता है कि अब किसी भी चीज़ का इंतज़ार नहीं करना है. कॉलर के पास, *pNativeFenceFd में दिखाए गए फ़ाइल डिस्क्रिप्टर का मालिकाना हक होता है और वह इसे बंद कर सकता है.

कई ड्राइवर, इमेज पैरामीटर को अनदेखा कर सकते हैं. हालांकि, कुछ को बाहरी इमेज उपभोक्ताओं के इस्तेमाल के लिए, Gralloc बफ़र से जुड़े सीपीयू-साइड डेटा स्ट्रक्चर तैयार करने पड़ सकते हैं. बाहरी उपभोक्ताओं के इस्तेमाल के लिए बफ़र कॉन्टेंट तैयार करने का काम, एसिंक्रोनस तरीके से किया जाना चाहिए. ऐसा VK_IMAGE_LAYOUT_PRESENT_SRC_KHR में इमेज को ट्रांज़िशन करने के दौरान किया जाना चाहिए.

अगर इमेज को VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID की मदद से बनाया गया है, तो ड्राइवर को vkQueueSignalReleaseImageANDROID() को बार-बार कॉल करने की अनुमति देनी होगी. साथ ही, vkAcquireImageANDROID() को कॉल करने के दौरान, vkQueueSignalReleaseImageANDROID() को कॉल करने में कोई रुकावट नहीं आनी चाहिए.

शेयर की जा सकने वाली इमेज से जुड़ी सुविधा

कुछ डिवाइसों में, डिसप्ले पाइपलाइन और 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 पर सेट करता है.

Validation

ओईएम, सीटीएस का इस्तेमाल करके Vulkan को लागू करने की जांच कर सकते हैं. इसमें ये शामिल हैं:

  • CtsDeqpTestCases मॉड्यूल में Khronos Vulkan Conformance टेस्ट शामिल हैं. इनमें 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 की तारीख से मेल खाती है. यह तारीख, Android 10 के लिए Vulkan dEQP टेस्ट से जुड़ी है. अगर फ़ीचर फ़्लैग की वैल्यू कम से कम इतनी है, तो डिवाइस यह दावा करता है कि उसने Android 10 के सभी Vulkan dEQP टेस्ट पास कर लिए हैं.

वैल्यू 0x07E40301, 2020-03-01 की तारीख से मेल खाती है. यह तारीख, Android 11 के लिए Vulkan dEQP टेस्ट से जुड़ी है. अगर सुविधा का फ़्लैग कम से कम इस वैल्यू पर सेट है, तो डिवाइस Android 11 के सभी Vulkan dEQP टेस्ट पास कर लेता है.

वैल्यू 0x07E60301, 2022-03-01 की तारीख से मेल खाती है. यह तारीख, Android 13 के लिए Vulkan dEQP टेस्ट से जुड़ी है. अगर फ़ीचर फ़्लैग की वैल्यू कम से कम इतनी है, तो इसका मतलब है कि डिवाइस ने Android 13 के Vulkan dEQP के सभी टेस्ट पास कर लिए हैं.

कोई ऐसा डिवाइस जो किसी खास फ़ीचर फ़्लैग (जैसे कि 0x07E30301, 0x07E40301, 0x07E60301) को दिखाता है, वह उस फ़ीचर फ़्लैग (क्रमशः Android 10, Android 11, Android 13) के सभी Android Vulkan dEQP टेस्ट पास करने का दावा करता है. ऐसा हो सकता है कि यह डिवाइस, Android के बाद के वर्शन में Vulkan dEQP टेस्ट पास कर ले.

Vulkan dEQP, Android CTS का हिस्सा है. Android 11 से, CTS का dEQP टेस्ट रनर कॉम्पोनेंट, android.software.vulkan.deqp.level फ़ीचर फ़्लैग के बारे में जानता है. साथ ही, यह उन सभी Vulkan dEQP टेस्ट को स्किप कर देता है जिनके बारे में इस फ़ीचर फ़्लैग के हिसाब से, डिवाइस यह दावा नहीं करता कि वह उन्हें सपोर्ट करता है. इस तरह की जांचों को, आसानी से पास होने वाली जांचों के तौर पर रिपोर्ट किया जाता है.