RenderScript APIs are deprecated starting in Android 12. They will continue to function, but we expect that device and component manufacturers will stop providing hardware acceleration support over time. To take full advantage of GPU acceleration, we recommend migrating your scripts to Vulkan or using our replacement toolkit to migrate away from intrinsics.
Following the deprecation of RenderScript in the Android platform, we are also removing support for RenderScript in the Android Gradle plugin. Starting with Android Gradle plugin 7.2, the RenderScript APIs are deprecated. They will continue to function, but will invoke warnings, and will be completely removed in future versions of AGP. This guide explains how to migrate from RenderScript.
Migrate from intrinsics
Although the RenderScript intrinsics functions will continue to function after RenderScript deprecation, they may execute only on the CPU rather than the GPU.
If your application uses intrinsics, you can use the standalone replacement library; our tests indicate it's faster than using the existing RenderScript CPU implementation.
The toolkit includes the following functions:
- Color matrix
- Histogram and histogramDot
- Lookup table (LUT) and LUT 3D
- YUV to RGB
Perform the following steps to download, add, and use the library:
Download the project from GitHub.
Locate and build the
Add the library to your Android Studio project by modifying the app's
Invoke the appropriate method of the toolkit.
Example: migrate from the ScriptIntrinsicBlur function
To replace the
To blur a bitmap, call
var blurredBitmap = Toolkit.blur(myBitmap, radius)
If you want to blur an image represented by an array of bytes, specify the width, height, and the number of bytes per pixel.
val outArray = Toolkit.blur(inputArray, bytesPerPixel, width, height, radius)
When targeting Android 12 (API level 31) and higher, consider
Migrate from scripts
To take full advantage of GPU acceleration, we recommend migrating RenderScript scripts to the cross-platform Vulkan API. Although your scripts will continue to run even if you don't migrate, they may execute on the CPU instead of the GPU depending on the availability of drivers.
To better understand how to migrate functionality, review the sample app. The sample demonstrates how to both blur a bitmap and do a color-matrix conversion in RenderScript, and has equivalent code in Vulkan.
If your application needs to support a range of releases, use RenderScript for devices running Android 9 (API level 28) and lower, and Vulkan for Android 10 (API level 29) and higher.
Vulkan doesn’t provide Kotlin or Java APIs, so there is no direct mapping from RenderScript to Vulkan. You'll need to write your Vulkan code using the NDK and create JNI functions to access this code from Kotlin or Java.
The following sections cover aspects of migrating from RenderScript. The sample app implements almost all of these considerations. To better understand them, compare the RenderScript and Vulkan equivalent code.
Instead of creating a RenderScript context object in Kotlin or Java, perform the following steps to create a Vulkan context with the NDK.
Create a Vulkan instance.
Choose a Vulkan physical device that supports a compute queue.
Create a Vulkan logical device, and get the compute queue.
Optionally, you can set up the Vulkan validation layers on Android to speed up your Vulkan application development.
You can migrate a RenderScript Allocation to a Vulkan storage image or a Vulkan storage buffer. For better performance with read-only images, use a sampled image with fetch operations, either as a combined image sampler, or with distinct sampler and sampled image bindings.
The Vulkan resources are allocated within Vulkan. To avoid memory copying
overhead when interacting with other Android components, consider using the
to import an Android
into Vulkan. This extension is available on all Android devices supporting Vulkan
1.1. For more information, see
Your RenderScript scripts must be converted to Vulkan compute shaders. You may also need to adapt your code depending on the use of RenderScript globals.
Write a Vulkan compute shader
For detailed information and instructions for integrating shaders into your app, see Vulkan shader compilers on Android.
Adaptation of script globals
Based on the characteristics of the script globals, we recommend using specialization constants, push constants, or uniform buffer objects for globals that are not modified within the shader:
- Specialization constants: Recommended for script globals that are mostly consistent across kernel invocations. Changing the value of specialization constants will need to recreate the compute pipeline.
- Push constants:
Recommended for frequently-changed script globals of sizes smaller than
maxPushConstantsSize(guaranteed minimum: 128 bytes).
- Uniform buffer: Recommended for frequently-changed script globals of sizes larger than the push constant limit.
You'll need to create a Vulkan compute pipeline in order to have the GPU execute your compute shader.
Create a Vulkan compute pipeline
file in the sample app demonstrates how to create the Vulkan compute pipeline.
To use a compiled SPIR-V shader in Vulkan, construct a Vulkan compute pipeline as follows:
- Create a shader module with the compiled SPIR-V shader.
- Create a descriptor set layout specifying the resource bindings (see Allocations for more details).
- Create a descriptor set from the descriptor set layout.
- Create a pipeline layout from the descriptor set layout.
- Create a compute pipeline with the shader module and pipeline layout.
For more information, see the Compute Pipelines section in the Vulkan specification.
Start a computation
To start the computation with a compute pipeline:
- Update the descriptor set with the Vulkan resources.
- Create a Vulkan command buffer, and record the following commands:
- Bind the pipeline and the descriptor set.
- Dispatch compute workgroups.
- Submit the command buffer to the compute queue.
- Wait on the queue, or optionally return a sync fence.
To chain multiple kernels together (for example, to migrate codes using
ScriptGroup), record them in a single command buffer and synchronize with
The sample app demonstrates two compute tasks:
- HUE rotation: A simple compute task with a single compute shader. See
ImageProcessor::rotateHuefor the code sample.
- Blur: A more complex compute task that sequentially executes two compute
ImageProcessor::blurfor the code sample.