|
|
Donner 0.5.1
Embeddable browser-grade SVG2 engine
|
Geode is Donner's GPU-native SVG rendering backend. In most uses it runs headless and owns its own wgpu::Device, but the public API also supports embedded mode: the host application owns the WebGPU device/queue and a target texture (typically a swap-chain image), and Geode draws into that texture without creating any WebGPU objects of its own.
Reach for embedded mode when you want to render SVG into an existing WebGPU frame alongside other GPU work — a game engine UI layer, a native editor window, a composited WebGPU canvas — without paying for a second device.
Geode is confirmed against the wgpu-native backend that ships in third_party/webgpu-cpp. The Dawn C++ wrapper exposes the same C++ API surface but a few status enumerants differ (see Troubleshooting below).
GeodeEmbedConfig (declared in donner/svg/renderer/geode/GeodeDevice.h) bundles the four pieces of host state Geode needs:
The adapter field is optional. When supplied it lets Geode probe for the Intel Arc + Vulkan MSAA bug and fall back to alpha-coverage AA; when left null, Geode assumes the host has already chosen a safe configuration.
CreateFromExternal is non-owning: the returned GeodeDevice's destructor will not release the underlying wgpu::Instance, adapter, device, or queue. That ownership stays with the host.
Call setTargetTexture once per frame (before beginFrame / draw / endFrame, which RendererGeode::draw fuses together internally), and call clearTargetTexture after each frame if you intend to mix embedded and headless output — it reverts the renderer to the internal offscreen target path.
| Requirement | Why |
|---|---|
| usage includes wgpu::TextureUsage::RenderAttachment | Geode draws into the texture via a render pass. |
| format matches GeodeEmbedConfig::textureFormat | The internal pipelines are built against a single color format. |
| usage includes wgpu::TextureUsage::CopySrc | Only needed for RendererGeode::takeSnapshot(); omit otherwise. |
| sampleCount is 1 | Geode resolves MSAA internally before writing to the host target. |
If the format doesn't match, Geode will reject the texture at beginFrame time and fall back to its internal offscreen target for that frame.
A runnable GLFW host lives at examples/geode_embed.cc alongside its two platform-specific surface helpers (geode_embed_surface_linux.cc, geode_embed_surface_macos.mm). Build and run it with:
The example handles the full host lifecycle:
Defining GLFW_EXPOSE_NATIVE_X11 pulls in <X11/Xlib.h>, which #defines None, True, False, and Status — all of which collide with C++ names used elsewhere (for example wgpu::Status, an enum class in third_party/webgpu-cpp/webgpu.hpp). Two fixes, in order of preference:
wgpu::Surface::getCurrentTexture writes status into WGPUSurfaceTexture::status, and the success enumerant on wgpu-native is SuccessOptimal (not Success). Treat both SuccessOptimal and SuccessSuboptimal as renderable; skip the frame on Timeout, Outdated, Lost, and reconfigure the surface on Outdated. Similarly, Instance::requestAdapter and Adapter::requestDevice are callback-based in the C API; the webgpu-cpp wrapper provides synchronous overloads that work on wgpu-native because the callback fires before the call returns. Dawn requires driving the future explicitly — the wrapper handles that transparently too, but be aware that synchronous wrapper calls are a wgpu-native-specific convenience.
If you see surface.getCurrentTexture always reporting Outdated, the surface dimensions probably don't match the SurfaceConfiguration — call surface.configure again after any window resize.