實作 Vulkan

Vulkan 是低負擔 適用於高效能 3D 的跨平台 API 圖像。就像 OpenGL ES (GLES): Vulkan 提供多種工具,可打造優質的優質應用程式 在應用程式中顯示即時圖像使用 Vulkan 的優點包括減少 CPU SPIR-V 二進位制中介語言的負擔與支援。

如要成功實作 Vulkan,裝置必須包含:

  • Android 提供的 Vulkan 載入器。
  • 一種 Vulkan 驅動程式,由 GPU IHV 等 SoC 提供, 會實作 Vulkan API:為了支援 Vulkan 功能,Android 裝置需要支援 Vulkan 的 GPU 硬體和相關驅動程式。GPU 必須同時支援 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 進入點,也就是擴充功能的進入點 以及許多其他選用擴充功能。視窗 系統整合 (WSI) 擴充功能會由載入器匯出,主要 載入,而非驅動程式中實作。載入器也支援 列舉及載入可能公開其他擴充功能與攔截的圖層 發出核心 API 呼叫

NDK 包含以下項目的虛設常式 libvulkan.so 程式庫: 。程式庫匯出的符號與載入器相同。應用程式會呼叫函式 從真正的 libvulkan.so 程式庫匯出至 在載入器中輸入 Trampoline 函式,該函式會調度至適當的 產生圖層或驅動程式vkGet*ProcAddr() 呼叫會傳回彈跳床分派的函式指標 (也就是 就會直接呼叫核心 API 程式碼)透過函式呼叫 比起匯出的符號,指標的效率更高, 就會略過彈跳床和派遣。

驅動程式列舉和載入

建構系統映像檔時,Android 會預期系統知道哪些 GPU 可以使用。載入器採用 hardware.h 輕鬆尋找並載入驅動程式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 衍生工具 包裝單一 hw_module_t 結構;僅支援一個驅動程式,而常數字串 HWVULKAN_DEVICE_0 已傳遞至 open()

Vulkan hw_device_t 導數對應單一 可支援多種實體裝置的驅動程式。 hw_device_t結構可延伸至匯出 vkGetGlobalExtensionProperties()vkCreateInstance()vkGetInstanceProcAddr() 函式。載入器可以找出其他 VkInstance()VkPhysicalDevice()和 呼叫 vkGetDeviceProcAddr() 函式 hw_device_t 結構的 vkGetInstanceProcAddr()

探索和載入圖層

Vulkan 載入器支援列舉及載入可能公開的圖層 額外的擴充功能、攔截核心 API 呼叫, 驅動程式庫。Android 不含層在系統映像檔上。不過 應用程式的 APK 可能含有圖層。

使用圖層時,請謹記 Android 的安全性模型和政策。 與其他平台有極大差異具體來說,Android 禁止 在實際工作環境中 (未啟用 Root 權限) 將外部程式碼載入無法進行偵錯的程序 也無法讓外部程式碼檢查或控制 例如記憶體、狀態等等包括禁止儲存核心傾印、API 追蹤等內容只有做為一部分的圖層 正式版裝置已啟用不可進行偵錯的應用程式,且驅動程式不得提供 違反這些政策的功能

圖層的用途包括:

  • 開發期間圖層 - 驗證 不得安裝追蹤/剖析/偵錯工具的資料層和雜湊碼 實際工作環境裝置的系統映像檔驗證層和填充程式 追蹤/剖析/偵錯工具應可在沒有系統的情況下更新 圖片。想要使用單一語言模型的開發人員 可以修改應用程式套件,例如 只需將檔案新增至原生資料庫目錄即可IHV 和原始設備製造商 (OEM) 工程師 想在無法修改的應用程式運送中診斷失敗的狀況,系統會假設 存取非正式 (已啟用 Root 權限) 的系統映像檔版本 (除非這些應用程式 可進行偵錯詳情請參閱「Android 上的 Vulkan 驗證層」。
  • 公用程式圖層 — 這些層會公開 例如,為裝置記憶體實作記憶體管理員的圖層。 開發人員自行選擇要使用的圖層 應用程式;同一個圖層的不同應用程式仍可使用 不同版本開發人員選擇要導入這些圖層 應用程式套件。
  • 插入 (隱式) 圖層 - 包括 使用者提供的影格速率、社群網路與遊戲啟動器重疊元素 或未取得對方同意。這些 違反 Android 安全性政策,就不在支援範圍內

對於無法進行偵錯的應用程式,載入器只會在 應用程式的原生資料庫目錄,並嘗試載入具有名稱的任何程式庫 與特定模式相符 (例如 libVKLayer_foo.so)。

對於可進行偵錯的應用程式,載入器會搜尋 請/data/local/debug/vulkan,並嘗試載入任何符合 特定模式

Android 可讓您在不同版本與建構環境之間變更層,以便移植圖層 Android 和其他平台如需各層和 載入器,請參閱 Vulkan 載入器介面的架構。克倫諾斯維護 驗證層的 Vulkan 驗證層

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 程式設計介面操作。不再需要單傳遞算繪通道執行個體 會轉譯傳遞物件或 framebuffers您可以減少管道狀態物件的總數 API 內的同步處理 > 發生。Vulkan 1.3 的硬體需求與 Vulkan 1.2、1.1 和 1.0,大部分是在 SoC 專屬圖形驅動程式中實作,而非 架構中的一環

Android 最重要的 Vulkan 1.3 功能如下:

  • 支援單傳遞算繪通道執行個體
  • 支援立即終止著色器叫用
  • 能精細處理管道的建立、共用和控管作業

Vulkan 1.3 還包含多項小型功能和 API 可用性改善項目。所有變更 對核心 Vulkan API 進行輕微修訂版本 1.3 的內容會列於 核心修訂版本 (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 可用性提升。所有變更 對核心 Vulkan API 進行輕微修訂版本 1.2 的內容會列於 核心修訂版本 (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 功能如下:

  • 支援匯入及匯出記憶體緩衝區和同步 物件 (適用於與相機、轉碼器和 GLES 的互通性)
  • 支援 YCbCr 格式

Vulkan 1.1 還包含多項小型功能和 API 可用性改善項目。所有變更 至於對核心 Vulkan API 進行輕微修訂版本 1.1 的變更,請參閱 Core 修訂版本 (Vulkan 1.1)

選擇 Vulkan 支援

Android 裝置應支援最先進的 Vulkan 功能集 且不必使用低記憶體

搭載 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),配合其他 CDD 規定, Android 版本。或者,您也可以更新現有的 Vulkan 驅動程式,採用較低的 Vulkan 版本號碼。
  2. 如果是 Vulkan 1.3 或 1.1,請確保套件管理員傳回的系統功能會傳回 true 代表正確的 vulkan 版本。
    • 對於 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 基準設定檔 (ABP)

我們建議所有 Android 裝置都符合最新的 Android Baseline 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 中

VkSurfaceKHRVkSwapchainKHR 物件和所有 與 ANativeWindow 的互動會由平台處理,而非 暴露在司機中。進行 WSI 實作時,仰賴 VK_ANDROID_native_buffer 副檔名,必須是 下載元件;這項擴充功能僅供 WSI 實作使用 並不會向應用程式公開

Gralloc 使用標記

Vulkan 實作可能需要交換鏈緩衝區,才能進行配置 實作定義的 Private Gralloc 使用標記建立交換鏈時 Android 要求駕駛人翻譯要求的格式和圖片使用方式 藉由呼叫:

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
);

formatimageUsage 參數的來源 VkSwapchainCreateInfoKHR 結構。駕駛人應填滿 *grallocConsumerUsage*grallocProducerUsage: 格式化所需的 Gralloc 使用標記 和使用方式驅動程式傳回的使用旗標會與 分配緩衝區時交換鏈使用者要求的旗標。

Android 7.x 呼叫舊版 VkSwapchainImageUsageFlagsANDROID()vkGetSwapchainGrallocUsageANDROID()。Android 8.0 以上版本淘汰項目 vkGetSwapchainGrallocUsageANDROID() (仍在通話中) 如果符合條件,則為vkGetSwapchainGrallocUsageANDROID() vkGetSwapchainGrallocUsage2ANDROID() 並非由驅動程式提供:

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

vkGetSwapchainGrallocUsageANDROID() 不支援交換鏈 標記或擴充 Gralloc 使用標記

採用 Gralloc 技術的圖片

VkNativeBufferANDROID」是vkCreateImage擴充功能 建立由 Gralloc 緩衝區支援的圖片的結構VkNativeBufferANDROID 是 提供給「VkImageCreateInfo」中的「vkCreateImage()」 架構鏈。使用 VkNativeBufferANDROID 撥打 vkCreateImage() 在呼叫 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」 必須在交換鏈中須使用任何交換鏈映像檔標記。 擴充功能結構包含交換鏈圖片使用旗標:

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 第 70 版,讓 Vulkan 應用程式可以建立 VkImage 由交換鏈記憶體支援。應用程式首次呼叫 具有VkImageSwapchainCreateInfoKHRvkCreateImageVkImageCreateInfo 結構鏈結在一起接著, 應用程式會透過vkBindImageMemory2(KHR) VkBindImageMemorySwapchainInfoKHR 結構與 VkBindImageMemoryInfo 結構。imageIndex 指定的 VkBindImageMemorySwapchainInfoKHR 結構中 為有效的交換鏈圖片索引。同時,這個平台提供了 VkNativeBufferANDROID 擴充功能結構,其中包含相對應的 指向 VkBindImageMemoryInfo 鏈結的 Gralloc 緩衝區資訊 驅動程式知道要與哪個 Gralloc 緩衝區繫結 VkImage

取得圖片

vkAcquireImageANDROID 取得交換鏈圖像的擁有權 並將外部信號的原生圍欄匯入 VkSemaphore 物件和現有的 VkFence 物件:

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

系統會在以下期間呼叫 vkAcquireImageANDROID() 使用 vkAcquireNextImageKHR 匯入 原生圍欄至 VkSemaphoreVkFence 物件 但實際上 smaphore 和 Fence 物件 為選擇性)。駕駛人也可能會利用這個機會 並處理 Gralloc 緩衝區狀態的任何外部變更許多駕駛人不會 不需要執行任何動作這項呼叫會執行 VkSemaphoreVkFence處於待處理狀態,與 vkQueueSubmit 發出訊號時相同。 讓佇列可以等待映射,應用程式可以等待圍欄。

當基礎原生圍欄信號時,兩個物件都會發出信號;如果 原生圍欄已發出訊號 並將地震置於信號的信號中 狀態。駕駛人取得圍欄檔案的擁有權 ,並且關閉不再需要的 Fence 檔案描述元。駕駛人 即使未提供地震或圍欄,或 vkAcquireImageANDROID 失敗,並傳回錯誤。如果 fenceFd 是 -1,這就跟原生圍欄已經一樣 並保持連線

發布映像檔

vkQueueSignalReleaseImageANDROID 準備了 原生圍欄、建立原生圍欄,並安排在 輸入的熱視圖有以下特徵:

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

vkQueuePresentKHR() 撥打 vkQueueSignalReleaseImageANDROID() 結果。駕駛必須產生無訊號的原生圍欄 直到總共 waitSemaphoreCountpWaitSemaphores 訊號,並且需要執行其他工作 image 為簡報完成準備。

如果等待同類群組 (如有) 已傳送信號,且 queue 已 駕駛可以設定「*pNativeFenceFd」 改為 -1 而非實際的原生 Fence 檔案描述元,表示 不必費心等待呼叫端擁有並關閉檔案描述元 於 *pNativeFenceFd 中傳回。

許多驅動程式可以忽略圖片參數,但有些驅動程式可能需要 與 Gralloc 緩衝區相關聯的 CPU 端資料結構,供外部使用 圖片消費者準備供外部消費者使用的緩衝區內容, 將映像檔轉換至 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

驗證

原始設備製造商 (OEM) 可以使用 CTS 測試 Vulkan 實作成果,其中包括:

  • Khronos Vulkan 一致性測試CtsDeqpTestCases 模組中 ,包含適用於 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 分店
  • Bits 16-23 (當月商店)
  • 每天挑選小畢店 24 到 31 點

功能旗標的下限為 0x07E30301。 所對應的日期是 2019-03-01,也就是與 適用於 Android 10 的 Vulkan dEQP 測試。如果功能旗標至少為這個值 裝置聲稱通過所有 Android 10 Vulkan dEQP 測試。

0x07E40301 對應到 2020 年 3 月 1 日的日期,也就是 與 Android 11 的 Vulkan dEQP 測試相關的日期。如果功能 旗標至少為這個值,則裝置聲稱會通過所有 Android 11 Vulkan dEQP 測試。

0x07E60301 對應 2022-03-01 的日期,也就是 與 Vulkan dEQP 測試相關的日期 Android 13。如果功能旗標至少為這個值 裝置宣稱能通過所有 Android 13 Vulkan dEQP 測試。

提供特定功能標記 (例如 0x07E303010x07E403010x07E60301) 宣稱通過該功能旗標的所有 Android Vulkan dEQP 測試 (Android 10、 Android 11、Android 13)。此裝置 「可能」能從較新的 Android 版本通過 Vulkan dEQP 測試。

Vulkan dEQP 是 Android CTS 的一部分。從 Android 11 開始,dEQP 測試執行器 CTS 的元件感知到 android.software.vulkan.deqp.level 並略過任何 Vulkan dEQP 測試,根據 功能旗標 - 裝置未聲稱可支援。這類測試 並回報為經常傳來的