Files
karim f4cd16b7ac Add native2d feature: wgpu 2D viewport window inside Tauri process
Spawns a GTK-free winit window with its own wgpu surface from Tauri's
setup hook on a background thread, sidestepping the WebKitGTK surface
contention on Wayland. Reuses render2d's renderer via a shared demo
module. Opt-in behind the native2d cargo feature; default build
unaffected.
2026-07-02 01:26:07 +02:00

4.9 KiB

M2 — nativer wgpu-2D-Renderer im Tauri-Fenster: Ansatzwahl

Ziel: den bereits fluessig laufenden standalone render2d-Renderer aus dem ECHTEN Tauri-Prozess heraus mit nativer GPU-Performance anzeigen — nicht in der WebKitGTK-Webview (Perf-Flaschenhals), nicht in einem Chromium-Workaround. Maschine: Linux, Wayland, AMD.

Gewaehlter Ansatz: B — separates natives Fenster (winit) im Tauri-Prozess

Der Tauri-Hauptthread haelt weiterhin die GTK-Hauptschleife + das Webview-Fenster (HTML-Chrome). Aus dem Tauri-setup-Hook startet der Prozess auf einem Hintergrund-Thread ein eigenes natives winit-Fenster mit eigener wgpu-Surface, das die render2d-Demo-Szene (konkaves L + Raum + Papier-mm-Linien) rendert, pan-/zoombar. Renderer/Szene werden NICHT reimplementiert — es ist exakt der Code des verifizierten standalone spike-Bins (render2d::gpu::Renderer + render2d::demo_scene).

Warum B (und was gegen A/C spricht)

  • Kein geteilter Wayland-Surface → keine Contention/Flicker. winit spricht auf Linux DIREKT Wayland/X11 (Crates wayland-client/x11rb), es benutzt kein GTK. Das native Fenster bekommt eine eigene, von WebKitGTK voellig getrennte Wayland-Surface. Genau das umgeht das dokumentierte Problem aus der Vorrecherche (Roh-wgpu-Surface UNTER der Webview im selben Fenster → Flicker/Schwarzbild auf Wayland).

  • Zwei Fenster-Stacks, aber KEIN Event-Loop-Konflikt. tao (Tauri) fuehrt eine GTK-Hauptschleife auf dem Hauptthread; winit fuehrt eine eigene Schleife. winit 0.30 erlaubt die Event-Loop explizit auf einem Nicht-Haupt-Thread via EventLoopBuilderExtWayland::with_any_thread(true) (X11-Pendant analog). Der native Renderer laeuft daher auf std::thread „cad-native2d", der Tauri-/GTK- Hauptthread bleibt frei. Da winit nicht an GTK gebunden ist, kollidieren die beiden Schleifen nicht (getrennte Stacks, getrennte fds).

  • Ansatz A (wgpu-Surface im SELBEN Tauri-Fenster, Unter-/Overlay): verworfen. taos raw_window_handle_rwh_06() liefert auf Wayland den WaylandWindowHandle der GTK-ApplicationWindow — also DIESELBE Surface, in die WebKitGTK komponiert. Eine zweite wgpu-Surface darauf ist genau die Contention, die die Vorrecherche als flackernd/schwarz auf diesem Setup markiert hat. Hoechstes Wayland-Risiko, fuer den Spike ungeeignet.

  • Ansatz C (wgpu als Haupt-Surface, HTML nur duennes Overlay): verworfen fuer den Spike. Sauberste Perf-Story, aber groesster Umbau: die ganze App muesste auf eine winit/tao-getriebene Haupt-Schleife umziehen und die Tauri-Webview zur Nebenrolle degradiert werden. Kein „minimaler realer Spike" mehr. Bleibt die Ziel-Endarchitektur-Option, aber nach B.

Crates / Versionen (verifiziert aus der Lock-Datei)

Rolle Crate Version
Tauri tauri / tauri-runtime-wry 2.11.5 / 2.11.4
Fenster (Webview-Seite) tao 0.35.3
Webview wry 0.55.1
Natives Renderfenster winit 0.30.13
GPU wgpu / wgpu-hal 22.1.0 / 22.0.0
Handle-Bruecke raw-window-handle 0.6.2 (identisch fuer tao UND wgpu/winit)
Renderer render2d (Pfad) 0.1.0, Feature window

Der entscheidende Kompatibilitaets-Glueckstreffer: tao 0.35 und wgpu 22/winit 0.30 teilen sich raw-window-handle 0.6.2 — keine rwh-Versionsbruecke noetig. (Fuer Ansatz B wird der tao-Handle gar nicht gebraucht, weil das native Fenster eine eigene winit-Surface hat; die Versions-Parität ist aber die Voraussetzung fuer ein spaeteres A/Compositing, falls je gewuenscht.)

Wayland-Caveats (fuer den Start auf dieser Maschine)

  • WEBKIT_DISABLE_DMABUF_RENDERER=1 bleibt fuer die Webview-Sichtbarkeit auf diesem Wayland/AMD-Setup noetig (Vorrecherche). Betrifft die WebKitGTK-Seite, nicht das wgpu-Fenster.
  • Das native winit-Fenster laeuft ueber Vulkan; GLES/EGL-Fallback wurde standalone ebenfalls funktionierend gesehen. WGPU_BACKEND=gl erzwingt bei Vulkan-Zicken den GL-Pfad.
  • with_any_thread(true) ist zwingend — ohne die Freigabe panict winit, weil es die Event-Loop sonst nur auf dem Hauptthread zulaesst (den haelt hier GTK).

Bau-Isolierung

Alles hinter Cargo-Feature native2d in cad-tauri (opt-in). Der normale Build (cargo build, npm run tauri:dev) zieht weder winit noch wgpu und bleibt unveraendert. render2d bleibt ohne Tauri-/GTK-Abhaengigkeiten headless baubar und testbar.

Naechster Schritt Richtung Vollbild-App (2D-Viewport + HTML-Chrome)

  1. Szene aus dem echten Modell speisen: Plan.primitives (TS) → serde-Scene → ueber einen Tauri-emit/Command an den native2d-Thread (statt demo_scene).
  2. Pan/Zoom-State zwischen Webview-Chrome und native2d-Fenster synchronisieren (Tauri-Events beidseitig).
  3. Fenster-Kopplung: das native Fenster als Kind/als angedockten Bereich neben der Webview positionieren (Layout), spaeter ggf. Umstieg auf Ansatz C, wenn ein einziges Fenster gefordert ist.