Renderer
Public methods, presentation modes, surface recovery, validation, and errors.
Renderer binds to one Arc<winit::window::Window>. It owns the GPU surface, instance,
adapter, device, queue, buffers, textures and pipelines.
Internally it is two parts. The part that belongs to the device (queue handle, layouts and
samplers, the built-in pipelines per color format, sample count and depth format, the texture
store with the glyph atlas, geometry buffers, viewport uniform, material blocks, backdrop
textures, counters) does not know about windows; the part that belongs to the window is the
surface, its configuration, the presentation mode and recovery. EmbeddedRenderer uses only the
first part, on a device the host created, to draw into a render pass or texture it owns: see
Embedding in a wgpu host. Renderer::create_embedded(options) makes one that
shares this renderer's pipelines, atlas and image store, as create_sibling does for a second
window.
Methods
| Method | Result / action |
|---|---|
Renderer::new(Arc<Window>).await | Result<Renderer, RenderError>; Vsync |
Renderer::new_with_presentation_mode(window, mode).await | Initialize with explicit presentation mode |
Renderer::new_with_backends(window, mode, Some(backends)).await | Try only these wgpu backends; None is the default order |
resize(PhysicalSize<u32>) | Reconfigure surface and MSAA; returns Result<(), RenderError> |
render(&DrawData, Color) | Present; returns Result<RenderStatus, RenderError> |
presentation_mode() | Return requested mode |
set_presentation_mode(mode) | Reconfigure presentation while preserving mesh/texture caches |
stats() | Snapshot cumulative RendererStats |
adapter_info() | wgpu::AdapterInfo for diagnostics |
create_sibling(window, mode) | Renderer for another window on the same device; shares pipelines and the texture store |
create_embedded(EmbedOptions) | EmbeddedRenderer on this device, sharing pipelines and the texture store |
Initialization selects a low-power compatible adapter, requests downlevel GPU limits
with the adapter's resolution limits, and creates the surface through safe Arc
ownership. zaxis forbids unsafe Rust code. On Windows DX12 is tried before the default
set unless WGPU_BACKEND or new_with_backends names one.
In a browser Renderer::new* is still async and never blocks; the runner awaits it in a
task. It probes WebGPU first, without touching the canvas, and falls back to WebGL2 with the
downlevel WebGL2 limits (the texture limit is raised to what the context reports). The shaders
are the same on both and use only features WebGL2 has. See Web.
Presentation modes
| Mode | wgpu mode | Requested maximum frame latency |
|---|---|---|
Vsync (default) | FIFO | 2 |
Immediate | AutoNoVsync: immediate, then mailbox, then FIFO fallback | 1 |
Immediate presentation can tear. presentation_mode() returns the requested enum,
not the platform's selected fallback. To switch at runtime in a custom host:
renderer.set_presentation_mode(zaxis::PresentationMode::Immediate);
window.request_redraw();Changing mode does not rebuild the pipeline or invalidate geometry/texture caches.
It survives surface resize and recovery. The built-in runner's initial mode comes
from RunOptions; it does not expose a renderer to App::update.
supported_present_modes() returns the modes advertised by the current surface.
For diagnostics, wait_idle(Duration) waits for submitted GPU work with a timeout,
reporting poll/device-loss errors. It serializes CPU/GPU execution and is intended
for completion benchmarks. It does not prove
that the compositor has displayed a frame.
Color and antialiasing
The renderer selects an sRGB surface format when available (a browser canvas offers
bgra8unorm or rgba8unorm, so it uses the sRGB view). If only RGBA8/BGRA8
unorm is available, it uses an sRGB view for the attachment. Unsupported formats
produce UnsupportedSurface.
Vertex colors are linear straight-alpha floats. Textures use sRGB RGBA8 and straight
alpha. The shader premultiplies vertex colors before interpolation and sampled
textures before compositing. Premultiplied alpha blending runs on the sRGB
attachment, keeping transparent contour and border transitions free of color halos.
Clear Color converts to linear RGB.
Built-in shapes use a one-physical-pixel coverage transition on their outer edges and between borders and fills. Arc tessellation limits chord error to 0.01 physical pixels at the current DPI (up to a resource cap for exceptionally large radii). Backdrop blur mixes the original and filtered RGBA by the same contour coverage.
4× MSAA is enabled when the attachment format supports it; otherwise rendering uses one sample. Shape coverage smoothing works in both cases. There is no public sample-count override or access to internal GPU resources.
Surface outcomes
| Acquisition condition | Renderer behavior |
|---|---|
| Success | Validate/upload as needed, draw, submit, notify native window, present |
| Suboptimal | Present, then reconfigure to current native size |
| Timeout | RenderStatus::Retry |
| Occluded | RenderStatus::Dormant |
| Outdated | Resize/reconfigure, then Retry |
| Lost | Recreate surface, verify format, resize/reconfigure, then Retry |
| Validation failure | RenderError::Validation |
| Device loss callback | RenderError::DeviceLost |
Zero-sized surfaces return Dormant without rendering. Hosts must delay retries
and wake dormant windows only on relevant events. The runner implements this;
custom hosts use Custom host.
Validation
Before use, viewport size and scale must be finite and positive. Texture payloads must have nonzero dimensions within device limits and exactly width × height × 4 bytes. Geometry upload validates global indices, finite vertex fields, draw ranges, finite clips, referenced texture IDs, and GPU buffer limits. Surface resize validates the GPU texture-dimension limit.
Geometry validation and uploads are keyed by (DrawData::source, DrawData::revision).
Editing vertices or commands without advancing the revision violates the cache
contract; unchanged keys do not cause a fresh geometry validation. Textures have
independent revision and size checks.
When a GeometryUpdate names the exact validated
parent revision, unchanged vertex/index ranges reuse that validation and upload.
Dirty ranges and all draw commands are checked. A missing parent, shrinking buffers,
or no hint selects complete validation; a newly allocated buffer is fully uploaded.
Materials
Commands with a material draw with a pipeline built on first use from the WGSL in
DrawData::materials, cached per (MaterialId, attachment format, sample count) and shared by
the windows of one device. At most 64 pipelines stay between frames (least recently used first);
the pipelines a frame draws with are never evicted. Pipelines are never rebuilt for changed
parameters. Uniform blocks of a frame are written once per revision into one buffer, aligned to
min_uniform_buffer_offset_alignment, and bound with a dynamic offset of a fixed 1 KiB binding,
within the WebGL2 limit of 16 KiB per block. A material that reads the backdrop uses the blur path
of blur commands (offscreen canvas, copy and Gaussian blur of the area), not a second mechanism.
Sources are validated with naga before they reach the renderer, so a build error here means a
device or driver limit: the material draws nothing, RendererStats::material_pipeline_failures
counts it and Renderer::take_material_errors() returns the text. A new renderer after a lost
device recompiles everything it needs from the next DrawData. RendererStats adds
material_draws, material_pipeline_builds and material_uniform_bytes.
Errors
RenderError implements Display and std::error::Error:
| Variant | Meaning / response |
|---|---|
CreateSurface(CreateSurfaceError) | Native GPU surface creation failed |
RequestAdapter(RequestAdapterError) | No compatible requested adapter was obtained |
RequestDevice(RequestDeviceError) | GPU device request failed |
UnsupportedSurface | No usable surface configuration/format, or recovered surface lost its format |
DeviceLost(String) | Recreate renderer; preserve context/model |
Validation(String) | GPU pipeline or surface validation failed |
InvalidDrawData(&'static str) | Fix viewport, geometry, command, texture payload, or exceeded GPU limits |
Log adapter_info() and the full error when diagnosing a backend failure.
Common symptoms and fixes are in Troubleshooting.