Skip to main content

DeviceResources

Struct DeviceResources 

Source
pub struct DeviceResources {
Show 56 fields pub target_format: TextureFormat, pub sample_count: u32, pub pipeline_cache: Option<PipelineCache>, pub solid_pipeline: RenderPipeline, pub solid_two_sided_pipeline: RenderPipeline, pub transparent_pipeline: RenderPipeline, pub wireframe_pipeline: RenderPipeline, pub camera_uniform_buf: Buffer, pub light_uniform_buf: Buffer, pub light_storage_buf: Buffer, pub clustered: ClusteredResources, pub camera_bind_group: BindGroup, pub camera_bind_group_layout: BindGroupLayout, pub object_bind_group_layout: BindGroupLayout, pub shadow_map_texture: Texture, pub shadow_map_view: TextureView, pub shadow_sampler: Sampler, pub point_shadow_cube_texture: Texture, pub point_shadow_cube_view: TextureView, pub point_shadow_face_views: Vec<TextureView>, pub shadow_point_pipeline: RenderPipeline, pub shadow_point_face_buf: Buffer, pub shadow_point_face_bind_group: BindGroup, pub shadow_pipeline: RenderPipeline, pub shadow_pipeline_two_sided: RenderPipeline, pub shadow_uniform_buf: Buffer, pub shadow_bind_group: BindGroup, pub shadow_info_buf: Buffer, pub shadow_atlas_depth_sampler: Sampler, pub shadow_atlas_viewer_pipeline: RenderPipeline, pub shadow_atlas_viewer_bg: BindGroup, pub shadow_atlas_viewer_buf: Buffer, pub debug_frag_sentinel_buf: Buffer, pub gizmo_pipeline: RenderPipeline, pub gizmo_vertex_buffer: Buffer, pub gizmo_index_buffer: Buffer, pub gizmo_index_count: u32, pub gizmo_uniform_buf: Buffer, pub gizmo_bind_group: BindGroup, pub overlay_pipeline: RenderPipeline, pub overlay_line_pipeline: RenderPipeline, pub grid_pipeline: RenderPipeline, pub grid_uniform_buf: Buffer, pub grid_bind_group: BindGroup, pub overlay_bind_group_layout: BindGroupLayout, pub constraint_line_buffers: Vec<(Buffer, Buffer, u32, Buffer, BindGroup)>, pub axes_pipeline: RenderPipeline, pub axes_vertex_buffer: Buffer, pub axes_vertex_count: u32, pub texture_bind_group_layout: BindGroupLayout, pub fallback_texture: GpuTexture, pub ibl_irradiance_view: Option<TextureView>, pub ibl_prefiltered_view: Option<TextureView>, pub ibl_brdf_lut_view: Option<TextureView>, pub ibl_skybox_view: Option<TextureView>, pub frame_upload_bytes: u64, /* private fields */
}
Expand description

Device-shared GPU resources: pipelines, layouts, samplers, fallbacks, LUTs, and the per-feature pipeline clusters (decal, scatter, volume, …). Created once at init and shared across every viewport.

Typically stored in the host framework’s resource container and accessed by ViewportRenderer during prepare() and paint().

Fields§

§target_format: TextureFormat

Swapchain texture format; all pipelines are compiled for this format.

§sample_count: u32

MSAA sample count used by all render pipelines.

§pipeline_cache: Option<PipelineCache>

Optional pipeline cache shared by every pipeline built here. Some only when the device enables Features::PIPELINE_CACHE. Persist its contents across runs with ViewportRenderer::pipeline_cache_data to skip shader recompilation on later launches.

§solid_pipeline: RenderPipeline

Solid-shaded render pipeline (TriangleList topology, no blending).

§solid_two_sided_pipeline: RenderPipeline

Solid-shaded render pipeline with back-face culling disabled (two-sided surfaces).

§transparent_pipeline: RenderPipeline

Transparent render pipeline (TriangleList topology, alpha blending).

§wireframe_pipeline: RenderPipeline

Wireframe render pipeline (LineList topology, same shader).

§camera_uniform_buf: Buffer

Uniform buffer holding the per-frame CameraUniform (view-proj + eye position).

§light_uniform_buf: Buffer

Uniform buffer holding the per-frame LightsUniform header (count + hemisphere + IBL + debug params). The per-light array lives in light_storage_buf (binding 13).

§light_storage_buf: Buffer

Storage buffer of per-light SingleLightUniform entries (binding 13).

Sized for MAX_SCENE_LIGHTS. The renderer truncates the consumer’s light list to this cap each frame, ranking surplus lights by LightSource::importance * proximity_weight.

§clustered: ClusteredResources

Clustered-shading state: cluster grid, global light index list, and the per-frame cluster build pipeline. Bindings 14/15/16 of the camera bind group expose this state to every lit pipeline.

§camera_bind_group: BindGroup

Bind group (group 0) binding camera, light, clip-plane, and shadow uniforms.

§camera_bind_group_layout: BindGroupLayout

Bind group layout for group 0 (shared by all scene pipelines).

§object_bind_group_layout: BindGroupLayout

Bind group layout for group 1 (per-object uniform: model, material, selection).

§shadow_map_texture: Texture

Shadow atlas depth texture (Depth32Float, atlas_size x atlas_size, 2x2 tile grid).

§shadow_map_view: TextureView

Depth texture view for binding as a shader resource (sampling).

§shadow_sampler: Sampler

Comparison sampler for PCF shadow filtering.

§point_shadow_cube_texture: Texture

Cubemap-array depth texture for point-light shadows. Layered as MAX_POINT_SHADOW_LIGHTS * 6 faces of POINT_SHADOW_FACE_SIZE px.

§point_shadow_cube_view: TextureView

texture_depth_cube_array view bound to the lit-pass bind group.

§point_shadow_face_views: Vec<TextureView>

One 2D-array view per face, used as the depth attachment during the shadow render pass. len() == MAX_POINT_SHADOW_LIGHTS * 6, indexed as slot * 6 + face.

§shadow_point_pipeline: RenderPipeline

Render pipeline for the point-shadow depth pass. Same vertex layout as the cascade shadow pipeline; writes linear distance-to-light.

§shadow_point_face_buf: Buffer

Per-face uniform buffer holding view_proj, light_pos, range for every (slot, face) of the point shadow array. Sized as MAX_POINT_SHADOW_LIGHTS * 6 * 256 bytes (256-byte dynamic-offset stride).

§shadow_point_face_bind_group: BindGroup

Bind group for the point-shadow per-face uniform. Stride is 256; the per-face render pass sets a dynamic offset.

§shadow_pipeline: RenderPipeline

Render pipeline for the shadow depth pass (depth-only, no fragment output).

Culls front faces, so closed solids cast shadow from their back face and a solid’s own front face is never compared against itself in the shadow map. Two-sided materials (BackfacePolicy::Identical and friends) are routed to shadow_pipeline_two_sided instead so both sides of cloth, foliage, and planar surfaces cast shadows.

§shadow_pipeline_two_sided: RenderPipeline

Shadow caster pipeline for two-sided materials. Same layout and shader as shadow_pipeline but with cull_mode: None and a larger caster-side depth bias (CSM_SHADOW_BIAS_TWO_SIDED) so both sides of a two-sided mesh rasterise into the shadow atlas without the surface self-shadowing where it is its own receiver.

§shadow_uniform_buf: Buffer

Uniform buffer holding the per-cascade light-space view-projection matrix (64 bytes).

§shadow_bind_group: BindGroup

Bind group for the shadow pass (group 0: light uniform).

§shadow_info_buf: Buffer

Uniform buffer for the ShadowAtlasUniform (binding 5 of camera_bgl, 416 bytes).

§shadow_atlas_depth_sampler: Sampler

Non-comparison sampler for reading depth values as float (atlas viewer).

§shadow_atlas_viewer_pipeline: RenderPipeline

Pipeline for the shadow atlas corner overlay.

§shadow_atlas_viewer_bg: BindGroup

Bind group for the atlas viewer (uniform + depth texture + sampler).

§shadow_atlas_viewer_buf: Buffer

Uniform buffer: NDC rect of the atlas viewer quad.

§debug_frag_sentinel_buf: Buffer

16-byte sentinel bound at group 0 binding 12 when the debug fragment buffer is inactive.

§gizmo_pipeline: RenderPipeline

Gizmo render pipeline (TriangleList, depth_compare Always : always on top).

§gizmo_vertex_buffer: Buffer

Gizmo vertex buffer (3 axis arrows, regenerated when hovered axis changes).

§gizmo_index_buffer: Buffer

Gizmo index buffer.

§gizmo_index_count: u32

Number of indices in the gizmo index buffer.

§gizmo_uniform_buf: Buffer

Gizmo uniform buffer (model matrix: positions gizmo at selected object, scaled to screen size).

§gizmo_bind_group: BindGroup

Bind group for gizmo uniform (group 1).

§overlay_pipeline: RenderPipeline

Overlay render pipeline (TriangleList with alpha blending : for semi-transparent BC quads).

§overlay_line_pipeline: RenderPipeline

Overlay wireframe pipeline (LineList, no alpha blending needed).

§grid_pipeline: RenderPipeline

Full-screen analytical grid pipeline (no vertex buffer : positions hardcoded in shader).

§grid_uniform_buf: Buffer

Uniform buffer for the grid shader (GridUniform : written every frame in prepare()).

§grid_bind_group: BindGroup

Bind group for the grid uniform (group 0, single binding).

§overlay_bind_group_layout: BindGroupLayout

Bind group layout for overlay uniforms (group 1: model + colour uniform).

§constraint_line_buffers: Vec<(Buffer, Buffer, u32, Buffer, BindGroup)>

Transient constraint guide lines, rebuilt each frame in prepare(). Each entry: (vertex_buffer, index_buffer, index_count, uniform_buffer, bind_group).

§axes_pipeline: RenderPipeline

Screen-space axes indicator pipeline (TriangleList, no depth, alpha blending).

§axes_vertex_buffer: Buffer

Vertex buffer for axes indicator geometry (rebuilt each frame).

§axes_vertex_count: u32

Number of vertices in the axes indicator buffer.

§texture_bind_group_layout: BindGroupLayout

Bind group layout for texture group (group 2: albedo + sampler + normal_map + ao_map).

§fallback_texture: GpuTexture

Fallback 1x1 white texture used when material.texture_id is None.

§ibl_irradiance_view: Option<TextureView>

IBL irradiance equirect texture view (binding 7). None until environment uploaded.

§ibl_prefiltered_view: Option<TextureView>

IBL prefiltered specular equirect texture view (binding 8). None until environment uploaded.

§ibl_brdf_lut_view: Option<TextureView>

BRDF integration LUT texture view (binding 9). None until the first upload_environment_map; cached across subsequent uploads (the LUT is scene-independent: function of roughness x N.V only).

§ibl_skybox_view: Option<TextureView>

Skybox / full-res environment equirect texture view (binding 11). None until uploaded.

§frame_upload_bytes: u64

Cumulative bytes of geometry data uploaded since the last prepare() reset.

Incremented by upload_mesh, upload_mesh_data, and replace_mesh_data. Read and reset at the start of each prepare() call to populate FrameStats::upload_bytes.

Implementations§

Source§

impl DeviceResources

Source

pub fn run_compute_filters( &mut self, device: &Device, queue: &Queue, items: &[ComputeFilterItem], ) -> Vec<ComputeFilterResult>

Dispatch GPU compute filters for all items in the list.

Returns one ComputeFilterResult per item. The renderer uses these during paint() to override the mesh’s default index buffer.

This is a synchronous v1 implementation: it submits each dispatch individually and polls the device to read back the counter. This is acceptable for v1; async readback can be added later.

Source§

impl DeviceResources

Source

pub fn create_gpu_particle_system( &mut self, device: &Device, queue: &Queue, config: &GpuParticleSystemConfig, ) -> GpuParticleSystemId

Allocate a persistent GPU particle system.

The returned GpuParticleSystemId stays valid until drop_gpu_particle_system is called or the renderer is dropped.

Source

pub fn drop_gpu_particle_system(&mut self, id: GpuParticleSystemId)

Release a particle system. The handle becomes invalid; the slot is reused on the next create_gpu_particle_system call.

Source§

impl DeviceResources

Source

pub fn new( device: &Device, target_format: TextureFormat, sample_count: u32, ) -> Self

Create all GPU resources for the viewport.

Call once at application startup. target_format must match the swap-chain surface format. Use sample_count = 1 unless the caller is providing MSAA resolve targets.

Source

pub fn new_with_cache( device: &Device, target_format: TextureFormat, sample_count: u32, pipeline_cache_data: Option<&[u8]>, ) -> Self

Like new, but seeds a wgpu::PipelineCache from previously saved data so shader compilation can be skipped on later launches.

pipeline_cache_data should come from a prior ViewportRenderer::pipeline_cache_data call, or None on first run. The cache is only created when the device enables Features::PIPELINE_CACHE; otherwise this behaves exactly like new and the data is ignored.

Source§

impl DeviceResources

Source

pub fn upload_texture( &mut self, device: &Device, queue: &Queue, width: u32, height: u32, rgba_data: &[u8], ) -> ViewportResult<TextureId>

Upload an RGBA texture to the GPU and return its texture ID.

The ID can be stored in Material::texture_id to apply the texture to objects. rgba_data must be exactly width * height * 4 bytes in RGBA8 format.

§Errors

Returns ViewportError::InvalidTextureData if the data length is incorrect.

Source

pub fn upload_normal_map( &mut self, device: &Device, queue: &Queue, width: u32, height: u32, rgba_data: &[u8], ) -> ViewportResult<TextureId>

Upload an RGBA texture as a normal map and return its texture ID.

Uses Rgba8Unorm format (not sRGB) so values are linear : required for correct normal map decoding. rgba_data must be width * height * 4 bytes.

Source

pub fn begin_upload_texture( &mut self, device: &Device, queue: &Queue, width: u32, height: u32, rgba: Vec<u8>, ) -> ViewportResult<JobId>

Start an asynchronous albedo texture upload.

Returns a JobId immediately. The texture and bind group are built on a worker thread; queue.write_texture queues the pixel copy and the runner gates the job on a fresh submission that flushes those writes. Once the status is Ready, take the resulting texture id with upload_result_texture and store it in Material::texture_id.

rgba transfers into the worker; clone at the call site to retain it. Format and binding match the synchronous upload_texture.

§Errors

Returns ViewportError::InvalidTextureData when rgba.len() != width * height * 4, reported before any job is submitted.

Source

pub fn begin_upload_normal_map( &mut self, device: &Device, queue: &Queue, width: u32, height: u32, rgba: Vec<u8>, ) -> ViewportResult<JobId>

Start an asynchronous normal-map upload.

Same shape as begin_upload_texture, but the texture is created with the linear Rgba8Unorm format and bound into the normal-map slot. Take the result with upload_result_texture once Ready.

§Errors

Same as begin_upload_texture.

Source

pub fn upload_result_texture(&mut self, id: JobId) -> ViewportResult<TextureId>

Take the texture id produced by a completed begin_upload_texture or begin_upload_normal_map job.

Returns JobNotReady while the upload is still in flight, and JobResultMissing for ids that have already been taken, were issued by a different upload type, or never existed.

Source

pub fn upload_compressed_texture( &mut self, device: &Device, queue: &Queue, desc: CompressedTextureDesc<'_>, ) -> ViewportResult<TextureId>

Upload a pre-compressed, pre-mipped texture and return its texture ID.

Sync wrapper around begin_upload_compressed_texture: see that method for the format and layout requirements. Blocks the calling thread until the upload completes.

§Errors

See begin_upload_compressed_texture.

Source

pub fn begin_upload_compressed_texture( &mut self, device: &Device, queue: &Queue, desc: CompressedTextureDesc<'_>, ) -> ViewportResult<JobId>

Start an asynchronous upload of pre-compressed, pre-mipped texture data.

Returns a JobId immediately; take the resulting texture id with upload_result_texture once the status is Ready, then store it in a Material slot. The data is validated and copied into the worker before the job is submitted.

§Errors

Returns ViewportError::UnsupportedTextureFormat when desc.format is not block-compressed or the device lacks its required feature (check first with supports_texture_format), and ViewportError::InvalidCompressedTextureData when mip_levels is empty or a level’s byte length does not match its block-packed size.

Source

pub fn texture_memory_stats(&self) -> TextureMemoryStats

Current GPU memory usage for user-uploaded textures.

Counts bytes from upload_texture, upload_normal_map, and the async upload entries. Internal resources (shadow maps, colourmaps, IBL, post-processing targets) are not included.

Source

pub fn free_texture(&mut self, id: TextureId) -> bool

Release a user-uploaded texture, reclaiming its slot and GPU memory.

Drops the GpuTexture (wgpu defers the real free until in-flight commands that reference it complete), bumps the slot generation so id no longer resolves, and evicts the cached bind groups that named the texture: the shared material_bind_groups / instance_bind_groups entries whose key contains id, and any per-mesh object bind group built against it (invalidated so the next prepare rebinds the fallback).

Returns true if a texture was released, false if id did not resolve to a live texture (already freed, never uploaded, or a stale handle). Materials still holding id are not rewritten; they fall back to the fallback texture until reassigned.

Source

pub fn replace_texture( &mut self, device: &Device, queue: &Queue, id: TextureId, width: u32, height: u32, rgba_data: &[u8], ) -> ViewportResult<()>

Replace the pixels of an already-uploaded texture in place, keeping the same TextureId.

The handle stays valid: materials and items holding id pick up the new pixels on the next frame with no reassignment. The generation check is the in-flight guard, so a stale handle (its slot freed and reused) returns StaleHandle instead of overwriting whatever now occupies the slot. Use this for content that changes over time (a streamed or animated texture) where re-uploading and reassigning a fresh id would be wasteful.

The texture is recreated as an Rgba8UnormSrgb albedo texture, matching upload_texture; rgba_data must be exactly width * height * 4 bytes. Dimensions and format need not match the original upload.

§Errors

ViewportError::InvalidTextureData if the data length is wrong, or ViewportError::StaleHandle if id does not resolve to a live texture.

Source§

impl DeviceResources

Source

pub fn upload_colourmap( &mut self, device: &Device, queue: &Queue, rgba_data: &[[u8; 4]; 256], ) -> ColourmapId

Upload a 256-sample RGBA colourmap to the GPU and return its ColourmapId.

The returned ID can be stored in SceneRenderItem::colourmap_id. Use BuiltinColourmap variants + Self::builtin_colourmap_id for the built-in presets.

Source

pub fn get_colourmap_rgba(&self, id: ColourmapId) -> Option<&[[u8; 4]; 256]>

Return the CPU-side colourmap LUT for id as 256 RGBA8 entries, or None if the id is invalid.

Useful for any non-GPU colourmap output: PDF export, table cell colouring, custom legend widgets, or sampling a colour at a specific scalar value. The data is always in memory (kept for GPU upload) so this accessor is free.

Source

pub fn builtin_colourmap_id(&self, preset: BuiltinColourmap) -> ColourmapId

Return the ColourmapId for a built-in preset.

Call Self::ensure_colourmaps_initialized first (done automatically by ViewportRenderer::prepare). Panics if colourmaps have not been initialized yet.

Source

pub fn ensure_colourmaps_initialized(&mut self, device: &Device, queue: &Queue)

Ensure built-in colourmaps are uploaded to the GPU.

Called automatically by ViewportRenderer::prepare() on the first frame. Safe to call multiple times : no-op after first invocation.

Source

pub fn upload_matcap( &mut self, device: &Device, queue: &Queue, rgba_data: &[u8], blendable: bool, ) -> ViewportResult<MatcapId>

Upload a 256x256 RGBA matcap texture and return its MatcapId.

rgba_data must be exactly 256 * 256 * 4 = 262_144 bytes. Set blendable = true for matcaps whose alpha channel tints the base geometry colour; false for static matcaps that fully replace the colour.

§Errors

Returns ViewportError::InvalidTextureData if rgba_data has the wrong length.

Source

pub fn builtin_matcap_id(&self, preset: BuiltinMatcap) -> MatcapId

Return the MatcapId for a built-in preset.

Panics if called before the renderer has run at least one prepare pass (which calls Self::ensure_matcaps_initialized automatically).

Source

pub fn ensure_matcaps_initialized(&mut self, device: &Device, queue: &Queue)

Upload the eight built-in matcaps to the GPU if not already done.

Called automatically by ViewportRenderer::prepare(). Safe to call multiple times : no-op after first invocation.

Source§

impl DeviceResources

Source

pub fn resident_bytes(&self) -> ResidentBytes

Resident GPU bytes for the user-uploaded working set: meshes, user textures, Gaussian splats, marching-cubes volumes, and pre-uploaded scivis curves.

Cheap enough to poll per frame: mesh, texture, and splat totals are running counters, and the volume / curve totals sum a handful of live entries. A streaming or eviction policy compares ResidentBytes::total against its own byte budget and calls the matching free_* to stay under it. Built-in LUTs, IBL maps, and render targets are not counted; see ResidentBytes.

Source

pub fn vram_budget(&self, device: &Device) -> Option<VramBudget>

Query the GPU’s device-local VRAM budget for device.

A thin wrapper over vram_budget so the hardware total sits next to resident_bytes: a policy sizes an eviction budget as a fraction of total_bytes and compares ResidentBytes::total against it. Returns None on backends that cannot be introspected. See VramBudget for what available_bytes reports per backend.

Source§

impl DeviceResources

Source

pub fn register_lod_group( &mut self, levels: &[MeshId], min_screen_sizes: &[f32], ) -> ViewportResult<LodGroupId>

Group meshes that are already uploaded into a LOD chain.

levels lists the meshes full detail first; min_screen_sizes gives the matching lower screen-size bound for each, as a fraction of viewport height. The thresholds must strictly decrease.

All levels must be drawable the same way: they need the same named attributes and the same deformer attachment, otherwise switching to a level would silently change or drop coloring, warp, or skinning. That is checked here so a mismatch fails at registration instead of at render time.

§Errors
Source

pub fn free_lod_group(&mut self, id: LodGroupId) -> bool

Free a LOD group and, composition-aware, its member meshes.

Removes the group from the registry and bumps its slot generation so id no longer resolves. Each member mesh is freed with free_mesh unless another still-live group also references it, in which case the shared mesh is left resident. Freeing the member meshes is the point of the call: freeing a group without it would leak every level’s GPU buffers.

Returns true if a group was freed, false if id did not resolve to a live group (already freed or a stale handle).

Source

pub fn set_lod_cull_below( &mut self, id: LodGroupId, cull_below: Option<f32>, ) -> ViewportResult<()>

Set the screen size, as a fraction of viewport height, below which objects in this group stop drawing. None disables size culling.

Applies to both SceneRenderItems and individual MeshInstanceItem instances that use the group.

§Errors

Returns ViewportError::LodGroupNotFound if id is not registered.

Source§

impl DeviceResources

Source

pub fn upload_mesh( &mut self, device: &Device, vertices: &[Vertex], indices: &[u32], ) -> ViewportResult<MeshId>

Create a GpuMesh from vertex/index slices and register it into the resource list.

Returns the MeshId of the new mesh.

§Errors

Returns ViewportError::EmptyMesh if vertices or indices is empty.

§Examples
let result = resources.upload_mesh(device, &[], &[]);
assert!(matches!(result, Err(ViewportError::EmptyMesh { .. })));
Source

pub fn upload_mesh_data( &mut self, device: &Device, data: &MeshData, ) -> ViewportResult<MeshId>

Upload a MeshData (from the geometry primitives module) directly.

Converts positions/normals/indices to the GPU Vertex layout (white colour) and creates a normal visualization line buffer (light blue #a0c4ff, length 0.1). Returns the MeshId.

§Errors

Returns ViewportError::EmptyMesh if positions or indices are empty, ViewportError::MeshLengthMismatch if positions and normals differ in length, or ViewportError::InvalidVertexIndex if an index references a nonexistent vertex.

Source

pub fn begin_upload_mesh_data( &mut self, device: &Device, data: MeshData, ) -> ViewportResult<JobId>

Start an asynchronous mesh upload.

Returns immediately with a JobId. The CPU prep (tangent computation, vertex repack, normal-line build) runs on a worker thread; GPU buffer creation and store insertion run on the main thread during the next process_uploads call after the worker finishes. Once the status is Ready, call upload_result_mesh to take the resulting MeshId.

Ownership of data transfers into the worker. To upload a mesh without giving up ownership, clone the MeshData at the call site.

§Errors

Returns the same validation errors as upload_mesh_data (empty mesh, length mismatch, invalid vertex index) before any job is submitted.

Source

pub fn upload_result_mesh(&mut self, id: JobId) -> ViewportResult<MeshId>

Take the MeshId produced by a completed begin_upload_mesh_data job.

Returns JobNotReady while the upload is still in flight, and JobResultMissing for ids that have already been taken, were issued by a different upload type, or never existed.

Source

pub fn upload_mesh_data_pickable( &mut self, device: &Device, data: &MeshData, ) -> ViewportResult<MeshId>

Upload a MeshData and retain CPU positions and indices for picking.

Equivalent to upload_mesh_data. The CPU position and index data is kept so that renderer.pick() can test FACE, EDGE, and VERTEX hits against this mesh. Use this variant to make the intent explicit at the call site.

§Errors

Same as upload_mesh_data.

Source

pub fn set_pickable(&mut self, mesh_id: MeshId, pickable: bool)

Free or retain the CPU position and index data for an already-uploaded mesh.

set_pickable(id, false) drops the retained CPU data, freeing memory. The mesh continues to render normally; it will be silently skipped for FACE, EDGE, and VERTEX picks after this call.

set_pickable(id, true) is a no-op: CPU data is either already present (the mesh was uploaded via [upload_mesh_data] or [upload_mesh_data_pickable]) or it was freed and cannot be recovered without re-uploading.

Has no effect if mesh_id is not found.

Source

pub fn write_mesh_positions_normals( &mut self, queue: &Queue, mesh_id: MeshId, positions: &[[f32; 3]], normals: &[[f32; 3]], ) -> ViewportResult<()>

Write new positions and normals into an existing mesh without reallocating GPU buffers.

The vertex count must match the original upload exactly. Use this for deforming meshes where topology is stable across frames: the index buffer, edge buffer, and bind groups are all reused. Colour, UVs, and tangents are written as defaults (white, zero, [0,0,0,1]).

The normal line visualization buffer is also updated in place if it was created at upload time.

Mutually exclusive per frame with set_position_override_buffer and set_normal_override_buffer for the same mesh: the two write paths race. A debug assertion fires if both are active. To switch from GPU-compute deformation back to CPU writes, call clear_position_override / clear_normal_override first.

§Errors

Returns ViewportError::StaleHandle if mesh_id is out of range, ViewportError::MeshLengthMismatch if positions and normals differ in length or do not match the existing vertex count.

Source

pub fn set_position_override_buffer( &mut self, mesh_id: MeshId, buffer: Buffer, ) -> ViewportResult<()>

Bind a GPU storage buffer of per-vertex positions to mesh_id. The standard mesh and skinned-mesh pipelines read positions from this buffer instead of the vertex buffer’s position attribute on every frame the binding is present.

Intended consumer: a GpuPlugin that computes deformed positions on the GPU in pre_prepare (cloth, hair, GPU particles, audio-reactive displacement). The override path sidesteps the CPU round-trip that write_mesh_positions_normals requires.

The buffer must:

  • have wgpu::BufferUsages::STORAGE,
  • hold at least 3 f32 per vertex (12 bytes each), in flat [x, y, z, x, y, z, ...] order. This matches the warp-attribute buffer layout and avoids WGSL’s 16-byte vec3 stride padding, so a consumer compute shader can write tight vec3 data directly.

The shader bounds-checks arrayLength before reading, so a smaller buffer falls back to in.position for out-of-range vertex indices.

Override and skinning compose: when both are active, the override replaces the bind-pose input and skinning is then applied on top.

Do not call this in the same frame as write_mesh_positions_normals for the same mesh; the two write paths race and the result is undefined. Pick one source for positions per frame.

§Errors

Returns ViewportError::StaleHandle if mesh_id is not registered.

Source

pub fn set_normal_override_buffer( &mut self, mesh_id: MeshId, buffer: Buffer, ) -> ViewportResult<()>

Same idea as set_position_override_buffer but for per-vertex normals (bound at group 1 binding 14).

§Errors

Returns ViewportError::StaleHandle if mesh_id is not registered.

Source

pub fn clear_position_override(&mut self, mesh_id: MeshId) -> ViewportResult<()>

Revert the position source to the mesh’s vertex buffer attribute. Drops the override buffer handle; if no other owner holds it, wgpu frees it after the in-flight frames complete.

§Errors

Returns ViewportError::StaleHandle if mesh_id is not registered.

Source

pub fn clear_normal_override(&mut self, mesh_id: MeshId) -> ViewportResult<()>

Revert the normal source to the mesh’s vertex buffer attribute.

§Errors

Returns ViewportError::StaleHandle if mesh_id is not registered.

Source

pub fn replace_mesh_data( &mut self, device: &Device, queue: &Queue, mesh_id: MeshId, data: &MeshData, ) -> ViewportResult<()>

Replace the mesh at mesh_index with new geometry data.

When the new vertex and index counts match the existing mesh and no attributes are present, the existing GPU buffers are reused and data is written in place, avoiding GPU memory allocation. When topology changes, new buffers are allocated.

This is the only slot-targeting mesh operation, so it doubles as the guard against a free racing a queued replace: the mesh_id generation is checked here (and again in MeshStore::replace), so a handle whose mesh was freed, or freed and its slot reused by a later upload, is rejected rather than overwriting the mesh now in that slot. The async upload paths need no such guard because they allocate a fresh slot at apply time.

§Errors

Returns ViewportError::StaleHandle if mesh_index is out of range or the handle is stale, or any mesh validation error from the new data.

Source

pub fn mesh(&self, id: MeshId) -> Option<&GpuMesh>

Get a reference to the mesh at the given index, or None if the slot is empty/invalid.

Source

pub fn mesh_slot_count(&self) -> usize

Total number of mesh slots (including empty/removed slots).

Source

pub fn remove_mesh(&mut self, id: MeshId) -> bool

👎Deprecated:

renamed to free_mesh

Deprecated alias for free_mesh.

Source

pub fn free_mesh(&mut self, id: MeshId) -> bool

Free a mesh, reclaiming its GPU buffers and slot.

Drops the GpuMesh (vertex, index, attribute buffers and its object bind group; wgpu defers the real free until in-flight commands complete), bumps the slot generation so id no longer resolves, and frees the slot for a later upload to reuse. A stale id held elsewhere degrades to fallback rendering rather than aliasing the reused slot.

Returns true if a mesh was freed, false if id did not resolve to a live mesh. This is the residency-facing name for remove_mesh; the two are equivalent. To free a mesh that is a member of a LOD group, free the group with free_lod_group instead so shared members are handled.

Source

pub fn upload_volume_mesh( &mut self, device: &Device, data: &VolumeMeshData, ) -> ViewportResult<VolumeMeshItem>

Upload an unstructured volume mesh and return a ready-to-submit VolumeMeshItem.

Extracts the boundary surface and uploads it through the standard mesh pipeline. Interior faces (shared by two cells) are discarded; only boundary faces (belonging to exactly one cell) are kept. Per-cell scalar and colour attributes are remapped to per-face attributes so the face-colouring path handles them automatically.

The returned item has transparency: None and projected_tet_id: None; it renders as an opaque surface mesh. Use upload_volume_mesh_with_transparency instead if you need to toggle volumetric rendering at runtime.

Source

pub fn upload_volume_mesh_with_transparency( &mut self, device: &Device, data: VolumeMeshData, scalar_attribute: &str, ) -> ViewportResult<VolumeMeshItem>

Upload an unstructured volume mesh with both the boundary surface and the projected-tet decomposition needed for volumetric rendering.

The returned item carries:

  • boundary_mesh_id + face_to_cell for the opaque surface draw and boundary-level cell picking,
  • projected_tet_id for the volumetric draw, and
  • volume_mesh_data (an Arc over the input) for interior-inclusive cell picking when transparency is on.

Default transparency: None: the item renders as a boundary surface until the host sets VolumeMeshItem::transparency to Some(VolumeTransparency { .. }). Switching modes at runtime is free because both GPU artifacts are already resident.

scalar_attribute names a key in data.cell_scalars; cells without the attribute receive scalar 0.0. The scalar range is auto-detected from the data and stored in the per-volume uniform.

Source

pub fn upload_clipped_volume_mesh( &mut self, device: &Device, data: &VolumeMeshData, clip_planes: &[[f32; 4]], ) -> ViewportResult<VolumeMeshItem>

Upload a clipped volume mesh, returning a ready-to-submit VolumeMeshItem.

Each entry in clip_planes is [nx, ny, nz, d] where a point p is kept when dot(p, [nx, ny, nz]) + d >= 0. An empty slice is equivalent to upload_volume_mesh.

The returned item has transparency: None and projected_tet_id: None.

Source

pub fn replace_clipped_volume_mesh( &mut self, device: &Device, queue: &Queue, mesh_id: MeshId, data: &VolumeMeshData, clip_planes: &[[f32; 4]], ) -> ViewportResult<Vec<u32>>

Replace an existing boundary-mesh slot with a freshly-extracted clipped volume mesh, returning the new face_to_cell map.

Equivalent to calling upload_clipped_volume_mesh and then replace_mesh_data, but without allocating a new mesh slot. Use this for per-frame clip-plane updates to avoid leaking GPU memory.

Source

pub fn replace_sparse_volume_grid_data( &mut self, device: &Device, queue: &Queue, mesh_id: MeshId, data: &SparseVolumeGridData, ) -> ViewportResult<()>

Replace a previously uploaded sparse voxel grid in place.

Equivalent to calling upload_sparse_volume_grid_data and then replace_mesh_data, but without allocating a new slot. Use this for per-frame or per-interaction updates (e.g. voxel paint) to avoid leaking GPU memory.

Source

pub fn upload_sparse_volume_grid_data( &mut self, device: &Device, data: &SparseVolumeGridData, ) -> ViewportResult<MeshId>

Upload a sparse voxel grid by extracting its boundary surface and uploading the result via upload_mesh_data.

Only quad faces not shared between two active cells are kept. Per-cell scalars and colours are remapped to per-face attributes, and per-node scalars are averaged over the 4 quad corners to produce per-face scalars.

Returns the MeshId. Reference cell and node attributes via AttributeRef { kind: AttributeKind::Face, .. }.

Source

pub fn begin_upload_volume_mesh( &mut self, device: &Device, data: VolumeMeshData, ) -> JobId

Start an asynchronous boundary-only volume mesh upload.

Returns a JobId immediately. Boundary extraction (extract_boundary_faces) and vertex prep (prep_mesh_data) run on a worker thread; the apply step creates GPU buffers and inserts the mesh. Take the resulting VolumeMeshItem via upload_result_volume_mesh.

Ownership of data transfers into the worker. The returned item has transparency: None; this async path does not produce a projected-tet decomposition. For volumetric rendering use the synchronous upload_volume_mesh_with_transparency.

Source

pub fn upload_result_volume_mesh( &mut self, id: JobId, ) -> ViewportResult<VolumeMeshItem>

Take the VolumeMeshItem produced by a completed begin_upload_volume_mesh job.

Source

pub fn begin_upload_clipped_volume_mesh( &mut self, device: &Device, data: VolumeMeshData, clip_planes: Vec<[f32; 4]>, ) -> JobId

Start an asynchronous clipped volume mesh upload. See upload_clipped_volume_mesh for the sync analog and the semantics of clip_planes.

Source

pub fn upload_result_clipped_volume_mesh( &mut self, id: JobId, ) -> ViewportResult<VolumeMeshItem>

Take the VolumeMeshItem produced by a completed begin_upload_clipped_volume_mesh job.

Source

pub fn begin_upload_sparse_volume_grid_data( &mut self, device: &Device, data: SparseVolumeGridData, ) -> JobId

Start an asynchronous sparse voxel grid upload.

Source

pub fn upload_result_sparse_volume_grid( &mut self, id: JobId, ) -> ViewportResult<MeshId>

Take the MeshId produced by a completed begin_upload_sparse_volume_grid_data job.

Source

pub fn replace_projected_tet( &mut self, device: &Device, id: ProjectedTetId, data: &VolumeMeshData, scalar_attribute: &str, ) -> ViewportResult<()>

Replace the tet buffer of an existing projected-tet mesh in-place.

Rebuilds the tet storage buffer (and its bind group) from the new scalar attribute. The uniform buffer (density, thresholds, opacity) is reused; only the cached scalar range is refreshed. Changing the colourmap on the owning item is now free because the LUT is bound per-frame in render.rs, so this call no longer takes a colourmap_id.

Source§

impl DeviceResources

Source

pub fn replace_attribute( &mut self, queue: &Queue, mesh_id: MeshId, name: &str, data: &[f32], ) -> ViewportResult<()>

Write new scalar data into an existing attribute buffer in-place.

No GPU buffer reallocation, no mesh re-upload, no bind group rebuild is required. The attribute bind group will be rebuilt on the next prepare() call if the scalar range changes (tracked via last_tex_key).

§Errors
Source§

impl DeviceResources

Source

pub fn set_deform_time(&mut self, queue: &Queue, time_seconds: f32)

Write the shared header uniform’s time_seconds field. Cheap; safe to call per frame.

Source

pub fn set_deform_slot_params( &mut self, queue: &Queue, slot: usize, params: [[f32; 4]; 4], )

Write the four vec4<f32> parameter words for one slot in the shared header uniform.

Source

pub fn attach_deform_slot( &mut self, device: &Device, mesh_id: MeshId, slot: usize, stride_bytes: u32, data: &[u8], )

Attach raw bytes for one deformer slot on the given mesh.

stride_bytes is the per-vertex byte stride and must equal the registered deformer’s per_vertex_stride. The data length is expected to be vertex_count * stride_bytes; the renderer does not validate the vertex count, only that the byte length is a multiple of stride_bytes and 4.

Source

pub fn detach_deform_slot( &mut self, device: &Device, mesh_id: MeshId, slot: usize, ) -> bool

Detach a per-mesh slot’s data. Returns true if any data was removed.

Source

pub fn has_deform_slot(&self, mesh_id: MeshId, slot: usize) -> bool

Returns true when the mesh has per-mesh data attached at the given slot.

Source

pub fn attach_deform_slot_instance( &mut self, device: &Device, queue: &Queue, mesh_id: MeshId, instance_id: u32, slot: usize, stride_bytes: u32, data: &[u8], )

Attach raw bytes for one deformer slot on a single instance of the given mesh. Used for data that varies per instance (e.g. joint palettes). stride_bytes is the per-element byte stride; the data length must be a multiple of stride_bytes and 4.

Source

pub fn detach_deform_slot_instance( &mut self, device: &Device, queue: &Queue, mesh_id: MeshId, instance_id: u32, slot: usize, ) -> bool

Detach a per-instance slot’s data. Returns true if any data was removed.

Source

pub fn has_deform_slot_instance( &self, mesh_id: MeshId, instance_id: u32, slot: usize, ) -> bool

Returns true when the given instance of the mesh has per-instance data attached at the given slot.

Source

pub fn register_deformer( &mut self, device: &Device, desc: DeformerDesc, ) -> ViewportResult<DeformerId>

Register a deformer against the mesh shader family.

Validates the descriptor’s name and allocates a slot, composes every mesh-family base shader with the new deformer plus all previously registered ones, and runs each composed module through wgpu’s validator. On success, the LDR and HDR mesh.wgsl pipelines are rebuilt from the freshly composed source so subsequent draws run the registered body. Other mesh-family pipelines (instanced, shadow, outline mask, OIT) continue to run the identity path until their factories migrate to the same rebuild path.

On any validation failure the registration is rolled back: the previously composed sources stay live and the returned error names the shader that failed.

§Errors
Source

pub fn registered_deformer_count(&self) -> usize

Number of currently registered deformers (host + internal).

Source

pub fn deformer_id_by_name(&self, name: &str) -> Option<DeformerId>

Look up a registered deformer’s id by its name. Returns None when no deformer with that name has been registered.

Source

pub fn deform_slot_handle(&self, id: DeformerId) -> DeformSlotHandle

Build a DeformSlotHandle for the given deformer. Plugins stash the handle at registration time and use it to write that slot’s slot_params block from contexts (e.g. a GpuPlugin::pre_prepare) that only carry &wgpu::Queue.

Source§

impl DeviceResources

Source

pub fn upload_font(&mut self, ttf_bytes: &[u8]) -> Result<FontHandle, FontError>

Upload a user-supplied TTF font for use with overlay items.

Returns an opaque FontHandle that can be passed to [LabelItem], [ScalarBarItem], or [RulerItem] via their font field. Pass None on those items to use the built-in default font instead.

The font bytes must be a valid TrueType (.ttf) file.

Source§

impl DeviceResources

Source

pub fn upload_overlay_texture( &mut self, device: &Device, queue: &Queue, width: u32, height: u32, rgba_data: &[u8], ) -> OverlayTextureId

Upload RGBA8 pixel data as a persistent texture for overlay shape fills.

Returns an OverlayTextureId that can be stored in OverlayShapeItem::texture. The texture persists for the lifetime of this DeviceResources.

rgba_data must contain exactly width * height * 4 bytes in row-major, top-to-bottom order. The data is treated as sRGB-encoded (standard 8-bit image data).

Source

pub fn begin_upload_overlay_texture( &mut self, device: &Device, queue: &Queue, width: u32, height: u32, rgba_data: Vec<u8>, ) -> ViewportResult<JobId>

Start an asynchronous overlay texture upload.

Returns a JobId immediately. Texture creation and queue.write_texture run on a worker thread on cloned Device and Queue handles; the apply step inserts the prepared OverlayShapeTextureEntry into the store. Take the resulting OverlayTextureId via upload_result_overlay_texture.

Ownership of rgba_data transfers into the worker.

§Errors

Returns ViewportError::InvalidTextureData before submission when rgba_data.len() != width * height * 4.

Source

pub fn upload_result_overlay_texture( &mut self, id: JobId, ) -> ViewportResult<OverlayTextureId>

Take the OverlayTextureId produced by a completed begin_upload_overlay_texture job.

Source§

impl DeviceResources

Source

pub fn update_gizmo_mesh( &mut self, device: &Device, queue: &Queue, mode: GizmoMode, hovered: GizmoAxis, space_orientation: Quat, )

Re-upload the gizmo mesh with updated hover highlight colours.

Called each frame when the hovered axis changes to brighten the appropriate axis colour. The gizmo mesh is small (~300 vertices), so re-uploading every frame is acceptable.

Source

pub fn update_gizmo_uniform(&self, queue: &Queue, model: Mat4)

Update the gizmo model matrix uniform (translation to gizmo center + scale for screen size).

Source

pub fn create_constraint_overlay( &self, device: &Device, overlay: &ConstraintOverlay, ) -> (Buffer, Buffer, u32, Buffer, BindGroup)

Create a line-list overlay for an active transform constraint.

Source§

impl DeviceResources

Source

pub fn shared_bindings(&self) -> SharedBindings<'_>

Group-0 bind layout shared by every scene pipeline. Use as group 0 when building a plugin pipeline layout.

Source

pub fn opaque_target_desc(&self) -> OpaqueTargetDesc

Render-target descriptor for the HDR opaque scene pass.

Source

pub fn oit_target_desc(&self) -> OitTargetDesc

Render-target descriptor for the OIT pass (MRT: accum + reveal).

Source

pub fn mask_target_desc(&self) -> MaskTargetDesc

Render-target descriptor for the outline-mask pass.

Source

pub fn pick_target_desc(&self) -> PickTargetDesc

Render-target descriptor for the pick-id pass.

Source

pub fn shadow_target_desc(&self) -> ShadowTargetDesc

Render-target descriptor for the shadow-atlas pass.

Source

pub fn texture_view(&self, id: TextureId) -> Option<&TextureView>

Borrow the TextureView for a texture previously uploaded via upload_texture or upload_normal_map.

Returns None if id does not refer to a live texture (a stale handle whose texture was freed, or one out of range).

Lifetime contract: the returned view is valid until the texture is freed with free_texture. Plugins that build a bind group from this view must rebuild it after any operation that could invalidate the texture (a free, device recreation). A safer pattern is to fetch the view each frame just before building / rebuilding the bind group.

Source

pub fn texture_sampler(&self, id: TextureId) -> Option<&Sampler>

Borrow the sampler the texture was uploaded with.

Most user textures are uploaded with a shared linear-repeat sampler; prefer material_sampler when you need the shared lib sampler rather than the per-texture instance.

Source

pub fn material_sampler(&self) -> &Sampler

Shared linear-repeat sampler used by the lib’s material pipelines.

Use this when building a plugin bind group that samples user textures the same way Material does (linear filter, repeat wrap).

Source

pub fn lut_sampler(&self) -> &Sampler

Shared linear-clamp sampler used by the lib for colormap LUTs.

Use this when sampling 1D LUT-style data (colourmaps, transfer functions) where the texture should not wrap.

Source

pub fn shadow_filter_sampler(&self) -> &Sampler

Comparison sampler used for PCF shadow filtering.

Plugins that sample the shadow atlas directly (rather than through viewport_sample_csm) use this sampler when binding the atlas.

Source

pub fn deform_bind_group_layout(&self) -> &BindGroupLayout

Bind group layout for the per-vertex deformation sidecar.

Plugins building pipelines that draw meshes with registered deformers add this layout at group 2 so their vertex stage can read from the shared deform_data / deform_instance_data storage buffers.

Source

pub fn texture_count(&self) -> usize

Number of live user-uploaded textures.

id values in 0..texture_count() are addressable via texture_view, with the caveat that promoted IDs from async uploads may sit at the high end.

Source

pub fn build_opaque_pipeline( &self, device: &Device, opts: &PluginPipelineOpts<'_>, ) -> RenderPipeline

Build an opaque scene pipeline that draws into the HDR scene pass.

Standard depth state: LessEqual test, depth write on. The pipeline layout lists shared_bindings as group 0, then extra_bind_group_layouts as groups 1.., in order. The plugin owns all groups past 0.

Source

pub fn build_oit_pipeline( &self, device: &Device, opts: &PluginPipelineOpts<'_>, ) -> RenderPipeline

Build a transparent pipeline that draws into the OIT pass.

The fragment shader must return OitOutput, writing both @location(0) (accum) and @location(1) (reveal). Depth state: LessEqual test, depth write off.

Source

pub fn build_mask_pipeline( &self, device: &Device, opts: &PluginPipelineOpts<'_>, ) -> RenderPipeline

Build a pipeline for the outline-mask pass (R8 target).

Fragment shader must write 1.0 at @location(0) for any covered pixel; use SHARED_MASK_WGSL. Depth state: LessEqual test, no depth write.

Source

pub fn build_pick_pipeline( &self, device: &Device, opts: &PluginPipelineOpts<'_>, ) -> RenderPipeline

Build a pipeline for the pick-id pass (R32Uint target).

Fragment shader must write the item’s PickId value at @location(0); use SHARED_PICK_WGSL.

Source

pub fn build_shadow_pipeline( &self, device: &Device, opts: &PluginPipelineOpts<'_>, ) -> RenderPipeline

Build a depth-only pipeline for the shadow-atlas pass.

No fragment output. The fragment entry is optional; pass an empty string to use a depth-only configuration with no fragment stage. Standard depth state: LessEqual test, depth write on, with the lib’s standard depth bias.

Source§

impl DeviceResources

Source

pub fn upload_gaussian_splat( &mut self, device: &Device, queue: &Queue, data: &GaussianSplatData, ) -> ViewportResult<GaussianSplatId>

Upload one Gaussian splat set to the GPU and return its handle.

Call once per splat set at startup (or when the set changes). The returned [GaussianSplatId] is stable until [free_gaussian_splat] is called.

§Errors

Returns ViewportError::InvalidGaussianSplatData if data.positions is empty or if the lengths of positions, scales, rotations, and opacities do not all match.

§Examples
let result = renderer.upload_gaussian_splat(device, queue, &GaussianSplatData::default());
assert!(matches!(result, Err(ViewportError::InvalidGaussianSplatData { .. })));
Source

pub fn replace_gaussian_splat( &mut self, device: &Device, queue: &Queue, id: GaussianSplatId, data: &GaussianSplatData, ) -> ViewportResult<()>

Replace the contents of an uploaded Gaussian splat set in place, keeping the same GaussianSplatId.

Items holding the handle pick up the new splats on the next frame with no reassignment. The generation check is the in-flight guard: a stale handle (its slot freed and reused) returns StaleHandle instead of overwriting whatever now occupies the slot. Use this for content that changes over time (a re-trained or streamed splat set).

§Errors

InvalidGaussianSplatData when data is empty or its per-attribute vectors disagree in length, or StaleHandle if id does not resolve to a live set.

Source

pub fn free_gaussian_splat(&mut self, id: GaussianSplatId)

Remove an uploaded Gaussian splat set by handle.

Source

pub fn begin_upload_gaussian_splat( &mut self, device: &Device, queue: &Queue, data: GaussianSplatData, ) -> ViewportResult<JobId>

Start an asynchronous Gaussian splat upload.

Returns a JobId immediately. Vec4 padding for positions / scales / rotations and storage buffer creation + writes all run on a worker thread on a cloned Device and Queue. The apply step inserts the prepared GaussianSplatGpuSet into the store and surfaces the resulting [GaussianSplatId].

§Errors

Returns [ViewportError::InvalidGaussianSplatData] before any job is submitted when data.positions is empty or the per-attribute vectors disagree in length.

Source

pub fn upload_result_gaussian_splat( &mut self, id: JobId, ) -> ViewportResult<GaussianSplatId>

Take the GaussianSplatId produced by a completed begin_upload_gaussian_splat job.

Source§

impl DeviceResources

Source

pub fn upload_glyph_set( &mut self, device: &Device, queue: &Queue, item: &GlyphItem, ) -> GlyphSetId

Pre-upload a glyph set and return a typed handle.

Source

pub fn drop_glyph_set(&mut self, id: GlyphSetId) -> bool

Remove a pre-uploaded glyph set.

Source

pub fn replace_glyph_set( &mut self, device: &Device, queue: &Queue, id: GlyphSetId, item: &GlyphItem, ) -> bool

Replace the geometry of a pre-uploaded glyph set, keeping the same id.

Source

pub fn begin_upload_glyph_set( &mut self, device: &Device, queue: &Queue, item: GlyphItem, ) -> JobId

Start an asynchronous glyph set upload.

Source

pub fn upload_result_glyph_set( &mut self, id: JobId, ) -> ViewportResult<GlyphSetId>

Take the GlyphSetId produced by a completed begin_upload_glyph_set job.

Source

pub fn upload_tensor_glyph_set( &mut self, device: &Device, queue: &Queue, item: &TensorGlyphItem, ) -> TensorGlyphSetId

Pre-upload a tensor glyph set and return a typed handle.

Source

pub fn drop_tensor_glyph_set(&mut self, id: TensorGlyphSetId) -> bool

Remove a pre-uploaded tensor glyph set.

Source

pub fn replace_tensor_glyph_set( &mut self, device: &Device, queue: &Queue, id: TensorGlyphSetId, item: &TensorGlyphItem, ) -> bool

Replace the geometry of a pre-uploaded tensor glyph set, keeping the same id.

Source

pub fn begin_upload_tensor_glyph_set( &mut self, device: &Device, queue: &Queue, item: TensorGlyphItem, ) -> JobId

Start an asynchronous tensor glyph set upload.

Source

pub fn upload_result_tensor_glyph_set( &mut self, id: JobId, ) -> ViewportResult<TensorGlyphSetId>

Take the TensorGlyphSetId produced by a completed begin_upload_tensor_glyph_set job.

Source§

impl DeviceResources

Source

pub fn upload_point_cloud( &mut self, device: &Device, queue: &Queue, item: &PointCloudItem, ) -> PointCloudId

Pre-upload a point cloud and return a typed handle.

Source

pub fn drop_point_cloud(&mut self, id: PointCloudId) -> bool

Remove a pre-uploaded point cloud.

Source

pub fn replace_point_cloud( &mut self, device: &Device, queue: &Queue, id: PointCloudId, item: &PointCloudItem, ) -> bool

Replace the geometry of a pre-uploaded point cloud, keeping the same id.

Source

pub fn begin_upload_point_cloud( &mut self, device: &Device, queue: &Queue, item: PointCloudItem, ) -> JobId

Start an asynchronous point cloud upload.

Source

pub fn upload_result_point_cloud( &mut self, id: JobId, ) -> ViewportResult<PointCloudId>

Take the PointCloudId produced by a completed begin_upload_point_cloud job.

Source§

impl DeviceResources

Source

pub fn upload_polyline( &mut self, device: &Device, queue: &Queue, item: &PolylineItem, ) -> PolylineId

Pre-upload a polyline and return a typed handle.

The returned PolylineId refers to GPU buffers retained by the renderer until [drop_polyline] is called. Submit a PolylineRefItem on SceneFrame::polyline_refs each frame to draw the polyline at a custom model transform without rebuilding its segment buffer.

The viewport size used for screen-space miter calculations is set from the most recent ref-item draw of this polyline. Stationary callers can rely on it being correct after the first frame.

Source

pub fn drop_polyline(&mut self, id: PolylineId) -> bool

Remove a pre-uploaded polyline. Returns true if a polyline was actually removed, false if the id was already invalid.

Source

pub fn replace_polyline( &mut self, device: &Device, queue: &Queue, id: PolylineId, item: &PolylineItem, ) -> bool

Replace the geometry of a pre-uploaded polyline, keeping the same PolylineId.

Returns true if the id was valid and the polyline was replaced, false if the slot was empty (call upload_polyline instead).

Source

pub fn begin_upload_polyline( &mut self, device: &Device, queue: &Queue, item: PolylineItem, ) -> JobId

Start an asynchronous polyline upload.

Returns a JobId immediately. The upload runs during the next process_uploads call (driven by prepare_scene); once the status is Ready, call upload_result_polyline to take the resulting handle.

Ownership of item transfers into the worker.

Source

pub fn upload_result_polyline( &mut self, id: JobId, ) -> ViewportResult<PolylineId>

Take the PolylineId produced by a completed begin_upload_polyline job.

Source§

impl DeviceResources

Source

pub fn upload_sprite_set( &mut self, device: &Device, queue: &Queue, item: &SpriteItem, ) -> SpriteSetId

Pre-upload a static sprite set and return a typed handle.

Use this for sprites whose positions, sizes, and colours never change between frames: foliage, signage, light flares. Submit a SpriteSetRefItem on SceneFrame::sprite_set_refs each frame to draw the set.

Source

pub fn drop_sprite_set(&mut self, id: SpriteSetId) -> bool

Remove a pre-uploaded sprite set.

Source

pub fn replace_sprite_set( &mut self, device: &Device, queue: &Queue, id: SpriteSetId, item: &SpriteItem, ) -> bool

Replace the contents of a pre-uploaded sprite set, keeping the same id.

Source

pub fn begin_upload_sprite_set( &mut self, device: &Device, queue: &Queue, item: SpriteItem, ) -> JobId

Start an asynchronous sprite set upload.

Source

pub fn upload_result_sprite_set( &mut self, id: JobId, ) -> ViewportResult<SpriteSetId>

Take the SpriteSetId produced by a completed begin_upload_sprite_set job.

Source

pub fn upload_sprite_instance_set( &mut self, device: &Device, queue: &Queue, item: &SpriteItem, ) -> SpriteInstanceSetId

Pre-upload a sprite instance set and return a typed handle.

Use this for sprites whose definition (texture, blend, size mode) is stable but whose instance transforms change every frame: NPCs, item drops, damage numbers. Submit a SpriteInstanceSetRefItem on SceneFrame::sprite_instance_set_refs each frame.

The current implementation pre-bakes both the definition and the instance transforms; full per-frame instance transform override against a stable definition is a planned follow-up.

Source

pub fn drop_sprite_instance_set(&mut self, id: SpriteInstanceSetId) -> bool

Remove a pre-uploaded sprite instance set.

Source

pub fn replace_sprite_instance_set( &mut self, device: &Device, queue: &Queue, id: SpriteInstanceSetId, item: &SpriteItem, ) -> bool

Replace the contents of a pre-uploaded sprite instance set, keeping the same id.

Source

pub fn begin_upload_sprite_instance_set( &mut self, device: &Device, queue: &Queue, item: SpriteItem, ) -> JobId

Start an asynchronous sprite instance set upload.

Source

pub fn upload_result_sprite_instance_set( &mut self, id: JobId, ) -> ViewportResult<SpriteInstanceSetId>

Take the SpriteInstanceSetId produced by a completed begin_upload_sprite_instance_set job.

Source§

impl DeviceResources

Source

pub fn upload_streamtube( &mut self, device: &Device, queue: &Queue, item: &StreamtubeItem, ) -> StreamtubeId

Pre-upload a streamtube and return a typed handle.

Submit a StreamtubeRefItem on SceneFrame::streamtube_refs each frame to draw the tube at a per-frame model transform without rebuilding its mesh.

Source

pub fn drop_streamtube(&mut self, id: StreamtubeId) -> bool

Remove a pre-uploaded streamtube.

Source

pub fn replace_streamtube( &mut self, device: &Device, queue: &Queue, id: StreamtubeId, item: &StreamtubeItem, ) -> bool

Replace the geometry of a pre-uploaded streamtube, keeping the same id.

Source

pub fn upload_tube( &mut self, device: &Device, queue: &Queue, item: &TubeItem, ) -> TubeId

Pre-upload a general tube and return a typed handle.

Source

pub fn drop_tube(&mut self, id: TubeId) -> bool

Remove a pre-uploaded tube.

Source

pub fn replace_tube( &mut self, device: &Device, queue: &Queue, id: TubeId, item: &TubeItem, ) -> bool

Replace the geometry of a pre-uploaded tube, keeping the same id.

Source

pub fn upload_ribbon( &mut self, device: &Device, queue: &Queue, item: &RibbonItem, ) -> RibbonId

Pre-upload a ribbon and return a typed handle.

Source

pub fn drop_ribbon(&mut self, id: RibbonId) -> bool

Remove a pre-uploaded ribbon.

Source

pub fn replace_ribbon( &mut self, device: &Device, queue: &Queue, id: RibbonId, item: &RibbonItem, ) -> bool

Replace the geometry of a pre-uploaded ribbon, keeping the same id.

Source

pub fn begin_upload_streamtube( &mut self, device: &Device, queue: &Queue, item: StreamtubeItem, ) -> JobId

Start an asynchronous streamtube upload.

Source

pub fn upload_result_streamtube( &mut self, id: JobId, ) -> ViewportResult<StreamtubeId>

Take the StreamtubeId produced by a completed begin_upload_streamtube job.

Source

pub fn begin_upload_tube( &mut self, device: &Device, queue: &Queue, item: TubeItem, ) -> JobId

Start an asynchronous tube upload.

Source

pub fn upload_result_tube(&mut self, id: JobId) -> ViewportResult<TubeId>

Take the TubeId produced by a completed begin_upload_tube job.

Source

pub fn begin_upload_ribbon( &mut self, device: &Device, queue: &Queue, item: RibbonItem, ) -> JobId

Start an asynchronous ribbon upload.

Source

pub fn upload_result_ribbon(&mut self, id: JobId) -> ViewportResult<RibbonId>

Take the RibbonId produced by a completed begin_upload_ribbon job.

Source§

impl DeviceResources

Source

pub fn process_uploads(&mut self, device: &Device, queue: &Queue)

Advance the upload-job runner. Worker results received since the previous call are observed, GPU submissions are polled, completed jobs are folded into renderer state, and any completion callbacks fire on the caller’s thread.

Apply closures and callbacks both run after the runner’s mutex is released, so they are free to query the runner or submit a fresh job without risk of deadlock.

Source

pub fn process_uploads_with_budget( &mut self, device: &Device, queue: &Queue, budget: FrameBudget, )

Advance the upload-job runner with a cap on per-call apply-step work.

Behaves the same as process_uploads except that, after the runner has been advanced and any failure callbacks fired, the caller stops popping apply closures off the queue once budget elapses. Remaining apply closures stay on the queue and are picked up by the next call. Their owning jobs continue to report UploadStatus::Pending until their apply runs, so the typed result is never observably available before it is in place.

The budget covers only the main-thread apply work and the preceding device poll. Worker-thread time is independent. The check happens between applies, so a single long-running apply may push past the deadline once it has started; the budget is a soft cap, not a hard deadline.

Source

pub fn job_duration(&self, id: JobId) -> Option<Duration>

Total wall-clock work duration for a completed job.

The value is the sum of the worker thread’s elapsed time and the main-thread apply-step elapsed time. It excludes frame-pacing delays (the time the apply step sat waiting for process_uploads to be called). For sync uploads this method returns None; sync callers measure their own wall-clock around the call.

Returns None for jobs that are still in flight, were never issued, or whose duration record has already been dropped via drop_job_duration. The runner retains durations until the consumer drops them so single-frame retention is not enough.

Source

pub fn drop_job_duration(&mut self, id: JobId)

Drop the recorded duration for id. Call this after reading the value via job_duration; otherwise the duration table grows over time.

Source

pub fn upload_status(&self, id: JobId) -> UploadStatus

Look up the current state of a submitted upload job.

Source

pub fn uploads_pending(&self) -> usize

Number of upload jobs still in flight.

Source

pub fn all_uploads_complete(&self) -> bool

True when no upload jobs are in flight.

Source

pub fn on_upload_complete<F>(&mut self, id: JobId, cb: F)
where F: FnOnce(&UploadStatus) + Send + 'static,

Register a callback to fire when a job finishes. The callback runs on the caller’s thread during the next process_uploads call. If the job has already finished and is still in the short retention window, the callback fires immediately on the calling thread.

Source

pub fn drain_until( &mut self, device: &Device, queue: &Queue, id: JobId, ) -> ViewportResult<()>

Block the calling thread, driving process_uploads until id reaches a terminal state.

Returns Ok(()) when the job’s worker (and any GPU submission it queued) completes successfully. Returns the worker error when the job fails. Used internally by the synchronous upload_* entries to wrap their begin_upload_* counterparts in a single round-trip; consumers who want to wait on a specific async upload can call it directly.

The loop sleeps for a short interval between polls so it does not pin a CPU core while the worker is running. It does not call back into the caller’s event loop; if you have other work to interleave, drive process_uploads yourself instead.

§Errors

Returns ViewportError::JobResultMissing if id has already been reaped or was never issued, and the worker’s error verbatim when the job ends in Failed.

Source§

impl DeviceResources

Source

pub fn upload_volume_for_mc( &mut self, device: &Device, queue: &Queue, vol: &VolumeData, ) -> ViewportResult<McVolumeId>

Upload a VolumeData to GPU, pre-allocating all intermediate and output buffers for GPU marching cubes.

The returned McVolumeId is stable until [free_mc_volume] is called.

Returns Err(ViewportError::McBufferTooLarge) if any required buffer exceeds the device’s max_buffer_size; the caller should fall back to CPU isosurface extraction.

Source§

impl DeviceResources

Source

pub fn begin_upload_volume_for_mc( &mut self, device: &Device, queue: &Queue, vol: VolumeData, ) -> JobId

Start an asynchronous marching-cubes-ready volume upload.

Returns a JobId immediately. Slab sizing, scalar buffer allocation, and intermediate / output buffer allocation run on a worker thread on cloned Device and Queue handles. The apply step inserts the resulting GPU buffers into the MC volume store; once UploadStatus::Ready, call upload_result_volume_mc to take the McVolumeId.

Ownership of vol transfers into the worker.

§Errors

The worker surfaces ViewportError::McBufferTooLarge through [UploadStatus::Failed] when the device’s max_storage_buffer_binding_size cannot fit a single Z-cell layer.

Source

pub fn upload_result_volume_mc( &mut self, id: JobId, ) -> ViewportResult<McVolumeId>

Take the McVolumeId produced by a completed begin_upload_volume_for_mc job.

Source

pub fn free_mc_volume(&mut self, id: McVolumeId)

Free a MC volume: drop its slab GPU buffers to reclaim the memory now, mark the slot free, and bump its generation so a stale handle no longer resolves. The emptied slot is reused by a later upload. Dropping the buffers drops this volume out of resident_bytes immediately (wgpu defers the real GPU free until in-flight commands that reference the buffers complete).

Source§

impl DeviceResources

Source

pub fn upload_volume( &mut self, device: &Device, queue: &Queue, data: &[f32], dims: [u32; 3], ) -> VolumeId

Upload a 3D scalar field to the GPU as an R32Float 3D texture.

data must be a flat array of dims[0] * dims[1] * dims[2] scalars in x-fastest order (index = x + ynx + znx*ny).

Returns a VolumeId that can be stored in VolumeItem::volume_id.

Source

pub fn begin_upload_volume( &mut self, device: &Device, queue: &Queue, data: Vec<f32>, dims: [u32; 3], ) -> ViewportResult<JobId>

Start an asynchronous volume upload.

Returns a JobId immediately. The 3D texture creation and queue.write_texture run on a worker thread on cloned Device and Queue handles; once the job reports UploadStatus::Ready, call upload_result_volume to take the resulting VolumeId.

Ownership of data transfers into the worker.

§Errors

Returns ViewportError::VolumeDataLengthMismatch if data.len() != dims[0] * dims[1] * dims[2] before any job is submitted.

Source

pub fn upload_result_volume(&mut self, id: JobId) -> ViewportResult<VolumeId>

Take the VolumeId produced by a completed begin_upload_volume job.

Returns JobNotReady while the upload is still in flight, and JobResultMissing for ids that have already been taken, were issued by a different upload type, or never existed.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Send + Sync>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more