|
|
Donner SVG Editor & Engine
SVG-native editor and embeddable SVG2 + CSS3 engine in C++20, with GPU (WebGPU) and compact CPU renderers, built for correctness, security, and performance.
|
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 host state Geode needs:
The instance and adapter fields are optional. Browser embedders should supply instance when calling RendererGeode::takeSnapshot() so synchronous readback can wait for map callback completion through Instance::waitAny(). When supplied, Geode preserves adapter for callers that need metadata about the adapter associated with the external device.
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 renders directly into a single-sample 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.