從 RenderScript 遷移

Stay organized with collections Save and categorize content based on your preferences.

自 Android 12 起,RenderScript API 已淘汰。這類 API 仍可繼續運作,但我們預期裝置和元件製造商會隨著時間停止提供硬體加速支援。如要充分利用 GPU 加速功能,建議您將指令碼遷移至 Vulkan,或使用我們的替換工具包從內建函式遷移

在 Android 平台上淘汰 RenderScript 後,我們也會移除 Android Gradle 外掛程式中的 RenderScript 支援功能。自 Android Gradle 外掛程式 7.2 版開始,RenderScript API 已淘汰。這類 API 仍可繼續運作,但會叫用警告,並將在未來的 AGP 版本中徹底移除。本指南將說明如何從 RenderScript 遷移。

從內建函式遷移

雖然 RenderScript 內建函式在 RenderScript 淘汰後仍會繼續運作,但可能只能在 CPU (而非 GPU) 上執行。

如果您的應用程式使用了內建函式,您可以使用獨立的替代程式庫;我們的測試結果顯示,與現有的 RenderScript CPU 實作相比,獨立替代程式庫的速度更快。

工具包中包含下列函式:

  • 混合
  • 模糊處理
  • 色彩矩陣
  • 卷積
  • 直方圖和 histogramDot
  • 對照表 (LUT) 函數和 LUT 3D
  • 調整大小
  • 從 YUV 轉換為 RGB

如需完整的詳細資料和限制條件,請參閱工具包的 README.mdToolkit.kt. 檔案。

請按照下列步驟下載、新增及使用資料庫:

  1. 從 GitHub 下載專案

  2. 找出並建構 renderscript-toolkit module

  3. 修改應用程式的 build.gradle 檔案,將程式庫新增至您的 Android Studio 專案。

  4. 叫用適當的工具包方法。

範例:從 ScriptIntrinsicBlur 函式遷移

如要取代 ScriptIntrinsicBlur 函式:

  • 如要模糊處理點陣圖,請呼叫 Toolkit.blur

    var blurredBitmap = Toolkit.blur(myBitmap, radius)
    
  • 如要模糊處理由位元組陣列表示的圖片,請指定每個像素的寬度、高度和位元組數。

    val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
    

如果您指定的是 Android 12 (API 級別 31) 以上版本,請考慮使用 RenderEffect 類別,而不是 Toolkit.blur()

從指令碼遷移

如要充分利用 GPU 加速功能,建議您將 RenderScript 指令碼遷移至跨平台 Vulkan API。即使您未遷移指令碼,指令碼仍會繼續執行,但可能會在 CPU (而非 GPU) 上執行,實際情況取決於驅動程式是否可用。

如要進一步瞭解如何遷移功能,請參閱範例應用程式。此範例示範了如何在 RenderScript 中對點陣圖進行模糊處理並執行色彩矩陣轉換,以及如何在 Vulkan 中編寫等效的程式碼。

如果您的應用程式需要支援多種版本,請針對搭載 Android 9 (API 級別 28) 以下版本的裝置使用 RenderScript,而對 Android 10 (API 級別 29) 以上的版本則使用 Vulkan。

Vulkan 不提供 Kotlin 或 Java API,因此無法將 RenderScript 直接對應至 Vulkan。您需要使用 NDK 編寫 Vulkan 程式碼,並建立 JNI 函式,才能從 Kotlin 或 Java 存取這個程式碼。

以下各節介紹了從 RenderScript 遷移的各個面向。範例應用程式幾乎涵蓋了上述所有考量因素。如要進一步瞭解這些因素,請比較 RenderScript 和 Vulkan 的對等程式碼。

初始化

請遵循下列步驟使用 NDK 建立 Vulkan 情境,而不要在 Kotlin 或 Java 中建立 RenderScript 情境物件。

  1. 建立 Vulkan 例項。

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

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

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

範例應用程式示範了如何在 VulkanContext.h 中初始化 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 規格中的資源建立資源描述元章節。

指令碼

您的 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 規格中的運算管線一節。

開始運算作業

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

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

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

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

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

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