什么是RenderScript
RenderScript 是用于在 Android 上以高性能運(yùn)行計(jì)算密集型任務(wù)的框架。RenderScript 主要用于數(shù)據(jù)并行計(jì)算,不過串行工作負(fù)載也可以從中受益。RenderScript 運(yùn)行時(shí)可在設(shè)備上提供的多個(gè)處理器(如多核 CPU 和 GPU)間并行調(diào)度工作。這樣您就能夠?qū)W⒂诒磉_(dá)算法而不是調(diào)度工作。RenderScript 對于專注于圖像處理、計(jì)算攝影或計(jì)算機(jī)視覺的應(yīng)用來說尤其有用。
使用RenderScript的效果圖
| 效果名 | 原圖 | 效果圖 |
|---|---|---|
| 灰度 | ![]() image.png
|
![]() image.png
|
| 高斯模糊 | ![]() image.png
|
![]() image.png
|
| 卷積 | ![]() image.png
|
![]() image.png
|
| 顏色matrix | ![]() image.png
|
![]() image.png
|
RenderScript內(nèi)核
自定義 RenderScript 內(nèi)核
- 在<project_root>/src/建立.rs目錄,并創(chuàng)建demo.rs文件
- 聲明
一個(gè)版本聲明:#pragma version(1),用于聲明此腳本中使用的 RenderScript 內(nèi)核語言的版本。目前,1 是唯一有效的值。
一個(gè)包名聲明:#pragma rs java_package_name(com.example.app),用于聲明從此腳本中反映的 Java 類的軟件包名稱。請注意,您的 .rs 文件必須是應(yīng)用軟件包的一部分,且不在庫項(xiàng)目中。
0個(gè)或者多個(gè)可調(diào)用函數(shù)。可調(diào)用函數(shù)是單線程 RenderScript 函數(shù),您可以使用任意參數(shù)從 Java 代碼調(diào)用該函數(shù)??烧{(diào)用函數(shù)通常用于較大處理流水線中的初始設(shè)置或串行計(jì)算。
0個(gè)或者多個(gè)腳本全局變量。腳本全局變量類似于 C 中的全局變量。您可以通過 Java 代碼訪問腳本全局變量,并且這些變量通常用于向 RenderScript 內(nèi)核傳遞參數(shù)。
0個(gè)或者多個(gè)計(jì)算內(nèi)核。計(jì)算內(nèi)核是函數(shù)或函數(shù)集合,可指導(dǎo) RenderScript 運(yùn)行時(shí)跨一組數(shù)據(jù)并行執(zhí)行。計(jì)算內(nèi)核分為兩種類型:映射內(nèi)核(也稱為 foreach 內(nèi)核)和歸約內(nèi)核。
映射內(nèi)核是并行函數(shù),可對相同維度的一組 Allocations 執(zhí)行操作。默認(rèn)情況下,它會(huì)對這些維度中的每個(gè)坐標(biāo)執(zhí)行一次。
歸約內(nèi)核是一系列函數(shù),可對維度相同的一組輸入Allocations執(zhí)行操作。默認(rèn)情況下,其accumulator 函數(shù)會(huì)對這些維度中的每個(gè)坐標(biāo)執(zhí)行一次。歸約內(nèi)核通常(但并非專門)用于將一組輸入 Allocations“歸約”為一個(gè)值。
系統(tǒng)內(nèi)置內(nèi)核
| 類名 | 用途 |
|---|---|
| ScriptIntrinsicBlur | 高斯模糊 |
| ScriptIntrinsicResize | 改變二維的大小,例如改變圖片的大小 |
| ScriptIntrinsicYuvToRGB | YUV轉(zhuǎn)RGB |
| ScriptIntrinsicColorMatrix | 顏色變換 |
| ScriptIntrinsicConvolve3x3 | 3*3卷積 |
| ScriptIntrinsicConvolve5x5 | 5*5卷積 |
| ScriptIntrinsicHistogram | 直方圖 |
| ScriptIntrinsicBlend | 混合 |
| ScriptIntrinsicLUT | ? |
| ScriptIntrinsic3DLUT | ? |
| ScriptIntrinsicBLAS | ? |
通過 Java 訪問 RenderScript API
在開發(fā)使用 RenderScript 的 Android 應(yīng)用時(shí),您可以通過以下兩種方式之一從 Java 訪問其 API:
-
android.renderscript- 此類軟件包中的 API 在搭載 Android 3.0(API 級(jí)別 11)及更高版本的設(shè)備上可用。 -
android.support.v8.renderscript- 此軟件包中的 API 通過支持庫提供,可供您在搭載 Android 2.3(API 級(jí)別 9)及更高版本的設(shè)備上使用。
其利弊如下所示:
- 如果您使用支持庫 API,無論您使用哪些 RenderScript 功能,應(yīng)用的 RenderScript 部分都會(huì)與搭載 Android 2.3(API 級(jí)別 9)及更高版本的設(shè)備兼容。與使用原生 (
android.renderscript) API 相比,它可讓您的應(yīng)用在更多設(shè)備上運(yùn)行。 - 某些 RenderScript 功能無法通過支持庫 API 使用。
- 如果您使用支持庫 API,您開發(fā)的 APK 會(huì)比使用原生 (
android.renderscript) API 開發(fā)的 APK 更大(可能會(huì)大幅增大)。
使用 RenderScript 支持庫 API
- 確保您已安裝所需的 Android SDK 版本(Android SDK Tools 修訂版 22.2 或更高版本,Android SDK Build-tools 修訂版 18.1.0 或更高版本)
- 更新 Android 構(gòu)建流程的設(shè)置,以包含 RenderScript 設(shè)置:
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
renderscriptTargetApi 18 // 指定要生成的字節(jié)碼版本。不會(huì)影響build.gradle的設(shè)置的minSdkVersion版本。
renderscriptSupportModeEnabled true // 指定當(dāng)運(yùn)行生成的字節(jié)碼所在的設(shè)備不支持目標(biāo)版本,生成的字節(jié)碼應(yīng)回退到兼容版本。
}
}
- 在使用 RenderScript 的應(yīng)用類中,添加對支持庫類的導(dǎo)入操作:
import android.support.v8.renderscript.*
RenderScript運(yùn)行時(shí)層
RenderScript 代碼在緊湊且明確定義的運(yùn)
行時(shí)層進(jìn)行編譯和執(zhí)行。RenderScript 運(yùn)行時(shí) API 支持密集型計(jì)算,它們具有可移植性,并且能夠根據(jù)處理器上可用的核心數(shù)量自動(dòng)擴(kuò)縮。
注意:NDK 中的標(biāo)準(zhǔn) C 函數(shù)必須保證能在 CPU 上運(yùn)行,從而使 RenderScript 無法訪問這些庫,因?yàn)?RenderScript 經(jīng)過設(shè)計(jì),能夠在不同類型的處理器上運(yùn)行。
您可以在 Android 項(xiàng)目的 src/ 目錄中的 .rs 和 .rsh 文件內(nèi)定義您的 RenderScript 代碼。該代碼由作為 Android 構(gòu)建的一部分運(yùn)行的 llvm 編譯器編譯為中間字節(jié)碼。當(dāng)您的應(yīng)用在設(shè)備上運(yùn)行時(shí),該字節(jié)碼隨后會(huì)由設(shè)備上的另一個(gè) llvm 編譯器即時(shí)編譯為機(jī)器代碼。該機(jī)器代碼針對設(shè)備進(jìn)行了優(yōu)化,也進(jìn)行了緩存,因此后續(xù)使用已啟用 RenderScript 的應(yīng)用時(shí)不會(huì)重新編譯該字節(jié)碼。

rs字節(jié)碼存放位置:和java反應(yīng)層在同一包名下,名字為rs文件名+BitCode。例如demo.rs文件的java反應(yīng)層為ScripC_demo,字節(jié)碼為demoBitCode。

反應(yīng)層
反映層是 Android 構(gòu)建工具生成的一組類,可允許從 Android 框架訪問 RenderScript 運(yùn)行時(shí)。此層還提供了多種方法和構(gòu)造函數(shù),允許您為 RenderScript 代碼中定義的指針分配和使用內(nèi)存。以下列表介紹了反映的主要組件:
- 您創(chuàng)建的每個(gè)
.rs文件都會(huì)生成到名為project_root/gen/package/name/ScriptC_*renderscript_filename*且類型為ScriptC 的類中。此文件是您的.rs文件的.java版本,您可以從 Android 框架中調(diào)用它。 -
struct將反映到其自己名為project_root/gen/package/name/ScriptField_struct_name的類中,該類擴(kuò)展了Script.FieldBase。此類表示struct的數(shù)組,允許您為此struct的一個(gè)或多個(gè)實(shí)例分配內(nèi)存。




