Skip to main content

FrameContext

Struct FrameContext 

Source
pub struct FrameContext { /* private fields */ }
Expand description

Context for a single frame of rendering.

When a GpuFrameProfiler is attached (via [RenderableWindow::set_gpu_profiler]), GPU profiling scopes are automatically created around render passes in with_pass and clear_and_render. Queries are resolved and the profiler frame is ended in the Drop implementation.

Implementations§

Source§

impl FrameContext

Source

pub fn compute_pass<'a>(&'a mut self, label: &'a str) -> ComputePass<'a>

Create a compute pass with a label.

Source

pub fn compute_pass_unlabeled(&mut self) -> ComputePass<'_>

Create a compute pass without a label.

Source§

impl FrameContext

Source

pub fn surface(&self) -> &Surface

Get the surface for this frame.

§Panics

Panics if the surface has already been consumed. Use try_surface() for fallible access.

Source

pub fn try_surface(&self) -> Option<&Surface>

Try to get the surface for this frame.

Returns None if the surface has already been consumed.

Source

pub fn has_surface(&self) -> bool

Check if the surface is available.

Source

pub fn surface_format(&self) -> TextureFormat

Source

pub fn increment_passes(&mut self)

Source

pub fn increment_draw_calls(&mut self)

Source

pub fn stats(&self) -> &FrameStats

Source

pub fn graphics_context(&self) -> &GraphicsContext

Source

pub fn graphics_context_arc(&self) -> &Arc<GraphicsContext>

Get a cloneable Arc reference to the graphics context.

Source

pub fn encoder(&mut self) -> &mut CommandEncoder

Get the command encoder for this frame.

§Panics

Panics if the encoder has already been taken. Use try_encoder() for fallible access.

Source

pub fn try_encoder(&mut self) -> Option<&mut CommandEncoder>

Try to get the command encoder for this frame.

Returns None if the encoder has already been taken.

Source

pub fn has_encoder(&self) -> bool

Check if the encoder is available.

Source

pub fn encoder_and_surface(&mut self) -> (&mut CommandEncoder, &Surface)

Get the encoder and surface together.

§Panics

Panics if either the encoder or surface has been consumed. Use try_encoder_and_surface() for fallible access.

Source

pub fn try_encoder_and_surface( &mut self, ) -> Option<(&mut CommandEncoder, &Surface)>

Try to get the encoder and surface together.

Returns None if either has been consumed.

Source

pub fn encoder_ref(&self) -> Option<&CommandEncoder>

Get direct access to the command encoder (immutable).

Source

pub fn encoder_mut(&mut self) -> Option<&mut CommandEncoder>

Get mutable access to the command encoder.

Source

pub fn surface_view(&self) -> &TextureView

Get the surface texture view for this frame.

§Panics

Panics if the surface has been consumed. Use try_surface_view() for fallible access.

Source

pub fn try_surface_view(&self) -> Option<&TextureView>

Try to get the surface texture view for this frame.

Source

pub fn surface_texture(&self) -> &Texture

Get the surface texture for this frame.

§Panics

Panics if the surface has been consumed. Use try_surface_texture() for fallible access.

Source

pub fn try_surface_texture(&self) -> Option<&Texture>

Try to get the surface texture for this frame.

Source

pub fn finish(self)

Examples found in repository?
examples/camera_demo.rs (line 111)
91    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
92        if window_id != self.window_id {
93            return;
94        }
95
96        events.dispatch(|event| {
97            if let astrelis_winit::event::Event::WindowResized(size) = event {
98                self.window.resized(*size);
99                astrelis_winit::event::HandleStatus::consumed()
100            } else {
101                astrelis_winit::event::HandleStatus::ignored()
102            }
103        });
104
105        let mut frame = self.window.begin_drawing();
106        frame.clear_and_render(
107            RenderTarget::Surface,
108            Color::from_rgb_u8(20, 30, 40),
109            |_pass| {},
110        );
111        frame.finish();
112    }
More examples
Hide additional examples
examples/mesh_primitives.rs (line 113)
93    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
94        if window_id != self.window_id {
95            return;
96        }
97
98        events.dispatch(|event| {
99            if let astrelis_winit::event::Event::WindowResized(size) = event {
100                self.window.resized(*size);
101                astrelis_winit::event::HandleStatus::consumed()
102            } else {
103                astrelis_winit::event::HandleStatus::ignored()
104            }
105        });
106
107        let mut frame = self.window.begin_drawing();
108        frame.clear_and_render(
109            RenderTarget::Surface,
110            Color::from_rgb_u8(20, 30, 40),
111            |_pass| {},
112        );
113        frame.finish();
114    }
examples/render_graph_demo.rs (line 111)
91    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
92        if window_id != self.window_id {
93            return;
94        }
95
96        events.dispatch(|event| {
97            if let astrelis_winit::event::Event::WindowResized(size) = event {
98                self.window.resized(*size);
99                astrelis_winit::event::HandleStatus::consumed()
100            } else {
101                astrelis_winit::event::HandleStatus::ignored()
102            }
103        });
104
105        let mut frame = self.window.begin_drawing();
106        frame.clear_and_render(
107            RenderTarget::Surface,
108            Color::from_rgb_u8(20, 30, 40),
109            |_pass| {},
110        );
111        frame.finish();
112    }
examples/window_manager_demo.rs (line 108)
86    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
87        // Get the color for this window
88        let Some(&color) = self.window_colors.get(&window_id) else {
89            return;
90        };
91
92        // WindowManager automatically handles:
93        // 1. Window lookup (no manual HashMap.get_mut)
94        // 2. Resize events (automatic)
95        // 3. Event dispatching
96        self.window_manager
97            .render_window(window_id, events, |window, _events| {
98                // No need to manually handle resize events!
99                // WindowManager already did that for us
100
101                // Just render!
102                let mut frame = window.begin_drawing();
103
104                frame.clear_and_render(RenderTarget::Surface, color, |_pass| {
105                    // Additional rendering would go here
106                });
107
108                frame.finish();
109            });
110    }
examples/material_system.rs (line 138)
107    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
108        if window_id != self.window_id {
109            return;
110        }
111
112        // Handle resize
113        events.dispatch(|event| {
114            if let astrelis_winit::event::Event::WindowResized(size) = event {
115                self.window.resized(*size);
116                astrelis_winit::event::HandleStatus::consumed()
117            } else {
118                astrelis_winit::event::HandleStatus::ignored()
119            }
120        });
121
122        // In a real application, materials would be bound during rendering:
123        // material.bind(&mut render_pass);
124        // draw_mesh(&mesh);
125
126        // Begin frame
127        let mut frame = self.window.begin_drawing();
128
129        frame.clear_and_render(
130            RenderTarget::Surface,
131            Color::from_rgb_u8(20, 30, 40),
132            |_pass| {
133                // Materials would be applied here in actual rendering
134                // This is a conceptual demonstration
135            },
136        );
137
138        frame.finish();
139    }
examples/sprite_sheet.rs (line 425)
390    fn render(
391        &mut self,
392        _ctx: &mut astrelis_winit::app::AppCtx,
393        window_id: WindowId,
394        events: &mut astrelis_winit::event::EventBatch,
395    ) {
396        let Some(window) = self.windows.get_mut(&window_id) else {
397            return;
398        };
399
400        // Handle resize
401        events.dispatch(|event| {
402            if let astrelis_winit::event::Event::WindowResized(size) = event {
403                window.resized(*size);
404                astrelis_winit::event::HandleStatus::consumed()
405            } else {
406                astrelis_winit::event::HandleStatus::ignored()
407            }
408        });
409
410        let mut frame = window.begin_drawing();
411
412        // Render with automatic scoping (no manual {} block needed)
413        frame.clear_and_render(
414            RenderTarget::Surface,
415            Color::rgb(0.1, 0.1, 0.15),
416            |pass| {
417                let pass = pass.wgpu_pass();
418                pass.set_pipeline(&self.pipeline);
419                pass.set_bind_group(0, &self.bind_group, &[]);
420                pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
421                pass.draw(0..6, 0..1);
422            },
423        );
424
425        frame.finish();
426    }
Source

pub fn gpu_profiler(&self) -> Option<&GpuFrameProfiler>

Get the GPU profiler attached to this frame, if any.

Source

pub fn has_gpu_profiler(&self) -> bool

Check if GPU profiling is active for this frame.

Source

pub fn with_pass<'a, F>(&'a mut self, builder: RenderPassBuilder<'a>, f: F)
where F: FnOnce(&mut RenderPass<'a>),

Execute a closure with a render pass, automatically handling scoping.

This is the ergonomic RAII pattern that eliminates the need for manual { } blocks. The render pass is automatically dropped after the closure completes.

When a GPU profiler is attached to this frame (via [RenderableWindow::set_gpu_profiler]), a GPU profiling scope is automatically created around the render pass, using the pass label (or "render_pass" as default) as the scope name.

§Example
frame.with_pass(
    RenderPassBuilder::new()
        .target(RenderTarget::Surface)
        .clear_color(Color::BLACK),
    |pass| {
        // Render commands here
        // pass automatically drops when closure ends
    }
);
frame.finish();
Examples found in repository?
examples/batched_renderer.rs (lines 433-450)
372    fn render(
373        &mut self,
374        _ctx: &mut astrelis_winit::app::AppCtx,
375        window_id: WindowId,
376        events: &mut astrelis_winit::event::EventBatch,
377    ) {
378        // Handle resize and get dimensions (scoped to release window borrow)
379        let (phys_width, phys_height) = {
380            let Some(window) = self.windows.get_mut(&window_id) else {
381                return;
382            };
383
384            events.dispatch(|event| {
385                if let astrelis_winit::event::Event::WindowResized(size) = event {
386                    window.resized(*size);
387                    astrelis_winit::event::HandleStatus::consumed()
388                } else {
389                    astrelis_winit::event::HandleStatus::ignored()
390                }
391            });
392
393            let phys = window.physical_size();
394            (phys.width, phys.height)
395        };
396
397        let width = phys_width as f32;
398        let height = phys_height as f32;
399
400        if width < 1.0 || height < 1.0 {
401            return;
402        }
403
404        // Ensure depth buffer matches viewport
405        self.ensure_depth_buffer(phys_width, phys_height);
406
407        // Build instances and prepare GPU data
408        let instances = self.build_instances(width, height);
409        let batch = DrawBatch2D {
410            instances,
411            textures: vec![],
412            projection: Self::ortho_projection(width, height),
413        };
414        self.renderer.prepare(&batch);
415
416        let stats = self.renderer.stats();
417        if self.frame_count % 120 == 0 {
418            tracing::info!(
419                "Frame {}: {} instances ({} opaque, {} transparent), {} draw calls",
420                self.frame_count,
421                stats.instance_count,
422                stats.opaque_count,
423                stats.transparent_count,
424                stats.draw_calls,
425            );
426        }
427
428        // Re-borrow window for rendering
429        let window = self.windows.get_mut(&window_id).unwrap();
430        let mut frame = window.begin_drawing();
431
432        // Use RenderPassBuilder with depth stencil attachment
433        frame.with_pass(
434            astrelis_render::RenderPassBuilder::new()
435                .label("batched_example_pass")
436                .target(astrelis_render::RenderTarget::Surface)
437                .clear_color(astrelis_render::Color::rgba(0.08, 0.08, 0.1, 1.0))
438                .clear_depth(0.0) // 0.0 = far with GreaterEqual
439                .depth_stencil_attachment(
440                    &self.depth_view,
441                    Some(wgpu::Operations {
442                        load: wgpu::LoadOp::Clear(0.0),
443                        store: wgpu::StoreOp::Store,
444                    }),
445                    None,
446                ),
447            |pass| {
448                self.renderer.render(pass.wgpu_pass());
449            },
450        );
451
452        frame.finish();
453    }
Source

pub fn clear_and_render<'a, F>( &'a mut self, target: RenderTarget<'a>, clear_color: impl Into<Color>, f: F, )
where F: FnOnce(&mut RenderPass<'a>),

Convenience method to clear to a color and execute rendering commands.

This is the most common pattern - clear the surface and render. When a GPU profiler is attached, a scope named "main_pass" is automatically created around the render pass.

§Example
frame.clear_and_render(
    RenderTarget::Surface,
    Color::BLACK,
    |pass| {
        // Render your content here
        // Example: ui.render(pass.wgpu_pass());
    }
);
frame.finish();
Examples found in repository?
examples/camera_demo.rs (lines 106-110)
91    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
92        if window_id != self.window_id {
93            return;
94        }
95
96        events.dispatch(|event| {
97            if let astrelis_winit::event::Event::WindowResized(size) = event {
98                self.window.resized(*size);
99                astrelis_winit::event::HandleStatus::consumed()
100            } else {
101                astrelis_winit::event::HandleStatus::ignored()
102            }
103        });
104
105        let mut frame = self.window.begin_drawing();
106        frame.clear_and_render(
107            RenderTarget::Surface,
108            Color::from_rgb_u8(20, 30, 40),
109            |_pass| {},
110        );
111        frame.finish();
112    }
More examples
Hide additional examples
examples/mesh_primitives.rs (lines 108-112)
93    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
94        if window_id != self.window_id {
95            return;
96        }
97
98        events.dispatch(|event| {
99            if let astrelis_winit::event::Event::WindowResized(size) = event {
100                self.window.resized(*size);
101                astrelis_winit::event::HandleStatus::consumed()
102            } else {
103                astrelis_winit::event::HandleStatus::ignored()
104            }
105        });
106
107        let mut frame = self.window.begin_drawing();
108        frame.clear_and_render(
109            RenderTarget::Surface,
110            Color::from_rgb_u8(20, 30, 40),
111            |_pass| {},
112        );
113        frame.finish();
114    }
examples/render_graph_demo.rs (lines 106-110)
91    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
92        if window_id != self.window_id {
93            return;
94        }
95
96        events.dispatch(|event| {
97            if let astrelis_winit::event::Event::WindowResized(size) = event {
98                self.window.resized(*size);
99                astrelis_winit::event::HandleStatus::consumed()
100            } else {
101                astrelis_winit::event::HandleStatus::ignored()
102            }
103        });
104
105        let mut frame = self.window.begin_drawing();
106        frame.clear_and_render(
107            RenderTarget::Surface,
108            Color::from_rgb_u8(20, 30, 40),
109            |_pass| {},
110        );
111        frame.finish();
112    }
examples/window_manager_demo.rs (lines 104-106)
86    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
87        // Get the color for this window
88        let Some(&color) = self.window_colors.get(&window_id) else {
89            return;
90        };
91
92        // WindowManager automatically handles:
93        // 1. Window lookup (no manual HashMap.get_mut)
94        // 2. Resize events (automatic)
95        // 3. Event dispatching
96        self.window_manager
97            .render_window(window_id, events, |window, _events| {
98                // No need to manually handle resize events!
99                // WindowManager already did that for us
100
101                // Just render!
102                let mut frame = window.begin_drawing();
103
104                frame.clear_and_render(RenderTarget::Surface, color, |_pass| {
105                    // Additional rendering would go here
106                });
107
108                frame.finish();
109            });
110    }
examples/material_system.rs (lines 129-136)
107    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
108        if window_id != self.window_id {
109            return;
110        }
111
112        // Handle resize
113        events.dispatch(|event| {
114            if let astrelis_winit::event::Event::WindowResized(size) = event {
115                self.window.resized(*size);
116                astrelis_winit::event::HandleStatus::consumed()
117            } else {
118                astrelis_winit::event::HandleStatus::ignored()
119            }
120        });
121
122        // In a real application, materials would be bound during rendering:
123        // material.bind(&mut render_pass);
124        // draw_mesh(&mesh);
125
126        // Begin frame
127        let mut frame = self.window.begin_drawing();
128
129        frame.clear_and_render(
130            RenderTarget::Surface,
131            Color::from_rgb_u8(20, 30, 40),
132            |_pass| {
133                // Materials would be applied here in actual rendering
134                // This is a conceptual demonstration
135            },
136        );
137
138        frame.finish();
139    }
examples/sprite_sheet.rs (lines 413-423)
390    fn render(
391        &mut self,
392        _ctx: &mut astrelis_winit::app::AppCtx,
393        window_id: WindowId,
394        events: &mut astrelis_winit::event::EventBatch,
395    ) {
396        let Some(window) = self.windows.get_mut(&window_id) else {
397            return;
398        };
399
400        // Handle resize
401        events.dispatch(|event| {
402            if let astrelis_winit::event::Event::WindowResized(size) = event {
403                window.resized(*size);
404                astrelis_winit::event::HandleStatus::consumed()
405            } else {
406                astrelis_winit::event::HandleStatus::ignored()
407            }
408        });
409
410        let mut frame = window.begin_drawing();
411
412        // Render with automatic scoping (no manual {} block needed)
413        frame.clear_and_render(
414            RenderTarget::Surface,
415            Color::rgb(0.1, 0.1, 0.15),
416            |pass| {
417                let pass = pass.wgpu_pass();
418                pass.set_pipeline(&self.pipeline);
419                pass.set_bind_group(0, &self.bind_group, &[]);
420                pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
421                pass.draw(0..6, 0..1);
422            },
423        );
424
425        frame.finish();
426    }
Source

pub fn clear_pass<'a>( &'a mut self, target: RenderTarget<'a>, clear_color: Color, ) -> RenderPass<'a>

Create a render pass that clears to the given color.

Source

pub fn load_pass<'a>(&'a mut self, target: RenderTarget<'a>) -> RenderPass<'a>

Create a render pass that loads existing content.

Source

pub fn with_gpu_scope<F>(&mut self, _label: &str, f: F)
where F: FnOnce(&mut CommandEncoder),

Execute a closure with a GPU profiling scope on the command encoder.

When gpu-profiling feature is disabled, this simply calls the closure with the encoder.

Trait Implementations§

Source§

impl AsWgpu for FrameContext

Source§

type WgpuType = CommandEncoder

The underlying wgpu type.
Source§

fn as_wgpu(&self) -> &Self::WgpuType

Get a reference to the underlying wgpu type.
Source§

impl AsWgpuMut for FrameContext

Source§

fn as_wgpu_mut(&mut self) -> &mut Self::WgpuType

Get a mutable reference to the underlying wgpu type.
Source§

impl Drop for FrameContext

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

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<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

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

Source§

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

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

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

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

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

Convert &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)

Convert &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> DowncastSync for T
where T: Any + Send + Sync,

Source§

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

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further 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, 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> 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
Source§

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

Source§

impl<T> WasmNotSendSync for T

Source§

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