Skip to content

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 07 Jun 13:42
· 53 commits to master since this release

Features

Async upload jobs

Long-running uploads can run on a background thread without freezing the viewport. The renderer owns a job runner that workers report to via a channel; the main thread drains completions once per frame from prepare_scene. Each call returns a JobId immediately; consumers poll upload_status(JobId) or attach a completion callback, then take the resulting handle with upload_result_*(JobId). The synchronous upload_* entries keep their signatures and are now thin wrappers that submit a job and wait.

Async entry points are wired up for every upload that previously blocked the main thread:

  • Environment maps (begin_upload_environment_map). Irradiance convolution, GGX prefilter, and BRDF LUT generation run on a worker. The GPU compute path no longer blocks on device.poll. The BRDF LUT is cached after its first generation.
  • Mesh data (begin_upload_mesh_data). Tangent computation, vertex repack, and normal-line generation move to a worker.
  • Skin weights (begin_upload_skin_weights).
  • Textures and normal maps (begin_upload_texture, begin_upload_normal_map).
  • Gaussian splats (begin_upload_gaussian_splats) and overlay textures (begin_upload_overlay_texture).
  • Volume meshes: begin_upload_volume_mesh_data, begin_upload_clipped_volume_mesh_data, begin_upload_sparse_volume_grid_data, begin_upload_projected_tet_mesh.
  • Volumes: begin_upload_volume and begin_upload_volume_for_mc.
  • The four curve types: begin_upload_polyline, _streamtube, _tube, _ribbon.

Three scene-item categories also gain a pre-upload + per-frame reference workflow (own an id, submit a lightweight ref item each frame): point clouds (PointCloudId), glyph sets (GlyphSetId), tensor glyph sets (TensorGlyphSetId), and two sprite variants for non-particle use (SpriteSetId for static billboards, SpriteInstanceSetId for entity sprites). SceneFrame gains matching *_refs fields. GlyphUniform and TensorGlyphUniform now carry a per-frame model matrix at offset 0; existing per-frame consumers see identical output.

Public types: JobId, UploadStatus, ProgressHandle, ResultSlot. New methods on ViewportGpuResources and ViewportRenderer: process_uploads, upload_status, uploads_pending, all_uploads_complete, on_upload_complete. ViewportRenderer::rebuild_camera_bind_groups is now public so consumers driving begin_upload_environment_map can rebuild bind groups themselves once the job lands.

Showcase 51 (eframe-showcase) demonstrates the system end to end with a sync vs async toggle, per-asset progress bars, and an in-flight count read from the same public API a consumer would use.

Item-type plugins

Plugins can ship a new kind of scene item without forking the lib. New categories register through an ItemTypePlugin trait and submit their per-frame data via SceneFrame::submit_plugin_items. The lib handles picking, selection outline, frustum cull, clip volumes, shadow casting, and OIT transparency for plugin items the same way it handles built-ins. Published WGSL helpers for lighting, transparency, and clipping keep plugin shaders in sync with the renderer.

Plugin-facing job API

ItemTypePlugin implementations can submit background work through the same runner the built-in uploads use. ItemFrameContext gains a jobs: Jobs<'a> field with submit_cpu<T, F>, status, and take<T: 'static>. The plugin trait surface is otherwise unchanged: a job submitted in frame N is consumable in frame N+1. A worked example lives at viewport-lib-terrain/examples/eframe_plugin_jobs.rs.

Improvements

  • GPU cull service is now multi-batch. CullSubmission carries per-batch metadata, atomic counter, and indirect-draw buffers alongside the instance AABB list; one call dispatches the cull compute for every batch. Per-mesh draw parameters live in BatchMeta, published from plugin_api::cull. submit_cull_single_mesh and submit_cull_shadow_single_mesh keep the simple call shape for one-mesh-N-instances plugins. The four-method dispatch surface on CullResources collapses to one.
  • Scene-graph lights gain built-in glyphs and picking. scene::build_light_glyphs(&scene, &selection) returns a GlyphItem per light (sphere for point, arrow for spot/directional) plus a PolylineItem influence-volume wireframe for any selected light.
  • 8-light cap removed. The fixed array<Light, 8> uniform is replaced by a per-frame storage buffer sized to MAX_SCENE_LIGHTS (currently 512). When the union of EffectsFrame::lighting.lights and SceneFrame::lights exceeds the cap, the shadow-casting directional stays at index 0 and the rest are ranked by LightSource::importance * proximity_weight.
  • upload_environment_map is much faster. The CPU irradiance, GGX prefilter, and BRDF LUT loops now run in parallel via rayon::par_chunks_mut. A GPU compute path runs the three convolutions as compute dispatches when the device exposes Rgba16Float storage write, dropping a multi-hundred-millisecond cost to a few milliseconds.

Bug fixes

  • Per-object draw path no longer collapses shared-mesh instances. The path used for two-sided, matcap, param_vis, scalar attribute, override, and wireframe items wrote every item's ObjectUniform into one buffer per MeshId, so when N scene nodes shared a mesh only the last write's transform survived. The renderer now maintains a per-scene-item pool of object uniform buffers and bind groups, indexed by position in the scene-items list, growing lazily with a cache key.
  • Excluded-item filter gaps across LDR, HDR, and OIT: the LDR filter now includes matcap_id, the HDR filter and has_transparent predicate now include param_vis, and the non-instancing HDR check plus per-object OIT loop now accept material.is_blend() items at opacity 1.0. Previously matcap-only, param_vis-only, or fully opaque blend items could be silently invisible.
  • OIT instanced pipeline: fix init-order trap where the pipeline was never created when the first frame had an empty scene. Instanced transparent geometry added on later frames is now drawn correctly.
  • Residual Y-up fixes. Hemisphere ambient now uses world_normal.z in mesh.wgsl, mesh_oit.wgsl, and the two instanced variants; shadow up-vector fallbacks use Vec3::X when the light direction is collinear with Z; build_glyph_arrow is rebuilt along +Z, so GlyphItem arrows and directional/spot light glyphs point along the supplied vector; placeholder pick-hit normals for the curve types are Vec3::Z.
  • Equirectangular IBL convention switched from Y-up to Z-up to match the rest of the library.
  • OverlayImageItem.alpha now actually fades the image. The pre-multiplied alpha blending was leaving RGB at full intensity. Same fix incidentally corrects soft-edge PNGs.

Removed

  • Legacy async texture API: upload_texture_async, PendingTextureId, is_upload_ready, promote_texture, and the bespoke staging-buffer pool that backed them. Use begin_upload_texture + upload_result_texture instead. See docs/migration-guides/upload-job-system.md.