將指令碼遷移至 Vulkan

對於最適合 GPU 運算的工作負載,將 RenderScript 指令碼遷移至 Vulkan 運算後,應用程式即可更直接地控管 GPU 硬體,且相較於其他 API,可能獲得額外效能。

以下概略說明內容,可協助您使用 Vulkan 運算著色器取代 RenderScript 指令碼。

Vulkan 初始化

請執行下列步驟,使用 NDK 建立 Vulkan 結構定義,不要在 Kotlin 或 Java 中建立 RenderScript 結構定義物件。

  1. 建立 Vulkan 例項。

  2. 選擇支援運算佇列的 Vulkan 實體裝置。

  3. 建立 Vulkan 邏輯裝置,並取得運算佇列。

您可以選擇在 Android 上設定 Vulkan 驗證層,加快 Vulkan 應用程式的開發速度。

範例應用程式示範了如何在 VulkanContext.h 中初始化 Vulkan 情境。詳情請參閱 Vulkan 規格中的初始化裝置與佇列章節。

Vulkan 分配

RenderScript 分配可遷移至 Vulkan 儲存空間映像檔Vulkan 儲存空間緩衝區。為了提高唯讀圖片的效能,請使用含有擷取作業的取樣圖片,無論是合併圖片取樣器,或有不同的取樣器取樣圖片繫結都使用。

Vulkan 資源在 Vulkan 中配置。為避免在與其他 Android 元件互動時產生記憶體複製負擔,建議您使用 VK_ANDROID_external_memory_android_hardware_buffer 擴充功能將 Android AHardwareBuffer 匯入 Vulkan。這項擴充功能適用於所有支援 Vulkan 1.1 的 Android 裝置。如需詳細資訊,請參閱 FEATURE_VULKAN_HARDWARE_VERSION

範例應用程式示範了如何在 VulkanResources.h 中建立 Vulkan 資源。詳情請參閱 Vulkan 規範的資源建立資源描述元章節。

轉換為 Vulkan 運算著色器

您的 RenderScript 指令碼必須轉換為 Vulkan 運算著色器。您可能還需要根據 RenderScript 全域變數的使用情況來調整程式碼。

撰寫 Vulkan 運算著色器

Vulkan 運算著色器通常是以 OpenGL 著色語言 (GLSL) 編寫,再編譯為 Standard Portable Intermediate Representation-V (SPIR-V) 格式。

如需瞭解如何將著色器整合到應用程式中的詳細資訊和操作說明,請參閱「Android 上的 Vulkan 著色器編譯器」。

調整指令碼全域變數

根據指令碼全域變數的特性,對於未在著色器中修改的全域變數,建議您使用特殊化常數、推送常數或統一緩衝區物件:

  • 特殊化常數:建議用於在不同核心叫用中大致一致的指令碼全域變數。變更特殊化常數值需要重新建立運算管線。
  • 推送常數:建議用於頻繁變更且小於 maxPushConstantsSize (保證大小下限為 128 個位元組) 的指令碼全域變數。
  • 統一緩衝區:建議用於頻繁變更且大於推送常數上限的指令碼全域變數。

對於在著色器內變更的全域變數,您可以使用 Vulkan 儲存空間映像檔Vulkan 儲存空間緩衝區

運算作業

您必須建立 Vulkan 運算管道,才能使 GPU 執行運算著色器。

建立 Vulkan 運算管線

範例應用程式中的 ComputePipeline.h 檔案示範瞭如何建立 Vulkan 運算管道。

如要在 Vulkan 中使用經過編譯的 SPIR-V 著色器,請依下列步驟建構 Vulkan 運算管線:

  1. 使用經過編譯的 SPIR-V 著色器建立著色器模組。
  2. 建立描述元集版面配置,以指定資源繫結 (詳情請參閱配置)。
  3. 根據描述元集版面配置建立描述元集。
  4. 根據描述元集版面配置建立管線版面配置。
  5. 使用著色器模組和管線版面配置建立運算管線。

詳情請參閱 Vulkan 規範中的「Compute Pipelines」一節。

開始運算作業

如要開始使用運算管線進行運算,請按照下列步驟操作:

  1. 使用 Vulkan 資源更新描述元集。
  2. 建立 Vulkan 指令緩衝區,並記錄下列指令:
    1. 繫結管線和描述元集。
    2. 調派運算工作群組。
  3. 將指令緩衝區提交至運算佇列。
  4. 在佇列中等候,或可選擇傳回同步處理圍欄。

如要鏈結多個核心 (例如使用 ScriptGroup 遷移程式碼),請將其記錄在一個指令緩衝區中,並與記憶體障礙進行同步處理。

範例應用程式示範了兩項運算工作:

  • HUE 輪替:具有單一運算著色器的簡易運算工作。如需程式碼範例,請參閱 ImageProcessor::rotateHue
  • 模糊處理:較為複雜的運算工作,依序執行兩個運算著色器。如需程式碼範例,請參閱 ImageProcessor::blur

如要進一步瞭解指令緩衝區或記憶體障礙,請參閱 Vulkan 規格中的「指令緩衝區」和「記憶體障礙」章節。