Skip to main content

RenderPass

Struct RenderPass 

Source
pub struct RenderPass<'a> { /* private fields */ }
Expand description

A render pass wrapper that automatically returns the encoder to the frame context.

Implementations§

Source§

impl<'a> RenderPass<'a>

Source

pub fn wgpu_pass(&mut self) -> &mut RenderPass<'static>

Get the underlying wgpu RenderPass.

§Panics

Panics if the render pass has already been consumed (dropped or finished). Use try_wgpu_pass() for fallible access.

Examples found in repository?
examples/sprite_sheet.rs (line 417)
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    }
More examples
Hide additional examples
examples/image_blitting.rs (line 471)
444    fn render(
445        &mut self,
446        _ctx: &mut astrelis_winit::app::AppCtx,
447        window_id: WindowId,
448        events: &mut astrelis_winit::event::EventBatch,
449    ) {
450        let Some(window) = self.windows.get_mut(&window_id) else {
451            return;
452        };
453
454        // Handle resize
455        events.dispatch(|event| {
456            if let astrelis_winit::event::Event::WindowResized(size) = event {
457                window.resized(*size);
458                astrelis_winit::event::HandleStatus::consumed()
459            } else {
460                astrelis_winit::event::HandleStatus::ignored()
461            }
462        });
463
464        let mut frame = window.begin_drawing();
465
466        // Render with automatic scoping (no manual {} block needed)
467        frame.clear_and_render(
468            RenderTarget::Surface,
469            Color::rgb(0.05, 0.05, 0.08),
470            |pass| {
471                let pass = pass.wgpu_pass();
472                pass.set_pipeline(&self.pipeline);
473                pass.set_bind_group(0, &self.bind_group, &[]);
474                pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
475                pass.draw(0..6, 0..1);
476            },
477        );
478
479        frame.finish();
480    }
examples/textured_window.rs (line 291)
262    fn render(
263        &mut self,
264        _ctx: &mut astrelis_winit::app::AppCtx,
265        window_id: WindowId,
266        events: &mut astrelis_winit::event::EventBatch,
267    ) {
268        if window_id != self.window_id {
269            return;
270        }
271
272        // Handle window resize events
273        events.dispatch(|event| {
274            if let astrelis_winit::event::Event::WindowResized(size) = event {
275                self.window.resized(*size);
276                astrelis_winit::event::HandleStatus::consumed()
277            } else {
278                astrelis_winit::event::HandleStatus::ignored()
279            }
280        });
281
282        // --- Render Loop ---
283        let mut frame = self.window.begin_drawing();
284
285        // clear_and_render handles render pass scoping automatically:
286        // the pass is created, the closure runs, then the pass drops.
287        frame.clear_and_render(
288            RenderTarget::Surface,
289            Color::rgb(0.1, 0.2, 0.3),
290            |pass| {
291                let pass = pass.wgpu_pass();
292                pass.set_pipeline(&self.pipeline);
293                pass.set_bind_group(0, &self.bind_group, &[]);
294                pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
295                pass.draw(0..6, 0..1);
296            },
297        );
298
299        frame.finish();
300    }
examples/renderer_api.rs (line 308)
286    fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
287        if window_id != self.window_id {
288            return;
289        }
290
291        // Handle window-specific resize events
292        events.dispatch(|event| {
293            if let astrelis_winit::event::Event::WindowResized(size) = event {
294                self.window.resized(*size);
295                astrelis_winit::event::HandleStatus::consumed()
296            } else {
297                astrelis_winit::event::HandleStatus::ignored()
298            }
299        });
300
301        let mut frame = self.window.begin_drawing();
302
303        // Pass 1: Render to offscreen framebuffer with automatic scoping
304        frame.clear_and_render(
305            RenderTarget::Framebuffer(&self.offscreen_fb),
306            Color::rgb(0.2, 0.1, 0.3),
307            |pass| {
308                let pass = pass.wgpu_pass();
309                pass.set_pipeline(&self.pipeline);
310                pass.set_bind_group(0, &self.bind_group, &[]);
311                pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
312                pass.draw(0..6, 0..1);
313            },
314        );
315
316        // Pass 2: Blit framebuffer to surface with automatic scoping
317        frame.clear_and_render(
318            RenderTarget::Surface,
319            Color::rgb(0.1, 0.2, 0.3),
320            |pass| {
321                let pass = pass.wgpu_pass();
322                pass.set_pipeline(&self.blit_pipeline);
323                pass.set_bind_group(0, &self.blit_bind_group, &[]);
324                // Draw fullscreen triangle
325                pass.draw(0..3, 0..1);
326            },
327        );
328
329        frame.finish();
330    }
examples/batched_renderer.rs (line 448)
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 try_wgpu_pass(&mut self) -> Option<&mut RenderPass<'static>>

Try to get the underlying wgpu RenderPass.

Returns None if the render pass has already been consumed.

Source

pub fn is_valid(&self) -> bool

Check if the render pass is still valid and can be used.

Source

pub fn raw_pass(&mut self) -> &mut RenderPass<'static>

Get raw access to the underlying wgpu render pass.

Source

pub fn graphics_context(&self) -> &GraphicsContext

Get the graphics context.

Source

pub fn frame_context(&self) -> &FrameContext

Get the frame context.

Source

pub fn finish(self)

Source

pub fn set_viewport_physical( &mut self, rect: PhysicalRect<f32>, min_depth: f32, max_depth: f32, )

Set the viewport using physical coordinates.

The viewport defines the transformation from normalized device coordinates to window coordinates.

§Arguments
  • rect - The viewport rectangle in physical (pixel) coordinates
  • min_depth - Minimum depth value (typically 0.0)
  • max_depth - Maximum depth value (typically 1.0)
Source

pub fn set_viewport_logical( &mut self, rect: LogicalRect<f32>, min_depth: f32, max_depth: f32, scale: ScaleFactor, )

Set the viewport using logical coordinates (converts with scale factor).

§Arguments
  • rect - The viewport rectangle in logical coordinates
  • min_depth - Minimum depth value (typically 0.0)
  • max_depth - Maximum depth value (typically 1.0)
  • scale - Scale factor for logical to physical conversion
Source

pub fn set_viewport(&mut self, viewport: &Viewport)

Set the viewport from a Viewport struct.

Uses the viewport’s position and size, with depth range 0.0 to 1.0.

Source

pub fn set_scissor_physical(&mut self, rect: PhysicalRect<u32>)

Set the scissor rectangle using physical coordinates.

The scissor rectangle defines the area of the render target that can be modified by drawing commands.

§Arguments
  • rect - The scissor rectangle in physical (pixel) coordinates
Source

pub fn set_scissor_logical( &mut self, rect: LogicalRect<f32>, scale: ScaleFactor, )

Set the scissor rectangle using logical coordinates.

§Arguments
  • rect - The scissor rectangle in logical coordinates
  • scale - Scale factor for logical to physical conversion
Source

pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline)

Set the pipeline for this render pass.

Source

pub fn set_bind_group( &mut self, index: u32, bind_group: &'a BindGroup, offsets: &[u32], )

Set a bind group for this render pass.

Source

pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>)

Set the vertex buffer for this render pass.

Source

pub fn set_index_buffer( &mut self, buffer_slice: BufferSlice<'a>, format: IndexFormat, )

Set the index buffer for this render pass.

Source

pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>)

Draw primitives.

Source

pub fn draw_indexed( &mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>, )

Draw indexed primitives.

Source

pub fn insert_debug_marker(&mut self, label: &str)

Insert a debug marker.

Source

pub fn push_debug_group(&mut self, label: &str)

Push a debug group.

Source

pub fn pop_debug_group(&mut self)

Pop a debug group.

Source

pub fn set_push_constants<T: Pod>( &mut self, stages: ShaderStages, offset: u32, data: &T, )

Set push constants for a range of shader stages.

Push constants are a fast way to pass small amounts of data to shaders without the overhead of buffer updates. They are limited in size (typically 128-256 bytes depending on the GPU).

Requires the PUSH_CONSTANTS feature to be enabled.

§Arguments
  • stages - Which shader stages can access this data
  • offset - Byte offset within the push constant range
  • data - The data to set (must be Pod)
§Example
#[repr(C)]
#[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
struct PushConstants {
    transform: [[f32; 4]; 4],
    color: [f32; 4],
}

let constants = PushConstants {
    transform: /* ... */,
    color: [1.0, 0.0, 0.0, 1.0],
};

pass.set_push_constants(
    wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
    0,
    &constants,
);
Source

pub fn set_push_constants_raw( &mut self, stages: ShaderStages, offset: u32, data: &[u8], )

Set push constants from raw bytes.

Use this when you need more control over the data layout.

Trait Implementations§

Source§

impl<'a> AsWgpu for RenderPass<'a>

Source§

type WgpuType = RenderPass<'static>

The underlying wgpu type.
Source§

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

Get a reference to the underlying wgpu type.
Source§

impl<'a> AsWgpuMut for RenderPass<'a>

Source§

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

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

impl Drop for RenderPass<'_>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for RenderPass<'a>

§

impl<'a> !RefUnwindSafe for RenderPass<'a>

§

impl<'a> Send for RenderPass<'a>

§

impl<'a> Sync for RenderPass<'a>

§

impl<'a> Unpin for RenderPass<'a>

§

impl<'a> !UnwindSafe for RenderPass<'a>

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,