Getting started with WebGPU

To use Jetpack WebGPU, your project must meet the following minimum requirements:

  • Minimum API Level: Android API 24 (Nougat) or higher is required.
  • Hardware: Devices supporting Vulkan 1.1+ are preferred for the backend.
  • Compatibility Mode and OpenGL ES Support: Using WebGPU with compatibility mode is possible by setting the standardized featureLevel option to compatibility while requesting the GPUAdapter.
// Example of requesting an adapter with "compatibility" mode enabled:
val adapter = instance.requestAdapter(
  GPURequestAdapterOptions(featureLevel = FeatureLevel.Compatibility))

Installation & setup

Prerequisites:

Android Studio: Download the latest version of Android Studio from the official website and follow the instructions given in the Android Studio Installation Guide.

Create a new project

Once Android Studio is installed, follow these steps to set up your WebGPU project:

  1. Start a New Project: Open Android Studio and click on New Project.
  2. Select a template: Choose the Empty Activity template in Android Studio and click Next.

    The Android Studio New Project dialog, showing the built-in list of
    activities that Studio will create on your behalf.
    Figure 1.Creating a new project in Android Studio
  3. Configure your project:

    • Name: Give your project a name (e.g., "JetpackWebGPUSample").
    • Package Name: Verify that the package name matches your chosen namespace (e.g., com.example.webgpuapp).
    • Language: Select Kotlin.
    • Minimum SDK: Select API 24: Android 7.0 (Nougat) or higher, as recommended for this library.
    • Build Configuration Language: It is recommended to use Kotlin DSL (build.gradle.kts) for modern dependency management.
    The Android Studio Empty Activity dialog that contains fields to
    populate the new empty activity, such as Name, Package Name, Save
    Location, and Minimum SDK.
    Figure 2.Starting with an empty activity
  4. Finish: Click Finish and wait for Android Studio to sync your project files.

Add WebGPU Jetpack library

The androidx.webgpu library contains the WebGPU NDK .so library files as well as the managed code interfaces.

You can update the library version by updating your build.gradle and synchronizing your project with gradle files using the "Sync Project" button in Android Studio.

High-level architecture

WebGPU rendering within an Android application is run on a dedicated rendering thread to maintain the responsiveness of the UI.

  • UI Layer: The UI is built with Jetpack Compose. A WebGPU drawing surface is integrated into the Compose hierarchy using AndroidExternalSurface.
  • Rendering Logic: A specialized class (e.g., WebGpuRenderer) is responsible for managing all WebGPU objects and coordinating the rendering loop.
  • The Shader Layer: WGSL shader code stored in res or string constants.
High-level architecture diagram showing the interaction between the
    UI Thread, a dedicated Rendering Thread, and GPU hardware in a WebGPU
    Android application.
Figure 3.WebGPU on Android high-level architecture

Step-by-step: sample app

This section walks through the essential steps required to render a colored triangle on the screen, demonstrating the core WebGPU workflow.

The main Activity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            WebGpuSurface()
        }
    }
}

The external surface Composable

Create a new file named WebgpuSurface.kt. This Composable wraps the AndroidExternalSurface to provide a bridge between Compose and your renderer.

@Composable
fun WebGpuSurface(modifier: Modifier = Modifier) {
    // Create and remember a WebGpuRenderer instance.
    val renderer = remember { WebGpuRenderer() }
    AndroidExternalSurface(
        modifier = modifier.fillMaxSize(),
    ) {
        // This block is called when the surface is created or resized.
        onSurface { surface, width, height ->
            // Run the rendering logic on a background thread.
            withContext(Dispatchers.Default) {
                try {
                    // Initialize the renderer with the surface
                    renderer.init(surface, width, height)
                    // Render a frame.
                    renderer.render() 
                } finally {
                    // Clean up resources when the surface is destroyed.
                    renderer.cleanup()
                }
            }
        }
    }
}

Set up the renderer

Create a WebGpuRenderer class in WebGpuRenderer.kt. This class will handle the heavy lifting of communicating with the GPU.

First, define the class structure and the variables:

class WebGpuRenderer() {
    private lateinit var webGpu: WebGpu
    private lateinit var renderPipeline: GPURenderPipeline
}

Initialization: Next, implement the init function to create the WebGPU instance and configure the surface. This function is called by the AndroidExternalSurface scope inside the external surface composable we created earlier.

Note: The init function uses