Untuk menggunakan Jetpack WebGPU, project Anda harus memenuhi persyaratan minimum berikut:
- Level API Minimum: Android API 24 (Nougat) atau yang lebih tinggi diperlukan.
- Hardware: Perangkat yang mendukung Vulkan 1.1+ lebih disukai untuk backend.
- Mode Kompatibilitas dan Dukungan OpenGL ES: Penggunaan WebGPU dengan mode kompatibilitas
dapat dilakukan dengan menyetel opsi
featureLevelstandar kecompatibilitysaat memintaGPUAdapter.
// Example of requesting an adapter with "compatibility" mode enabled:
val adapter = instance.requestAdapter(
GPURequestAdapterOptions(featureLevel = FeatureLevel.Compatibility))
Penginstalan & penyiapan
Prasyarat:
Android Studio: Download Android Studio versi terbaru dari situs resmi dan ikuti petunjuk yang diberikan dalam Panduan Penginstalan Android Studio.
Membuat project baru
Setelah Android Studio diinstal, ikuti langkah-langkah berikut untuk menyiapkan project WebGPU Anda:
- Mulai Project Baru: Buka Android Studio dan klik New Project.
Pilih template: Pilih template Empty Activity di Android Studio, lalu klik Next.
Gambar 1.Membuat project baru di Android Studio Konfigurasi project Anda:
- Nama: Beri nama project Anda (misalnya, "JetpackWebGPUSample").
- Nama Paket: Verifikasi bahwa nama paket cocok dengan namespace yang Anda pilih (misalnya, com.example.webgpuapp).
- Language: Pilih Kotlin.
- SDK Minimum: Pilih API 24: Android 7.0 (Nougat) atau yang lebih tinggi, seperti yang direkomendasikan untuk library ini.
- Build Configuration Language: Sebaiknya gunakan Kotlin DSL (build.gradle.kts) untuk pengelolaan dependensi modern.
Gambar 2.Memulai dengan aktivitas kosong Selesai: Klik Finish dan tunggu hingga Android Studio menyinkronkan file project Anda.
Menambahkan library Jetpack WebGPU
- Tambahkan repositori
googlekesettings.gradleseperti yang dijelaskan dalam Menggunakan library Jetpack di aplikasi Anda - Tambahkan dependensi untuk artefak yang Anda perlukan dalam file build.gradle untuk aplikasi atau modul Anda:
- Catatan: Periksa webgpu | Jetpack | Android Developers untuk mengetahui versi library terbaru
Library
androidx.webgpu
berisi file library .so WebGPU NDK serta antarmuka
kode terkelola.
Anda dapat memperbarui versi library dengan memperbarui build.gradle dan menyinkronkan project dengan file gradle menggunakan tombol "Sync Project" di Android Studio.
Arsitektur tingkat tinggi
Rendering WebGPU dalam aplikasi Android dijalankan di thread rendering khusus untuk menjaga responsivitas UI.
- Lapisan UI: UI dibangun dengan Jetpack Compose. Permukaan gambar WebGPU diintegrasikan ke dalam hierarki Compose menggunakan
AndroidExternalSurface. - Logika Rendering: Class khusus (misalnya, WebGpuRenderer) bertanggung jawab untuk mengelola semua objek WebGPU dan mengoordinasikan loop rendering.
- Lapisan Shader: Kode shader WGSL yang disimpan dalam konstanta string atau res.
Langkah demi langkah: aplikasi contoh
Bagian ini menjelaskan langkah-langkah penting yang diperlukan untuk merender segitiga berwarna di layar, yang menunjukkan alur kerja WebGPU inti.
Aktivitas utama
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
WebGpuSurface()
}
}
}
Composable permukaan eksternal
Buat file baru bernama WebgpuSurface.kt. Composable ini membungkus
AndroidExternalSurface untuk menyediakan jembatan antara Compose dan perender Anda.
@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()
}
}
}
}
}
Menyiapkan perender
Buat class WebGpuRenderer di WebGpuRenderer.kt. Class ini akan menangani
komunikasi berat dengan GPU.
Pertama, tentukan struktur class dan variabel:
class WebGpuRenderer() {
private lateinit var webGpu: WebGpu
private lateinit var renderPipeline: GPURenderPipeline
}
Inisialisasi: Selanjutnya, terapkan fungsi init untuk membuat instance WebGPU dan mengonfigurasi permukaan. Fungsi ini dipanggil oleh cakupan
AndroidExternalSurface di dalam composable permukaan eksternal yang kita buat
sebelumnya.
Catatan: Fungsi init menggunakan
createWebGpu,
metode helper (bagian dari
androidx.webgpu.helper) untuk menyederhanakan penyiapan. Utilitas ini membuat instance WebGPU, memilih adaptor, dan meminta perangkat.
// Inside WebGpuRenderer class
suspend fun init(surface: Surface, width: Int, height: Int) {
// 1. Create Instance & Device
webGpu = createWebGpu(surface)
val device = webGpu.device
// 2. Setup Pipeline (compile shaders)
initPipeline(device)
// 3. Configure the Surface
webGpu.webgpuSurface.configure(
GPUSurfaceConfiguration(
device,
width,
height,
TextureFormat.RGBA8Unorm,
)
)
}
Library androidx.webgpu mencakup file JNI dan .so, yang
ditautkan dan dikelola secara otomatis oleh sistem build. Metode helper
createWebGpu menangani pemuatan libwebgpu_c_bundled.so yang di-bundle.
Penyiapan pipeline
Sekarang setelah memiliki perangkat, kita perlu memberi tahu GPU cara menggambar segitiga. Kita melakukannya dengan membuat "pipeline" yang berisi kode shader (ditulis dalam WGSL).
Tambahkan fungsi helper pribadi ini ke class WebGpuRenderer untuk mengompilasi shader dan membuat pipeline render.
// Inside WebGpuRenderer class
private fun initPipeline(device: GPUDevice) {
val shaderCode = """
@vertex fn vs_main(@builtin(vertex_index) vertexIndex : u32) ->
@builtin(position) vec4f {
const pos = array(vec2f(0.0, 0.5), vec2f(-0.5, -0.5), vec2f(0.5, -0.5));
return vec4f(pos[vertexIndex], 0, 1);
}
@fragment fn fs_main() -> @location(0) vec4f {
return vec4f(1, 0, 0, 1);
}
"""
// Create Shader Module
val shaderModule = device.createShaderModule(
GPUShaderModuleDescriptor(shaderSourceWGSL = GPUShaderSourceWGSL(shaderCode))
)
// Create Render Pipeline
renderPipeline = device.createRenderPipeline(
GPURenderPipelineDescriptor(
vertex = GPUVertexState(
shaderModule,
), fragment = GPUFragmentState(
shaderModule, targets = arrayOf(GPUColorTargetState(TextureFormat.RGBA8Unorm))
), primitive = GPUPrimitiveState(PrimitiveTopology.TriangleList)
)
)
}
Menggambar bingkai
Setelah pipeline siap, kita dapat menerapkan fungsi render. Fungsi ini mendapatkan tekstur berikutnya yang tersedia dari layar, merekam perintah gambar, dan mengirimkannya ke GPU.
Tambahkan metode ini ke class WebGpuRenderer Anda:
// Inside WebGpuRenderer class
fun render() {
if (!::webGpu.isInitialized) {
return
}
val gpu = webGpu
// 1. Get the next available texture from the screen
val surfaceTexture = gpu.webgpuSurface.getCurrentTexture()
// 2. Create a command encoder
val commandEncoder = gpu.device.createCommandEncoder()
// 3. Begin a render pass (clearing the screen to blue)
val renderPass = commandEncoder.beginRenderPass(
GPURenderPassDescriptor(
colorAttachments = arrayOf(
GPURenderPassColorAttachment(
GPUColor(0.0, 0.0, 0.5, 1.0),
surfaceTexture.texture.createView(),
loadOp = LoadOp.Clear,
storeOp = StoreOp.Store,
)
)
)
)
// 4. Draw
renderPass.setPipeline(renderPipeline)
renderPass.draw(3) // Draw 3 vertices
renderPass.end()
// 5. Submit and Present
gpu.device.queue.submit(arrayOf(commandEncoder.finish()))
gpu.webgpuSurface.present()
}
Pembersihan resource
Terapkan fungsi pembersihan, yang dipanggil oleh WebGpuSurface saat
permukaan dihancurkan.
// Inside WebGpuRenderer class
fun cleanup() {
if (::webGpu.isInitialized) {
webGpu.close()
}
}
Output yang dirender
Struktur aplikasi contoh
Sebaiknya pisahkan penerapan rendering dari logika UI, seperti pada struktur yang digunakan oleh aplikasi contoh:
app/src/main/
├── java/com/example/app/
│ ├── MainActivity.kt // Entry point
│ ├── WebGpuSurface.kt // Composable Surface
│ └── WebGpuRenderer.kt // Pure WebGPU logic
- MainActivity.kt: Titik entri aplikasi. Menetapkan konten ke Composable
WebGpuSurface. - WebGpuSurface.kt: Menentukan komponen UI menggunakan
[AndroidExternalSurface](/reference/kotlin/androidx/compose/foundation/package-summary#AndroidExternalSurface(androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.unit.IntSize,androidx.compose.foundation.AndroidExternalSurfaceZOrder,kotlin.Boolean,kotlin.Function1)). Class ini mengelola cakupan siklus prosesSurface, menginisialisasi perender saat permukaan siap dan membersihkan saat dihancurkan. - WebGpuRenderer.kt: Merangkum semua logika khusus WebGPU (pembuatan Perangkat, penyiapan Pipeline). Objek ini dipisahkan dari UI, hanya menerima
[Surface](/reference/android/view/Surface.html)dan dimensi yang diperlukan untuk menggambar.
Pengelolaan siklus proses & resource
Pengelolaan siklus proses ditangani oleh cakupan Coroutine Kotlin yang disediakan oleh
[AndroidExternalSurface](/reference/kotlin/androidx/compose/foundation/package-summary#AndroidExternalSurface(androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.unit.IntSize,androidx.compose.foundation.AndroidExternalSurfaceZOrder,kotlin.Boolean,kotlin.Function1)) dalam Jetpack Compose.
- Pembuatan Permukaan: Lakukan inisialisasi konfigurasi
DevicedanSurfacedi awal blok lambdaonSurface. Kode ini akan langsung berjalan saatSurfacetersedia. - Penghancuran Permukaan: Saat pengguna keluar atau
Surfacedihancurkan oleh sistem, blok lambda dibatalkan. Blokfinallydieksekusi, memanggilrenderer.cleanup()untuk mencegah kebocoran memori. - Mengubah ukuran: Jika dimensi permukaan berubah,
AndroidExternalSurfacedapat memulai ulang blok atau menangani pembaruan secara langsung, bergantung pada konfigurasi, sehingga perender selalu menulis ke buffer yang valid.
Proses debug & validasi
WebGPU memiliki mekanisme yang dirancang untuk memvalidasi struktur input dan menangkap error runtime.
- Logcat: Error validasi dicetak ke Android Logcat.
- Cakupan Error: Anda dapat merekam error tertentu dengan mengapsulasi perintah GPU dalam blok
[device.pushErrorScope()](/reference/kotlin/androidx/webgpu/GPUDevice#pushErrorScope(kotlin.Int))dan `device.popErrorScope().
device.pushErrorScope(ErrorFilter.Validation)
// ... potentially incorrect code ...
device.popErrorScope { status, type, message ->
if (status == PopErrorScopeStatus.Success && type != ErrorType.NoError) {
Log.e("WebGPU", "Validation Error: $message")
}
}
Tips performa
Saat memprogram di WebGPU, pertimbangkan hal berikut untuk menghindari hambatan performa:
- Hindari Pembuatan Objek Per Frame: Buat instance pipeline
(
GPURenderPipeline), tata letak grup pengikatan, dan modul shader sekali selama penyiapan aplikasi untuk memaksimalkan penggunaan ulang. - Mengoptimalkan Penggunaan Buffer: Perbarui konten
GPUBuffersyang ada melaluiGPUQueue.writeBuffer, bukan membuat buffer baru setiap frame. - Meminimalkan Perubahan Status: Kelompokkan panggilan gambar yang menggunakan pipeline yang sama dan ikat kelompok untuk meminimalkan overhead driver dan meningkatkan efisiensi rendering.