zaxis 0.1.0

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

MethodResult / action
Renderer::new(Arc<Window>).awaitResult<Renderer, RenderError>; Vsync
Renderer::new_with_presentation_mode(window, mode).awaitInitialize with explicit presentation mode
Renderer::new_with_backends(window, mode, Some(backends)).awaitTry 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

Modewgpu modeRequested maximum frame latency
Vsync (default)FIFO2
ImmediateAutoNoVsync: immediate, then mailbox, then FIFO fallback1

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 conditionRenderer behavior
SuccessValidate/upload as needed, draw, submit, notify native window, present
SuboptimalPresent, then reconfigure to current native size
TimeoutRenderStatus::Retry
OccludedRenderStatus::Dormant
OutdatedResize/reconfigure, then Retry
LostRecreate surface, verify format, resize/reconfigure, then Retry
Validation failureRenderError::Validation
Device loss callbackRenderError::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:

VariantMeaning / response
CreateSurface(CreateSurfaceError)Native GPU surface creation failed
RequestAdapter(RequestAdapterError)No compatible requested adapter was obtained
RequestDevice(RequestDeviceError)GPU device request failed
UnsupportedSurfaceNo 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.

Edit on GitHub

On this page