Skip to content

feat(vulkan): add Android arm64 Vulkan support#268

Open
besmpl wants to merge 13 commits into
gogpu:mainfrom
besmpl:besmpl/android-vulkan-preview
Open

feat(vulkan): add Android arm64 Vulkan support#268
besmpl wants to merge 13 commits into
gogpu:mainfrom
besmpl:besmpl/android-vulkan-preview

Conversation

@besmpl

@besmpl besmpl commented Jul 15, 2026

Copy link
Copy Markdown

Status

This is ready for maintainer review as a complete Android/arm64 Vulkan implementation candidate. It is intentionally stacked and cannot merge as-is: the canonical goffi dependency must ship, the WGPU prerequisites must merge, and this branch must then be rebased to its three Android-owned commits.

We need this Android path for Hearth, a Go game engine whose Android target depends on canonical WGPU/goffi support. This is not a drive-by patch: we are prepared to do whatever follow-up makes the implementation maintainable here—revise the shape, split or rebase work, add requested tests and device evidence, respond to review, and keep the Android matrix healthy after landing.

No replace, committed go.work, personal module path, or forked dependency is present. PR CI checks out one exact canonical goffi PR head and creates an ephemeral workspace.

Android-owned implementation

  • Android/arm64 registers Vulkan only and loads Bionic's libvulkan.so.
  • Instance.CreateSurface ignores the display handle and accepts only a non-null raw ANativeWindow*, matching Rust wgpu v29.
  • Surfaces are independent: creating a second surface does not invalidate the first. There is no display-generation protocol or global window registry.
  • The host owns the Activity/native-window lifecycle and its application reference. Vulkan owns the surface reference until vkDestroySurfaceKHR; WGPU does not call ANativeWindow_acquire or ANativeWindow_release.
  • API 29 uses an infinite acquire timeout; API 30+ preserves the requested timeout. Android uses identity pre-transform and suppresses orientation-only SUBOPTIMAL.
  • Fixed currentExtent is compositor-owned; variable extents are clamped. RGBA16Float is advertised and selected only with extended-linear sRGB.
  • Required WSI commands are checked, errors preserve recoverable HAL types, and native-window ownership conflicts remain ordinary errors.
  • This adds no Android-driven global Vulkan version gate or adapter filter.

The Android-owned range is three commits:

Commit Purpose
8160adc221122bca4de837d0c66223e78e281a83 Android WSI, Rust-v29 policy, and focused tests
61cb8e12283509dcafd0c8cbce02d5526ad93ade exact goffi/NDK cross-build, ABI, and ELF proof
7245d59850733b30ea218bb293e5cbde95660c6c support contract and acceptance boundary

The range after the lifecycle prerequisite does not touch core/instance.go, encoder_native.go, or texture_native.go. The only desktop-named platform file is hal/vulkan/api_linux.go, whose one-line build constraint prevents Android from selecting Linux WSI sources.

Rust wgpu v29 semantic oracle

The oracle is gfx-rs/wgpu v29.0.3 commit 4cbe6232b2d7c289b6e1a38416a6ae1461a22e81.

Behavior Rust v29 shape Go proof
Android surface input ignore display; raw a_native_window only raw-pointer and independent-surface tests
API 29 / API 30+ acquire infinite / requested timeout platform-policy tests
fence wait waitAll=true shared checked acquire path
transform / suboptimal identity / suppress orientation-only signal platform-policy tests
extent fixed authoritative; variable clamped exact extent tests
float surface pair R16G16B16A16_SFLOAT + extended-linear sRGB only pair-aware capability and selection tests
teardown device drains configured swapchains first lifecycle prerequisite and public tests

Ownership

public Instance
├── Device  ── owns configured swapchains and device children
├── Surface ── owns the platform VkSurfaceKHR wrapper
└── core Instance ── owns the native VkInstance

release order: Device → Surface → core/native Instance

core.Surface owns acquisition validity, so stale textures and retained views fail before HAL access. Vulkan Device owns configured swapchain teardown; Vulkan Surface owns only VkSurfaceKHR; no Vulkan instance child registry is needed.

Exact prerequisite stack

Change PR Exact canonical head Replayed stack head
drain GPU work before teardown #264 0ed17064f8c977f35d9b49b5cde0d0c69e867ecf cc20fac
fail-closed swapchain lifecycle #265 a8ff52e340f0a06c8e1b6599a03856d7fc74d1a2 c2653bd
explicit mock construction #266 e97e4901ee76d9e5f587569c073b38114221c4e6 78daa26
surface-qualified present queue #267 a3e839f94a12edce98e2496d96e5bd8d3cdd2fc3 4aff6e1
surface lifetime ownership #269 85eeeb02a278bf4caebf66310b6baad8c328dd87 d51d3961a219487633c2c9f06bd5743e8f70aefd
Android/Bionic runtime goffi#62 8ccaae72d877a7af0af4b628bf86e92536e27d88 ephemeral workspace only

The previously published WGPU preview is preserved at besmpl/archive/android-vulkan-preview-b11d267, exact head b11d2671e80081a191705c41c4e77e8b61472017.

Verification

On the integrated, committed head:

  • GOWORK=off go test ./...
  • GOWORK=off go test -race . ./core ./hal/vulkan
  • GOWORK=off go vet . ./core ./hal/vulkan
  • GOWORK=off go test -tags rust ./...
  • GOWORK=off go mod verify
  • Windows/amd64 and Linux/amd64 cgo-disabled all-package cross-tests
  • golangci-lint v2.12.2 relative to upstream main: 0 issues
  • formatting, shell syntax, diff, path, workspace, and module-hygiene audits
  • Go 1.25.12 and 1.26.5 with NDK r29: every Android/arm64 package and test in both cgo modes, headless binary build, generated-Go/NDK-C ABI checks, and ELF dependency audits requiring Bionic libc.so/libdl.so plus libvulkan.so while rejecting glibc, standalone pthread, desktop WSI, GLES, and software fallback

A separate maintainer-oriented review found no remaining Android-owned correctness, Rust-v29 parity, public-contract, scope, or CI blockers.

Merge prerequisites and follow-through

This PR is ready for review, but the current stacked branch is deliberately not ready to merge. The remaining path is explicit:

  1. review and merge WGPU prerequisites #264, #265, #266, #267, and #269;
  2. review, merge, and release canonical goffi#62;
  3. rebase this PR to the three Android-only commits and consume the canonical goffi release;
  4. rerun the clean hosted matrix after the upstream fork workflow is approved;
  5. complete API 29 and API 30+ arm64 physical-device evidence in both cgo modes: startup, known-color presentation, rotation, Activity recreation, and repeated native-window replacement.

Cross-build and binary-shape evidence does not substitute for that physical-device evidence, and this PR does not claim released Android support before those gates close. We will own the follow-through rather than leave that integration work to maintainers.

Hosted CI note: run 29444335410 is action_required with zero jobs until an upstream maintainer approves the fork workflow.

@besmpl besmpl force-pushed the besmpl/android-vulkan-preview branch from b11d267 to 7245d59 Compare July 15, 2026 19:23
@besmpl besmpl changed the title feat(vulkan): add Android arm64 implementation preview feat(vulkan): add Android arm64 Vulkan support Jul 15, 2026
@besmpl besmpl marked this pull request as ready for review July 15, 2026 19:33
@besmpl besmpl requested a review from kolkov as a code owner July 15, 2026 19:33
@kolkov

kolkov commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Thank you for this — the scope and quality of work here is impressive. Rust v29 semantic oracle, ELF dependency audits, dual cgo mode testing, and a clear prerequisite stack show serious engineering.

Before we dive into the review: have you seen our Android research discussion? https://github.com/orgs/gogpu/discussions/31 — it covers the "Minimal CGO Bootstrap" approach and community feedback. Would be good to know if your design aligns with or diverges from what we outlined there.

We will review the full stack (#264#269, goffi#62, and this PR), but this is 10K+ LOC across multiple repositories touching core lifecycle, surface ownership, and a new platform. We take responsibility for every line that lands in the codebase, so this will take some time to do properly. We'll work through the prerequisites first and come back to the Android implementation after that.

Thanks again for the thorough work and for being upfront about the merge path and remaining physical-device gates.


Pinging people who may be interested in Android support or whose review would be valuable:

Team: @lkmavi — 5 prerequisite lifecycle fixes affect all backends including Metal. Your review on surface ownership (#269) especially welcome.

wgpu contributors: @samyfodil @amery — lifecycle/surface changes in prerequisites touch areas you've contributed to.

goffi contributors: @jiyeyuran @tie @pekim — goffi#62 adds Bionic/Android arm64 platform loader. Your perspective on the FFI layer changes welcome.

Android interested (from discussion #31 and #18): @JanGordon @beikege @celer @SideFx — this is an Android implementation candidate. Your input and testing interest welcome.

@kolkov

kolkov commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

One more thought — since you're driving the Android implementation and have hands-on experience with the Go mobile toolchain + NDK, would you be interested in starting a discussion on r/golang about adding mobile platform support to a Pure Go GPU stack? The community there is large and this could attract developers and testers who have Android/iOS devices and experience with Go on mobile. Getting early feedback and testing help from the broader Go community would help us reach enterprise-quality faster.

Just an idea — totally up to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants