pub struct Frame<'w> { /* private fields */ }Expand description
Context for a single frame of rendering.
Frame represents a single frame being rendered. It holds the acquired surface texture and collects command buffers from render passes. When dropped, it automatically submits all command buffers and presents the surface.
§Key Design Points
- Immutable reference: RenderPasses take
&Frame, not&mut Frame - RefCell for command buffers: Allows multiple passes without mutable borrow
- Atomic stats: Thread-safe pass/draw counting
- RAII cleanup: Drop handles submit and present
§Example
let frame = window.begin_frame().expect("Surface available");
// Create first pass
{
let mut pass = frame.render_pass()
.clear_color(Color::BLACK)
.build();
// Render background
}
// Create second pass (different encoder)
{
let mut pass = frame.render_pass()
.load_color()
.build();
// Render UI overlay
}
// Auto-submits on dropImplementations§
Source§impl<'w> Frame<'w>
impl<'w> Frame<'w>
Sourcepub fn surface_view(&self) -> &TextureView
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.
Sourcepub fn try_surface_view(&self) -> Option<&TextureView>
pub fn try_surface_view(&self) -> Option<&TextureView>
Try to get the surface texture view for this frame.
Sourcepub fn depth_view(&self) -> Option<&TextureView>
pub fn depth_view(&self) -> Option<&TextureView>
Get the window’s depth texture view, if the window was created with depth.
This provides access to the window-owned depth buffer for render passes that need depth testing.
Sourcepub fn surface_format(&self) -> TextureFormat
pub fn surface_format(&self) -> TextureFormat
Get the surface texture format.
Sourcepub fn graphics(&self) -> &GraphicsContext
pub fn graphics(&self) -> &GraphicsContext
Get the graphics context.
Sourcepub fn stats(&self) -> FrameStats
pub fn stats(&self) -> FrameStats
Get frame statistics.
Sourcepub fn gpu_profiler(&self) -> Option<&GpuFrameProfiler>
pub fn gpu_profiler(&self) -> Option<&GpuFrameProfiler>
Get the GPU profiler if attached.
Sourcepub fn has_gpu_profiler(&self) -> bool
pub fn has_gpu_profiler(&self) -> bool
Check if GPU profiling is active.
Sourcepub fn create_encoder(&self, label: Option<&str>) -> CommandEncoder
pub fn create_encoder(&self, label: Option<&str>) -> CommandEncoder
Create a command encoder for custom command recording.
Use this for operations that don’t fit the render pass model, like buffer copies or texture uploads.
Sourcepub fn add_command_buffer(&self, buffer: CommandBuffer)
pub fn add_command_buffer(&self, buffer: CommandBuffer)
Add a pre-built command buffer to the frame.
Use this when you have custom command recording logic.
Sourcepub fn render_pass(&self) -> RenderPassBuilder<'_, 'w>
pub fn render_pass(&self) -> RenderPassBuilder<'_, 'w>
Start building a render pass.
Returns a builder that can be configured with target, clear operations, and depth settings before building the actual pass.
Examples found in repository?
89 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90 if window_id != self.window_id {
91 return;
92 }
93
94 events.dispatch(|event| {
95 if let astrelis_winit::event::Event::WindowResized(size) = event {
96 self.window.resized(*size);
97 astrelis_winit::event::HandleStatus::consumed()
98 } else {
99 astrelis_winit::event::HandleStatus::ignored()
100 }
101 });
102
103 let Some(frame) = self.window.begin_frame() else {
104 return; // Surface not available
105 };
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(Color::from_rgb_u8(20, 30, 40))
110 .label("camera_demo_pass")
111 .build();
112 }
113 // Frame auto-submits on drop
114 }More examples
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 Some(frame) = self.window.begin_frame() else {
106 return; // Surface not available
107 };
108 {
109 let _pass = frame
110 .render_pass()
111 .clear_color(Color::from_rgb_u8(20, 30, 40))
112 .label("mesh_primitives_pass")
113 .build();
114 }
115 // Frame auto-submits on drop
116 }89 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
90 if window_id != self.window_id {
91 return;
92 }
93
94 events.dispatch(|event| {
95 if let astrelis_winit::event::Event::WindowResized(size) = event {
96 self.window.resized(*size);
97 astrelis_winit::event::HandleStatus::consumed()
98 } else {
99 astrelis_winit::event::HandleStatus::ignored()
100 }
101 });
102
103 let Some(frame) = self.window.begin_frame() else {
104 return; // Surface not available
105 };
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(Color::from_rgb_u8(20, 30, 40))
110 .label("render_graph_demo_pass")
111 .build();
112 }
113 // Frame auto-submits on drop
114 }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 Some(frame) = window.begin_frame() else {
103 return; // Surface not available
104 };
105
106 {
107 let _pass = frame
108 .render_pass()
109 .clear_color(color)
110 .label("window_manager_pass")
111 .build();
112 // Additional rendering would go here
113 }
114 // Frame auto-submits on drop
115 });
116 }105 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
106 if window_id != self.window_id {
107 return;
108 }
109
110 // Handle resize
111 events.dispatch(|event| {
112 if let astrelis_winit::event::Event::WindowResized(size) = event {
113 self.window.resized(*size);
114 astrelis_winit::event::HandleStatus::consumed()
115 } else {
116 astrelis_winit::event::HandleStatus::ignored()
117 }
118 });
119
120 // In a real application, materials would be bound during rendering:
121 // material.bind(&mut render_pass);
122 // draw_mesh(&mesh);
123
124 // Begin frame
125 let Some(frame) = self.window.begin_frame() else {
126 return; // Surface not available
127 };
128
129 {
130 let _pass = frame
131 .render_pass()
132 .clear_color(Color::from_rgb_u8(20, 30, 40))
133 .label("material_system_pass")
134 .build();
135 // Materials would be applied here in actual rendering
136 // This is a conceptual demonstration
137 }
138 // Frame auto-submits on drop
139 }431 fn render(
432 &mut self,
433 _ctx: &mut astrelis_winit::app::AppCtx,
434 window_id: WindowId,
435 events: &mut astrelis_winit::event::EventBatch,
436 ) {
437 let Some(window) = self.windows.get_mut(&window_id) else {
438 return;
439 };
440
441 // Handle resize
442 events.dispatch(|event| {
443 if let astrelis_winit::event::Event::WindowResized(size) = event {
444 window.resized(*size);
445 astrelis_winit::event::HandleStatus::consumed()
446 } else {
447 astrelis_winit::event::HandleStatus::ignored()
448 }
449 });
450
451 let Some(frame) = window.begin_frame() else {
452 return; // Surface not available
453 };
454 {
455 let mut pass = frame
456 .render_pass()
457 .clear_color(Color::rgb(0.1, 0.1, 0.15))
458 .label("sprite_sheet_pass")
459 .build();
460 pass.set_pipeline(&self.pipeline);
461 pass.set_bind_group(0, &self.bind_group, &[]);
462 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
463 pass.draw(0..6, 0..1);
464 }
465 // Frame auto-submits on drop
466 }Sourcepub fn compute_pass(&self) -> ComputePassBuilder<'_, 'w>
pub fn compute_pass(&self) -> ComputePassBuilder<'_, 'w>
Start building a compute pass.
Trait Implementations§
Auto Trait Implementations§
impl<'w> !Freeze for Frame<'w>
impl<'w> !RefUnwindSafe for Frame<'w>
impl<'w> Send for Frame<'w>
impl<'w> !Sync for Frame<'w>
impl<'w> Unpin for Frame<'w>
impl<'w> UnsafeUnpin for Frame<'w>
impl<'w> !UnwindSafe for Frame<'w>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&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> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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