Vulkan の実装

Vulkan は、高パフォーマンスの 3D グラフィックを実現する、低オーバーヘッドのクロス プラットフォーム API です。OpenGL ES(GLES)と同様に、Vulkan はアプリで高品質のリアルタイム グラフィックを生成するためのツールを提供します。Vulkan を使用するメリットとしては、CPU オーバーヘッドを削減できることや、SPIR-V バイナリ中間言語がサポートされることなどがあります。

Vulkan を実装するには、デバイスに次のものが必要です。

  • Vulkan ローダー(Android で提供)。
  • Vulkan API を実装する Vulkan ドライバ(GPU IHV などの SoC で提供)。Vulkan の機能をサポートするには、Android デバイスに Vulkan 対応の GPU ハードウェアと関連するドライバが必要です。また、GPU は GLES 3.1 以降をサポートする必要があります。ドライバのサポートについては、SoC ベンダーにお問い合わせください。

デバイスが Vulkan ドライバを搭載している場合、デバイスで FEATURE_VULKAN_HARDWARE_LEVELFEATURE_VULKAN_HARDWARE_VERSION のシステム機能を、デバイスの機能を正確に反映したバージョンを含めて宣言する必要があります。これにより、デバイスが互換性定義ドキュメント(CDD)に準拠するようになります。

Vulkan ローダー

Vulkan ローダーである platform/frameworks/native/vulkan は、Vulkan アプリとデバイスの Vulkan ドライバとの間のプライマリ インターフェースです。Vulkan ローダーは /system/lib[64]/libvulkan.so にインストールされます。このローダーは、コア Vulkan API のエントリ ポイント、Android CDD で必要な拡張機能のエントリ ポイント、その他多くのオプションの拡張機能として機能します。ウィンドウ システム統合(WSI)拡張機能は、このローダーによってエクスポートされ、主にドライバではなくローダーに実装されます。このローダーは、追加の拡張機能を提供したり、コア API の呼び出しをドライバに渡る途中でインターセプトしたりできるレイヤの列挙と読み込みにも対応しています。

NDK には、リンク用のスタブ libvulkan.so ライブラリが含まれています。このライブラリは、ローダーと同じシンボルをエクスポートします。アプリは、実際の libvulkan.so ライブラリからエクスポートされた関数を呼び出して、ローダーのトランポリン関数に入り、トランポリン関数は最初の引数に基づいて適切なレイヤまたはドライバにディスパッチします。vkGet*ProcAddr() の呼び出しは、トランポリンがディスパッチする先の関数ポインタを返します(つまりコア API コードを直接呼び出します)。エクスポートされたシンボルではなく、関数ポインタを使って呼び出すと、トランポリンとディスパッチが省略されるので効率的です。

ドライバの列挙と読み込み

システム イメージをビルドする際、Android はシステムが使用可能な GPU を認識していると想定します。ローダーは、hardware.h にある既存の HAL メカニズムを使用してドライバを検出し、読み込みます。32 ビットと 64 ビットの Vulkan ドライバの推奨パスは次のとおりです。

/vendor/lib/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib/hw/vulkan.<ro.product.platform>.so
/vendor/lib64/hw/vulkan.<ro.hardware.vulkan>.so
/vendor/lib64/hw/vulkan.<ro.product.platform>.so

Android 7.0 以降では、Vulkan hw_module_t の派生 API は単一の hw_module_t 構造体をラップしています。1 つのドライバのみがサポートされ、定数文字列 HWVULKAN_DEVICE_0open() に渡されます。

Vulkan hw_device_t の派生 API は、複数の物理デバイスをサポートできる 1 つのドライバに対応します。hw_device_t 構造体を拡張して vkGetGlobalExtensionProperties() 関数、vkCreateInstance() 関数、vkGetInstanceProcAddr() 関数をエクスポートできます。ローダーは、hw_device_t 構造体の vkGetInstanceProcAddr() を呼び出すことにより、他のすべての VkInstance() 関数、VkPhysicalDevice() 関数、vkGetDeviceProcAddr() 関数を見つけることができます。

レイヤの検出と読み込み

Vulkan ローダーは、追加の拡張機能を提供したり、ドライバに渡る途中でコア API の呼び出しをインターセプトしたりできるレイヤの列挙と読み込みにも対応しています。Android ではシステム イメージにレイヤは含まれませんが、アプリでは APK にレイヤを含めることができます。

レイヤを使用する際には、Android のセキュリティ モデルとセキュリティ ポリシーが他のプラットフォームと大きく異なる点に注意してください。特に、Android では、外部コードを本番環境の(ルート権限を取得していない)デバイスのデバッグ不可能なプロセスに読み込むことも、外部コードがプロセスのメモリや状態などを調査したり制御したりすることも許可されません。また、コアダンプや API トレースなどを後で調査するためにディスクに保存することも禁止されています。デバッグ不可能なアプリの一部として配信されるレイヤのみが本番環境のデバイスで有効になります。ドライバがこれらのポリシーに違反する機能を提供してはなりません。

レイヤには次のユースケースがあります。

  • 開発時レイヤ - トレースツール、プロファイリング ツール、デバッグツール用の検証レイヤと shim は、本番デバイスのシステム イメージにインストールするべきではありません。トレースツール、プロファイリング ツール、デバッグツール用の検証レイヤと shim は、システム イメージなしで更新できるようにする必要があります。開発中にこれらのレイヤのいずれかを使用するデベロッパーは、たとえばネイティブ ライブラリ ディレクトリにファイルを追加するなどして、アプリ パッケージを変更できます。変更不可能なアプリを配信する際にエラーを診断する IHV と OEM のエンジニアは、アプリがデバッグ可能でない限り、システム イメージの非本番(ルート権限を取得した)ビルドにアクセスできるとみなされます。詳細については、Android の Vulkan 検証レイヤをご覧ください。
  • ユーティリティ レイヤ - デバイスメモリのメモリ マネージャーを実装するレイヤなどの拡張機能を公開します。デベロッパーは、アプリで使用するレイヤやそのバージョンを選択します。同じレイヤを使用する別のアプリでも異なるバージョンを使用できます。デベロッパーは、アプリ パッケージに同梱するレイヤを選択します。
  • 注入(非明示的)レイヤ - フレームレート、ソーシャル ネットワーク、アプリが認識または同意することなくユーザーや他のアプリによって提供されたゲーム ランチャー オーバーレイなどのレイヤです。これらは Android のセキュリティ ポリシーに違反しているためサポートされていません。

デバッグ不可能なアプリの場合、ローダーはアプリのネイティブ ライブラリ ディレクトリのみでレイヤを検索し、特定のパターンに一致する名前のライブラリを読み込みます(たとえば、libVKLayer_foo.so)。

デバッグ可能なアプリの場合、ローダーは /data/local/debug/vulkan でレイヤを検索し、特定のパターンに一致するライブラリを読み込みます。

Android では、Android と他のプラットフォームとの間でのビルド環境の変更を含めてレイヤを移植できます。レイヤとローダーとの間のインターフェースの詳細については、Architecture of the 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 プログラミング インターフェースを介して制御と粒度を強化することを目的としています。シングルパス レンダリング パス インスタンスでは、レンダリング パス オブジェクトまたはフレームバッファが不要になりました。パイプライン状態オブジェクトの総数を減らすことができ、API 内の同期が全面的に見直されています。Vulkan 1.3 のハードウェア要件は Vulkan 1.2、1.1、1.0 と同じです。ほとんどの実装は SoC 固有のグラフィック ドライバ内にあり、フレームワーク内にはありません。

Android で最も重要な Vulkan 1.3 の機能を次に示します。

  • シングルパス レンダリング パス インスタンスのサポート
  • シェーダー呼び出しの即時終了のサポート
  • パイプラインの作成、共有、制御のより細かい粒度

Vulkan 1.3 では、他にもいくつかの機能拡張と API のユーザビリティ改善が行われています。マイナー リビジョン 1.3 を使用してコア Vulkan API に加えられたすべての変更については、コアリビジョン(Vulkan 1.3)をご覧ください。

Vulkan 1.2 の機能の概要

Vulkan 1.2 では、API サーフェスを簡素化するさまざまな機能と拡張機能が追加されています。これには、統合されたメモリモデルと、デバイス ドライバからクエリできる追加情報が含まれます。Vulkan 1.2 のハードウェア要件は、Vulkan 1.0 および 1.1 と同じです。すべての実装は SoC 固有のグラフィック ドライバ内にあり、フレームワーク内にはありません。

Android で最も重要な Vulkan 1.2 の機能は、8 ビット ストレージのサポートです。

Vulkan 1.2 では、他にもいくつかの機能拡張と API のユーザビリティ改善が行われています。マイナー リビジョン 1.2 を使用してコア Vulkan API に加えられたすべての変更については、コアリビジョン(Vulkan 1.2)をご覧ください。

Vulkan 1.1 の機能の概要

Vulkan 1.1 ではメモリと同期の相互運用がサポートされているため、OEM は Vulkan 1.1 をデバイスでサポートできます。さらに、メモリと同期の相互運用により、デベロッパーは Vulkan 1.1 がデバイスでサポートされているかどうかを判別して、サポートされている場合には効果的に使用できます。Vulkan 1.1 のハードウェア要件は Vulkan 1.0 と同じですが、ほとんどの実装は SOC 固有のグラフィック ドライバ内にあり、フレームワーク内にはありません。

Android で最も重要な Vulkan 1.1 の機能を次に示します。

  • メモリバッファ、同期オブジェクトを Vulkan の外部からインポートおよびエクスポートする機能(カメラ、コーデック、GLES との相互運用のため)
  • YCbCr 形式のサポート

Vulkan 1.1 では、他にもいくつかの機能拡張と API のユーザビリティ改善が行われています。マイナー リビジョン 1.1 を使用してコア Vulkan API に加えられたすべての変更については、コアリビジョン(Vulkan 1.1)をご覧ください。

Vulkan のサポートの選択

Android デバイスは、64 ビット ABI をサポートしメモリが十分ある場合、利用可能な最新の Vulkan 機能セットをサポートする必要があります。

Android 13 以降を搭載したデバイスは、Vulkan 1.3 をサポートする必要があります。

Android 10 を搭載したデバイスは、Vulkan 1.1 をサポートする必要があります。

他のデバイスでも、任意で Vulkan 1.3、1.2、1.1 をサポートできます。

Vulkan バージョンのサポート

Android デバイスは、次の条件が満たされた場合、Vulkan バージョンをサポートします。

  1. 該当の Vulkan バージョン(Vulkan バージョン 1.3、1.1、1.0 のいずれかである必要があります)をサポートする Vulkan ドライバを、Android バージョンの追加の CDD 要件とともに追加します。または、下位の 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) です。
    パッケージ マネージャーは、次のようなルールを適切な device.mk ファイルに追加することにより、Vulkan 1.3 と Vulkan 1.1 の 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
      

ウィンドウ システム統合(WSI)

libvulkan.so では、ドライバが次のウィンドウ システム統合(WSI)拡張機能を実装します。

  • 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() に提供されます。vkCreateSwapchainKHR への呼び出し中に、VkNativeBufferANDROID を伴う vkCreateImage() の呼び出しが発生します。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 を作成できます。アプリは最初に VkImageCreateInfo 構造体にチェーンされている VkImageSwapchainCreateInfoKHR 構造体で vkCreateImage を呼び出します。次に、アプリは VkBindImageMemoryInfo 構造体にチェーンされている VkBindImageMemorySwapchainInfoKHR 構造体で vkBindImageMemory2(KHR) を呼び出します。VkBindImageMemorySwapchainInfoKHR 構造体で指定されている imageIndex は、有効なスワップチェーン画像インデックスである必要があります。また、プラットフォームが対応する Gralloc バッファ情報を持つ VkNativeBufferANDROID 拡張構造体を VkBindImageMemoryInfo チェーンに提供するため、ドライバは VkImage とバインドする Gralloc バッファを認識します。

画像の確保

vkAcquireImageANDROID はスワップチェーン画像の所有権を取得し、外部からシグナル状態にされたネイティブ フェンスを既存の VkSemaphore オブジェクトと既存の VkFence オブジェクトにインポートします。

VkResult VKAPI vkAcquireImageANDROID(
    VkDevice            device,
    VkImage             image,
    int                 nativeFenceFd,
    VkSemaphore         semaphore,
    VkFence             fence
);

vkAcquireNextImageKHR の最中に vkAcquireImageANDROID() が呼び出されて、ネイティブ フェンスがアプリによって作成された VkSemaphore オブジェクトと VkFence オブジェクトにインポートされます。ただし、この呼び出しではセマフォ オブジェクトとフェンス オブジェクトはどちらも任意です。ドライバはこの機会を利用して、Gralloc バッファの状態への外部変更を認識して処理することもできます。ほとんどのドライバは、ここで何かを行う必要はありません。この呼び出しは、vkQueueSubmit によってシグナル状態にされたかのように VkSemaphoreVkFence を同じ保留状態にできます。このため、キューはセマフォで待機でき、アプリはフェンスで待機できます。

両方のオブジェクトは、中にあるネイティブ フェンスがシグナルを発信するとシグナル状態になります。ネイティブ フェンスがすでにシグナルを発信している場合、セマフォはこの関数が終了したときにシグナル状態になります。ドライバは、フェンスのファイル記述子の所有権を取得し、不要になったときにフェンスのファイル記述子を閉じます。ドライバは、セマフォ オブジェクトとフェンス オブジェクトのどちらも指定されていない場合、または vkAcquireImageANDROID が失敗してエラーが返された場合にも、これを行います。fenceFd が -1 の場合、ネイティブ フェンスがすでにシグナル状態であるかのようになります。

画像の解放

vkQueueSignalReleaseImageANDROID は、外部使用のためにスワップチェーン画像を準備し、ネイティブ フェンスを作成して、入力セマフォがシグナルを発信した後にネイティブ フェンスがシグナル状態になるようにスケジュールします。

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

vkQueuePresentKHR() は提供されたキューの vkQueueSignalReleaseImageANDROID() を呼び出します。ドライバは、pWaitSemaphores のすべての waitSemaphoreCount セマフォがシグナルを発信して、image の表示に必要なその他の作業がすべて完了するまで、シグナルを発信しないネイティブ フェンスを生成する必要があります。

待機セマフォが存在してすでにシグナル状態であり、queue がすでにアイドル状態である場合、ドライバは、実際のネイティブ フェンスのファイル記述子ではなく -1*pNativeFenceFd を設定し、待機する対象がないことを示します。呼び出し元は、*pNativeFenceFd に返されたファイル記述子の所有権を取得して閉じます。

多くのドライバは、image パラメータを無視できますが、一部のドライバでは、外部の画像コンシューマーが使用するために Gralloc バッファに関連付けられた CPU 側のデータ構造を準備する必要があります。外部コンシューマーが使用するバッファ コンテンツの準備は、イメージから VK_IMAGE_LAYOUT_PRESENT_SRC_KHR への遷移の一環として非同期に行う必要があります。

VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_ANDROID を指定して画像が作成された場合、ドライバは vkAcquireImageANDROID() への呼び出しを妨げることなく vkQueueSignalReleaseImageANDROID() を繰り返し呼び出せるようにする必要があります。

共有表示可能画像のサポート

一部のデバイスでは、ディスプレイ パイプラインと Vulkan の実装との間で、単一の画像の所有権を共有して、レイテンシを最小化できます。Android 9 以降では、ローダーは vkGetPhysicalDeviceProperties2 への呼び出しに対するドライバの応答に基づいて VK_KHR_shared_presentable_image 拡張機能を条件付きでアドバタイズします。

ドライバが 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 は、次のような CTS を使用して Vulkan の実装をテストできます。

  • CtsDeqpTestCases モジュールの Khronos Vulkan 適合性テスト(Vulkan 1.0、1.1、1.2、1.3 の API の機能テストが含まれます)。
  • 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 です。これは、Android 10 の Vulkan dEQP テストに関連付けられた日付である 2019-03-01 に相当します。機能フラグがこの値以上であれば、デバイスは Android 10 のすべての Vulkan dEQP テストに合格すると主張していることになります。

また、0x07E40301 という値は、Android 11 の Vulkan dEQP テストに関連付けられた日付である 2020-03-01 に相当します。機能フラグがこの値以上であれば、デバイスは Android 11 のすべての Vulkan dEQP テストに合格すると主張していることになります。

また、0x07E60301 という値は、Android 13 の Vulkan dEQP テストに関連付けられた日付である 2022-03-01 に相当します。機能フラグがこの値以上であれば、デバイスは Android 13 のすべての Vulkan dEQP テストに合格すると主張していることになります。

特定の機能フラグ(0x07E303010x07E403010x07E60301)を公開するデバイスは、その機能フラグ(Android 10、Android 11、Android 13 それぞれ)のすべての Android Vulkan dEQP テストに合格すると主張していることになります。このようなデバイスは、今後の Android リリースの Vulkan dEQP テストに合格する可能性があります

Vulkan dEQP は Android CTS の一部です。Android 11 以降の CTS のテストランナー コンポーネントは、android.software.vulkan.deqp.level 機能フラグを認識し、それに基づいてデバイスがサポートすると主張していない Vulkan dEQP テストをすべてスキップします。このようなテストは、単に通過と報告されます。