Feat/vulkan frontends - #21
Open
acalcutt wants to merge 17 commits into
Open
Conversation
…base) The Vulkan bindings package packed only the Windows DLLs, so unlike the base MapLibreNative.Maui package it delivered no native library on iOS/macCatalyst - a transitive consumer (via the handlers) linked nothing. Bring it to parity: - Pack the iOS XCFramework (device + simulator) and macCatalyst .a into buildTransitive/native/, and prefer the XCFramework for local iOS builds. - Add buildTransitive/MapLibreNative.Maui.Vulkan.targets (mirrors the base package's targets) to re-add the Apple NativeReferences - with the Metal frameworks and -lsqlite3 -lz -lc++ linker flags - for transitive consumers. - release.yml: build the Vulkan iOS XCFramework in the pack-vulkan job before packing, matching the base pack job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The CI pack-vulkan job (which runs on PRs) arranged the Apple slices but never built the iOS XCFramework, so with the new packaging the iOS native would be silently skipped (file-existence gated) - the parity change would go untested. Add the Create iOS XCFramework step (mirroring the base pack job) and a verification step that fails the build if the packed Vulkan .nupkg is missing the buildTransitive targets, the macCatalyst .a, or the iOS XCFramework. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Foundation for real Vulkan frontends. Adds, without changing existing GL/Metal behaviour (compiles on all backends): - mbgl_get_render_backend() -> "opengl"|"vulkan"|"metal" so the shared managed layer can pick the right surface handshake at runtime. - mbgl_frontend_create() (backend-agnostic) with mbgl_frontend_create_gl() kept as a thin alias. - mbgl_frontend_read_pixels() + PlatformFrontend::readPixels() (default no-op) for the offscreen (Vulkan Windows) read-back path. - platform_frontend_vulkan_common.hpp: VulkanFrontendT<Backend> implementing the PlatformFrontend/RendererFrontend interface once; each platform supplies only a surface-specific mbgl::vulkan::RendererBackend. Not yet wired in. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the throwing stub with an ANativeWindow surface backend mirroring maplibre-native's android_vulkan_renderer_backend (VK_KHR_surface + VK_KHR_android_surface, swapchain presents into the TextureView surface, matching today's EGL path), driven through the shared VulkanFrontendT<Backend>. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the throwing stub with an offscreen frontend that reuses mbgl::vulkan::HeadlessBackend (already compiled into mbgl-core on Windows Vulkan builds via platform/windows/windows.cmake): renders into a headless color texture and returns the pixels through mbgl_frontend_read_pixels(), which the managed layer blits into the WriteableBitmap. No HWND/window surface, so the airspace-free in-tree model of the WGL path is preserved. CMake adds platform/default/include for the headless header on Vulkan builds. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mbgl_frontend_read_pixels uses size_t but the header only pulled in <stdint.h>. Apple clang doesn't get size_t transitively there, so every target including the header (incl. the Metal iOS/macOS builds) failed with "unknown type name 'size_t'". Add <stddef.h>. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…al default) Wraps the existing Metal frontend in #if MLN_RENDER_BACKEND_METAL and adds a #elif MLN_RENDER_BACKEND_VULKAN path: renders Vulkan into a CAMetalLayer-backed UIView via VK_EXT_metal_surface (vk::MetalSurfaceCreateInfoEXT + createMetalSurfaceEXTUnique), driven through the shared VulkanFrontendT, and returns the view from getNativeView() like the MTKView. Apple keeps defaulting to Metal; the Vulkan path only compiles under -DMLN_WITH_VULKAN=ON. CMake selects link libs accordingly (Metal/MetalKit vs QuartzCore/UIKit; MoltenVK is linked by the consuming app since mln-cabi is a static archive on Apple). Not yet wired into CI — the native-apple-vulkan build job comes next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…package
Adds native-apple-vulkan.yml (mirrors native-apple.yml: iOS device/simulator +
macCatalyst) building mln-cabi with -DMLN_WITH_METAL=OFF -DMLN_WITH_VULKAN=ON.
Vulkan headers + VMA are vendored by maplibre-native, so only a Vulkan SDK
(MoltenVK) is installed to satisfy find_package(Vulkan) on the Darwin path;
mln-cabi is a static archive on Apple so MoltenVK links in the consuming app.
Artifacts: native-mln-{ios-arm64,iossimulator-arm64,maccatalyst}-vulkan.
Wires build-apple-vulkan into ci.yml + release.yml and repoints pack-vulkan to
consume the Vulkan Apple slices (was reusing the Metal build-apple output), so
the Vulkan package now ships a real Vulkan Apple binary. The base package still
uses the Metal build-apple.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Bindings: add mbgl_get_render_backend, the backend-agnostic mbgl_frontend_create, and mbgl_frontend_read_pixels P/Invokes. MbglFrontend now creates via the generic entry point, exposes the static RenderBackend (OpenGL/Vulkan/Metal, queried once), and adds ReadPixels() for the offscreen path. - Windows MapImageView: branch on backend. OpenGL keeps the WGL context + glReadPixels; Vulkan skips WGL entirely, renders headless, and copies frames back via frontend.ReadPixels into the WriteableBitmap. The GL vertical flip (ScaleY = -1) is undone for Vulkan since the headless read-back is already top-down. Android/Apple need no change: they pass the ANativeWindow / consume getNativeView(), which the generic create routes to the Vulkan frontends. (WPF MlnMapImage still assumes GL — a Vulkan branch there is a follow-up.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds MauiSample-vulkan-win-x64 to the "Pack WPF NuGet + Windows samples" job output (ci.yml + release.yml). Because the managed layer is backend-agnostic, the Vulkan sample is the normal win-x64 MauiSample publish with the Vulkan-built mln-cabi.dll overlaid — at runtime MapImageView detects the "vulkan" backend and drives the offscreen Vulkan frontend. Downloads the native-mln-windows-x64-vulkan artifact (adds build-windows-vulkan to the job's needs) and zips the result alongside the existing Windows samples. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
humbletim/setup-vulkan-sdk cannot build MoltenVK (it errored with "unknown component: MoltenVK"). MoltenVK isn't needed at build time anyway: mln-cabi is a static archive using Vulkan's dynamic dispatch loader with vendored headers, so no Vulkan library links here (MoltenVK links later in the app). Install only Vulkan-Headers + Vulkan-Loader, which is enough to satisfy find_package(Vulkan) on the macCatalyst leg. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maplibre-native's own mbgl/vulkan/*.cpp has latent -Wshorten-64-to-32 (size_t -> uint32_t) truncations that only surface under Apple's strict flags, since upstream never compiles the Vulkan backend for Apple (upload_pass.cpp:54 was the first of many). Set -DMLN_WITH_WERROR=OFF so these upstream warnings don't fail our build; our own code is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Windows samples - WPF MlnMapImage: branch on MbglFrontend.RenderBackend like MapImageView — OpenGL keeps the WGL context + glReadPixels; Vulkan skips WGL, renders headless, and copies frames back via frontend.ReadPixels into the WriteableBitmap (flip undone for the top-down read-back). - ConsoleExample: add a RunVulkan() headless render path (no WGL/Win32) selected when the loaded native reports the Vulkan backend. - ci.yml + release.yml: the Windows-samples job now overlays the Vulkan mln-cabi.dll onto all three win-x64 apps and zips ConsoleExample-vulkan / WpfExample-vulkan / MauiSample-vulkan alongside the existing samples, so the windows-samples bundle has a working Vulkan build of each renderer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-back The offscreen frontend rendered under BackendScope::Implicit and then read pixels back in a *separate* scope. Implicit never calls HeadlessBackend::activate() (which creates the backend impl and validates the Vulkan context), and reading in a second scope tears the just-rendered frame's resources down before readStillImage() copies getAcquiredImage() — reading/freeing invalid Vulkan memory and corrupting the heap (0xc0000374, crashing MauiSample/WpfExample on the Vulkan native). Mirror maplibre-native's HeadlessFrontend: render under the default (Explicit) scope and read the still image back inside the SAME scope, caching the RGBA frame so readPixels() just copies it out. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…on crash The offscreen Vulkan path still crashes with heap corruption (0xc0000374) and guessing hasn't pinned it, so instrument each stage of VulkanOffscreenFrontend (create / ctor / update / render steps / readStillImage / readPixels / dtor) to %TEMP%\mln_vulkan_diag.log, flushed per line so the last entry survives the crash and tells us exactly which step dies. Also ship mln-cabi.pdb in the Windows Vulkan artifact and alongside the overlaid sample DLL so the crash dump can be symbolicated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts: # handlers/Windows/MapImageView.Windows.cs # wpf/MlnMapImage.cs
mbgl_get_render_backend and mbgl_get_last_error return pointers to memory the native library owns — a static string literal and a thread_local std::string buffer respectively. Marshalling their return as a `string` makes the source-generated P/Invoke free that pointer with FreeCoTaskMem, corrupting the heap (0xC0000374). mbgl_get_render_backend is the first native call at startup (static RenderBackend initializer), so every build — GL and Vulkan — crashed on load before showing a window. Return IntPtr and copy with Marshal.PtrToStringUTF8, which does not free. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.