Vulkan लागू करना

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

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

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

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

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

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

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

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

डिबग किए जा सकने वाले ऐप्लिकेशन के लिए, लोडर इन फ़ोल्डर में लेयर खोजता है: /data/local/debug/vulkan. साथ ही, किसी खास पैटर्न से मेल खाने वाली लाइब्रेरी को लोड करने की कोशिश करता है. Android 10 (एपीआई लेवल 29) से, Vulkan किसी दूसरे APK से डेवलपमेंट-टाइम लेयर भी लोड कर सकता है. दोनों मामलों में, लोडर यह चुनता है कि हर ऐप्लिकेशन के लिए कौनसी लेयर चालू करनी हैं. इसके लिए, वह सिस्टम सेटिंग का इस्तेमाल करता है. इन लेयर को vkEnumerateInstanceLayerProperties में शामिल किया गया है. इसका मतलब है कि ऐप्लिकेशन को इनके बारे में जानकारी हो सकती है. भले ही, इन्हें ऐप्लिकेशन की सहमति के बिना लोड किया गया हो.

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

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

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

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

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

Vulkan 1.3 में कई छोटी सुविधाएं भी शामिल हैं. साथ ही, एपीआई के इस्तेमाल को बेहतर बनाया गया है. Vulkan 1.3 के मुख्य एपीआई में किए गए सभी बदलावों के बारे में जानने के लिए, मुख्य बदलाव (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 के माइनर रिवीज़न में, Vulkan API के मुख्य हिस्से में किए गए सभी बदलावों के बारे में यहां जानकारी दी गई है: 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 API के मुख्य वर्शन 1.1 में किए गए सभी बदलावों के बारे में जानने के लिए, Core Revisions (Vulkan 1.1) पर जाएं.

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

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

Android 16 और इसके बाद के वर्शन के साथ लॉन्च होने वाले डिवाइसों में, Vulkan 1.4 काम करना चाहिए.

Android 13 और इसके बाद के वर्शन के साथ लॉन्च होने वाले डिवाइसों में, Vulkan 1.3 का इस्तेमाल किया जाना चाहिए.

Android 10 के साथ लॉन्च होने वाले डिवाइसों पर, Vulkan 1.1 काम करना चाहिए.

अन्य डिवाइसों पर, Vulkan 1.4, 1.3, 1.2, और 1.1 का इस्तेमाल किया जा सकता है.

Vulkan के किसी वर्शन के साथ काम करना

किसी Android डिवाइस पर Vulkan का कोई वर्शन तब काम करता है, जब ये शर्तें पूरी होती हैं:

  1. Vulkan के उस वर्शन के साथ काम करने वाला Vulkan ड्राइवर जोड़ें जिसके बारे में आपको जानकारी चाहिए. यह Vulkan 1.4, 1.3, 1.1 या 1.0 वर्शन में से कोई एक होना चाहिए. साथ ही, Android वर्शन की सीडीडी की अन्य ज़रूरी शर्तों को पूरा करना चाहिए. इसके अलावा, Vulkan के कम वर्शन नंबर वाले मौजूदा Vulkan ड्राइवर को अपडेट करें.
  2. Vulkan 1.4, 1.3 या 1.1 के लिए, पुष्टि करें कि पैकेज मैनेजर से मिली सिस्टम सुविधा, Vulkan के सही वर्शन के लिए true दिखाती हो.
    • 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) है.
    पैकेज मैनेजर, Vulkan 1.4, 1.3, और 1.1 के लिए true दिखाएगा. इसके लिए, वह 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 बेसलाइन प्रोफ़ाइल (एबीपी)

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

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(), swapchain usage फ़्लैग या Gralloc usage फ़्लैग के एक्सटेंशन के साथ काम नहीं करता.

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 को कॉल करता है. इसमें VkImageCreateInfo स्ट्रक्चर से जुड़ा VkImageSwapchainCreateInfoKHR स्ट्रक्चर होता है. इसके बाद, ऐप्लिकेशन 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() को कॉल करने में कोई रुकावट नहीं आनी चाहिए.

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

कुछ डिवाइसों में, डिसप्ले पाइपलाइन और Vulkan के बीच एक ही इमेज का मालिकाना हक शेयर किया जा सकता है, ताकि लेटेन्सी को कम किया जा सके. Android 9 और इसके बाद के वर्शन में, ड्राइवर के VK_KHR_shared_presentable_image पर कॉल करने के जवाब के आधार पर, लोडर 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, और 1.4 के लिए फ़ंक्शनल एपीआई टेस्ट शामिल हैं.
  • CtsGraphicsTestCases मॉड्यूल, जो यह जांच करता है कि डिवाइस को Vulkan की उन सुविधाओं के लिए सही तरीके से कॉन्फ़िगर किया गया है जो इस पर काम करती हैं.

Vulkan फ़ीचर फ़्लैग

किसी डिवाइस पर फ़ीचर फ़्लैग, android.software.vulkan.deqp.level को दिखाने के लिए, यह ज़रूरी है कि उस पर Android 11 या इसके बाद का वर्शन काम करता हो. साथ ही, उस पर Vulkan API काम करता हो. इस सुविधा फ़्लैग की वैल्यू एक तारीख होती है. इसे पूर्णांक के तौर पर कोड किया जाता है. इससे उस तारीख के बारे में पता चलता है जब डिवाइस ने 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 टेस्ट को छोड़ देता है जिनके बारे में इस फ़ीचर फ़्लैग के हिसाब से, डिवाइस यह दावा नहीं करता कि वह उन्हें सपोर्ट करता है. इस तरह की जांचों को, आसानी से पास होने वाली जांचों के तौर पर रिपोर्ट किया जाता है.