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>
impl<'a> RenderPass<'a>
Sourcepub fn wgpu_pass(&mut self) -> &mut RenderPass<'static>
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?
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
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 }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 }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 }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 }Sourcepub fn try_wgpu_pass(&mut self) -> Option<&mut RenderPass<'static>>
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.
Sourcepub fn raw_pass(&mut self) -> &mut RenderPass<'static>
pub fn raw_pass(&mut self) -> &mut RenderPass<'static>
Get raw access to the underlying wgpu render pass.
Sourcepub fn graphics_context(&self) -> &GraphicsContext
pub fn graphics_context(&self) -> &GraphicsContext
Get the graphics context.
Sourcepub fn frame_context(&self) -> &FrameContext
pub fn frame_context(&self) -> &FrameContext
Get the frame context.
pub fn finish(self)
Sourcepub fn set_viewport_physical(
&mut self,
rect: PhysicalRect<f32>,
min_depth: f32,
max_depth: f32,
)
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) coordinatesmin_depth- Minimum depth value (typically 0.0)max_depth- Maximum depth value (typically 1.0)
Sourcepub fn set_viewport_logical(
&mut self,
rect: LogicalRect<f32>,
min_depth: f32,
max_depth: f32,
scale: ScaleFactor,
)
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 coordinatesmin_depth- Minimum depth value (typically 0.0)max_depth- Maximum depth value (typically 1.0)scale- Scale factor for logical to physical conversion
Sourcepub fn set_viewport(&mut self, viewport: &Viewport)
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.
Sourcepub fn set_scissor_physical(&mut self, rect: PhysicalRect<u32>)
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
Sourcepub fn set_scissor_logical(
&mut self,
rect: LogicalRect<f32>,
scale: ScaleFactor,
)
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 coordinatesscale- Scale factor for logical to physical conversion
Sourcepub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline)
pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline)
Set the pipeline for this render pass.
Sourcepub fn set_bind_group(
&mut self,
index: u32,
bind_group: &'a BindGroup,
offsets: &[u32],
)
pub fn set_bind_group( &mut self, index: u32, bind_group: &'a BindGroup, offsets: &[u32], )
Set a bind group for this render pass.
Sourcepub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>)
pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>)
Set the vertex buffer for this render pass.
Sourcepub fn set_index_buffer(
&mut self,
buffer_slice: BufferSlice<'a>,
format: IndexFormat,
)
pub fn set_index_buffer( &mut self, buffer_slice: BufferSlice<'a>, format: IndexFormat, )
Set the index buffer for this render pass.
Sourcepub fn draw_indexed(
&mut self,
indices: Range<u32>,
base_vertex: i32,
instances: Range<u32>,
)
pub fn draw_indexed( &mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>, )
Draw indexed primitives.
Sourcepub fn insert_debug_marker(&mut self, label: &str)
pub fn insert_debug_marker(&mut self, label: &str)
Insert a debug marker.
Sourcepub fn push_debug_group(&mut self, label: &str)
pub fn push_debug_group(&mut self, label: &str)
Push a debug group.
Sourcepub fn pop_debug_group(&mut self)
pub fn pop_debug_group(&mut self)
Pop a debug group.
Sourcepub fn set_push_constants<T: Pod>(
&mut self,
stages: ShaderStages,
offset: u32,
data: &T,
)
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 dataoffset- Byte offset within the push constant rangedata- 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,
);Sourcepub fn set_push_constants_raw(
&mut self,
stages: ShaderStages,
offset: u32,
data: &[u8],
)
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>
impl<'a> AsWgpu for RenderPass<'a>
Source§impl<'a> AsWgpuMut for RenderPass<'a>
impl<'a> AsWgpuMut for RenderPass<'a>
Source§fn as_wgpu_mut(&mut self) -> &mut Self::WgpuType
fn as_wgpu_mut(&mut self) -> &mut Self::WgpuType
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> 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> DowncastSync for T
impl<T> DowncastSync for T
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