RenderScript API tidak digunakan lagi mulai Android 12. Produsen perangkat dan komponen telah berhenti menyediakan dukungan akselerasi hardware, dan dukungan RenderScript diperkirakan akan dihapus sepenuhnya dalam rilis mendatang.
Performa C/C++ mungkin cukup untuk banyak kasus penggunaan, dan jika Anda hanya mengandalkan RenderScript untuk intrinsik, Anda dapat mengganti penggunaan tersebut dengan Toolkit Penggantian Intrinsik RenderScript yang lebih mudah digunakan dan berpotensi meningkatkan performa 2x lipat.
Jika Anda perlu memanfaatkan akselerasi GPU secara optimal, sebaiknya migrasikan skrip Anda ke Vulkan. Opsi akselerasi lainnya mencakup memigrasikan skrip ke OpenGL, menggunakan Operasi gambar berbasis kanvas, atau memanfaatkan Android Graphics Shading Language (AGSL).
Setelah RenderScript tidak digunakan lagi di platform Android, dukungan untuk RenderScript akan dihapus dalam plugin Android Gradle. Mulai plugin Android Gradle 7.2, API RenderScript tidak digunakan lagi. API tersebut tetap berfungsi, tetapi menimbulkan peringatan. Versi AGP mendatang tidak akan lagi menyertakan dukungan Renderscript. Panduan ini menjelaskan cara melakukan migrasi dari RenderScript.
Bermigrasi dari intrinsik
Meskipun fungsi intrinsik RenderScript akan terus berfungsi setelah penghentian RenderScript, fungsi tersebut hanya dapat dijalankan pada CPU, bukan GPU.
Untuk beberapa operasi ini, ada opsi yang lebih efisien yang kini terintegrasi ke dalam platform atau di library Jetpack.
Operasi gambar bawaan yang dipercepat
Platform Android mendukung operasi pemrosesan gambar yang dipercepat dan dapat diterapkan ke gambar, terlepas dari intrinsik RenderScript. Contohnya mencakup:
- Penggabungan
- Pemburaman
- Matriks warna
- Perubahan ukuran
Pemburaman gambar di Android 12+ ke Tampilan
RenderEffect
dengan dukungan untuk pemburaman ditambahkan ke Android 12,
level API 31, yang memungkinkan Anda memburamkan RenderNode
. RenderNode
adalah konstruksi daftar tampilan yang digunakan Android untuk membantu mempercepat
grafis platform.
Android menyediakan pintasan untuk menerapkan efek ke RenderNode
yang terkait
dengan View
. Untuk memburamkan View
, panggil
View.setRenderEffect()
:
val blurRenderEffect = RenderEffect.createBlurEffect(radius, radius,
Shader.TileMode.MIRROR
)
view.setRenderEffect(blurRenderEffect)
Pemburaman gambar di Android 12+ yang dirender menjadi Bitmap
Jika Anda ingin gambar yang diburamkan dirender menjadi Bitmap
, framework
mendukung rendering yang dipercepat dengan HardwareRenderer
yang didukung oleh HardwareBuffer
. Kode berikut membuat
HardwareRenderer
, RenderNode
, dan RenderEffect
untuk pemburaman:
val imageReader = ImageReader.newInstance(
bitmap.width, bitmap.height,
PixelFormat.RGBA_8888, numberOfOutputImages,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE or HardwareBuffer.USAGE_GPU_COLOR_OUTPUT
)
val renderNode = RenderNode("BlurEffect")
val hardwareRenderer = HardwareRenderer()
hardwareRenderer.setSurface(imageReader.surface)
hardwareRenderer.setContentRoot(renderNode)
renderNode.setPosition(0, 0, imageReader.width, imageReader.height)
val blurRenderEffect = RenderEffect.createBlurEffect(
radius, radius,
Shader.TileMode.MIRROR
)
renderNode.setRenderEffect(blurRenderEffect)
Untuk menerapkan efek, Anda harus menggunakan
RecordingCanvas
internal untuk RenderNode
. Kode berikut
merekam gambar, membuat permintaan render, lalu menunggu
permintaan selesai:
val renderCanvas = it.renderNode.beginRecording()
renderCanvas.drawBitmap(it.bitmap, 0f, 0f, null)
renderNode.endRecording()
hardwareRenderer.createRenderRequest()
.setWaitForPresent(true)
.syncAndDraw()
Gambar yang dirender berada di HardwareBuffer
yang terkait dengan
ImageReader
. Kode berikut memperoleh Image
dan
menampilkan Bitmap
yang menggabungkan HardwareBuffer
-nya.
val image = imageReader.acquireNextImage() ?: throw RuntimeException("No Image")
val hardwareBuffer = image.hardwareBuffer ?: throw RuntimeException("No HardwareBuffer")
val bitmap = Bitmap.wrapHardwareBuffer(hardwareBuffer, null)
?: throw RuntimeException("Create Bitmap Failed")
Kode berikut akan melakukan pembersihan setelah merender gambar. Perhatikan bahwa
ImageReader
, RenderNode
, RenderEffect
, dan HardwareRenderer
dapat digunakan
untuk memproses beberapa gambar.
hardwareBuffer.close()
image.close()
imageReader.close()
renderNode.discardDisplayList()
hardwareRenderer.destroy()
AGSL untuk pemrosesan gambar
Android Graphics Shading Language (AGSL) digunakan oleh Android 13+ untuk
menentukan perilaku objek
RuntimeShader
yang dapat diprogram. AGSL
berbagi banyak sintaksisnya dengan shader fragmen GLSL, tetapi berfungsi dalam
sistem rendering grafis Android untuk menyesuaikan proses menggambar dalam Canvas
sekaligus memfilter konten View
. Hal ini dapat digunakan untuk menambahkan pemrosesan gambar kustom
selama operasi gambar, atau dengan menggunakan RenderNode
secara langsung untuk merender
gambar menjadi kanvas Bitmap
. Contoh berikut menunjukkan cara menerapkan
shader kustom untuk mengganti efek pemburaman gambar.
Mulai dengan membuat RuntimeShader
, membuat instance-nya dengan kode shader
AGSL. Shader ini digunakan untuk menerapkan matriks warna untuk rotasi hue:
val hueShader = RuntimeShader("""
uniform float2 iResolution; // Viewport resolution (pixels)
uniform float2 iImageResolution; // iImage1 resolution (pixels)
uniform float iRadian; // radian to rotate things around
uniform shader iImage1; // An input image
half4 main(float2 fragCoord) {
float cosR = cos(iRadian);
float sinR = sin(iRadian);
mat4 hueRotation =
mat4 (
0.299 + 0.701 * cosR + 0.168 * sinR, //0
0.587 - 0.587 * cosR + 0.330 * sinR, //1
0.114 - 0.114 * cosR - 0.497 * sinR, //2
0.0, //3
0.299 - 0.299 * cosR - 0.328 * sinR, //4
0.587 + 0.413 * cosR + 0.035 * sinR, //5
0.114 - 0.114 * cosR + 0.292 * sinR, //6
0.0, //7
0.299 - 0.300 * cosR + 1.25 * sinR, //8
0.587 - 0.588 * cosR - 1.05 * sinR, //9
0.114 + 0.886 * cosR - 0.203 * sinR, //10
0.0, //11
0.0, 0.0, 0.0, 1.0 ); //12,13,14,15
float2 scale = iImageResolution.xy / iResolution.xy;
return iImage1.eval(fragCoord * scale)*hueRotation;
}
""")
Shader dapat diterapkan ke RenderNode
, seperti RenderEffect
lainnya.
Contoh berikut menunjukkan cara menyetel seragam di hueShader:
hueShader.setFloatUniform("iImageResolution", bitmap.width.toFloat(),
bitmap.height.toFloat())
hueShader.setFloatUniform("iResolution", bitmap.width.toFloat(),
bitmap.height.toFloat())
hueShader.setFloatUniform("iRadian", radian)
hueShader.setInputShader( "iImage1", BitmapShader(bitmap, Shader.TileMode.MIRROR,
Shader.TileMode.MIRROR))
val colorFilterEffect = RenderEffect.createShaderEffect(it.hueShader)
renderNode.setRenderEffect(colorFilterEffect)
Untuk mendapatkan Bitmap
, teknik yang sama digunakan seperti pada contoh pemburaman
gambar sebelumnya.
RecordingCanvas
internal untukRenderNode
menerapkan shader.Image
diperoleh, menampilkanBitmap
yang menggabungkanHardwareBuffer
.
Mengonversi dari YUV planar ke RGB menggunakan CameraX
Konversi dari YUV planar ke RGB untuk digunakan dalam pemrosesan gambar didukung sebagai bagian dari kasus penggunaan ImageAnalysis dalam CameraX Jetpack.
Ada resource tentang penggunaan ImageAnalysis
sebagai bagian dari
codelab Mulai Menggunakan CameraX dan di
repositori
contoh kamera Android.
Toolkit pengganti intrinsik Renderscript
Jika aplikasi Anda menggunakan intrinsik, Anda dapat menggunakan library pengganti mandiri; pengujian kami menunjukkan bahwa penggunaan library ini lebih cepat daripada implementasi CPU RenderScript yang sudah ada.
Toolkit ini mencakup fungsi berikut:
- Penggabungan
- Pemburaman
- Matriks warna
- Konvolusi
- Histogram dan histogramDot
- Tabel pemeta (LUT) dan LUT 3D
- Perubahan ukuran
- YUV ke RGB
Untuk detail dan batasan selengkapnya, lihat file README.md
dan Toolkit.kt
.
Lakukan langkah-langkah berikut untuk mendownload, menambahkan, dan menggunakan library:
Download project dari GitHub.
Temukan dan buat
renderscript-toolkit module
.Tambahkan library ke project Android Studio dengan memodifikasi file
build.gradle
aplikasi.Panggil metode yang sesuai dari toolkit.
Contoh: bermigrasi dari fungsi ScriptIntrinsicBlur
Untuk mengganti fungsi ScriptIntrinsicBlur
:
Untuk memburamkan bitmap, panggil
Toolkit.blur
.var blurredBitmap = Toolkit.blur(myBitmap, radius)
Jika Anda ingin memburamkan gambar yang diwakili oleh sederet byte, tentukan lebar, tinggi, dan jumlah byte per piksel.
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
Bermigrasi dari skrip
Jika kasus penggunaan Anda tidak dapat diselesaikan dengan:
- Toolkit Penggantian Intrinsik RenderScript
- API baru dalam platform Android seperti
RenderEffect
danAGSL
- API library Android Jetpack seperti
CameraX
Selain itu, kasus penggunaan Anda dapat memanfaatkan akselerasi GPU. Android mendukung komputasi GPU pada API Vulkan dan OpenGL ES (GLES) lintas platform. Tindakan ini mungkin tidak diperlukan karena di sebagian besar perangkat, skrip Anda sudah berjalan di CPU, bukan GPU: C/C++ mungkin lebih cepat daripada komputasi RenderScript, GLES, atau Vulkan untuk beberapa kasus penggunaan. (atau setidaknya cukup cepat untuk kasus penggunaan Anda)
Untuk lebih memahami cara bermigrasi, tinjau aplikasi contoh. Contoh ini menunjukkan cara memburamkan bitmap dan mengonversi matriks warna di RenderScript, serta memiliki kode yang setara di Vulkan dan OpenGL.
Jika aplikasi Anda perlu mendukung berbagai rilis, gunakan RenderScript untuk
perangkat yang menjalankan Android 6 (level API 23) dan yang lebih rendah, serta Vulkan atau GLES pada
perangkat yang didukung dengan Android 7 (level API 24) dan yang lebih tinggi. Jika
minSdkVersion
adalah 24 atau lebih tinggi, Anda mungkin tidak perlu menggunakan RenderScript. Vulkan atau
GLES 3.1 dapat digunakan di mana pun Anda memerlukan dukungan komputasi GPU.
Android menyediakan binding SDK untuk API GLES, sehingga tidak perlu menggunakan NDK saat menggunakan OpenGL ES.
Vulkan tidak menyediakan binding SDK, sehingga tidak ada pemetaan langsung dari RenderScript ke Vulkan. Anda harus menulis kode Vulkan menggunakan NDK dan membuat fungsi JNI untuk mengakses kode ini dari Kotlin atau Java.
Halaman berikut ini membahas aspek proses migrasi dari RenderScript. Aplikasi contoh mengimplementasikan hampir semua pertimbangan ini. Untuk lebih memahaminya, bandingkan kode RenderScript dan Vulkan yang setara.