pub struct RenderPass<'f> { /* private fields */ }Expand description
A render pass that owns its encoder.
When dropped, the render pass:
- Ends the wgpu render pass
- Finishes the command encoder
- Pushes the command buffer to the frame
This design eliminates encoder movement and borrow conflicts.
Implementations§
Source§impl<'f> RenderPass<'f>
impl<'f> RenderPass<'f>
Sourcepub fn wgpu_pass(&mut self) -> &mut RenderPass<'static>
pub fn wgpu_pass(&mut self) -> &mut RenderPass<'static>
Get the underlying wgpu RenderPass (mutable).
§Panics
Panics if the render pass has already been consumed.
Examples found in repository?
370 fn render(
371 &mut self,
372 _ctx: &mut astrelis_winit::app::AppCtx,
373 window_id: WindowId,
374 events: &mut astrelis_winit::event::EventBatch,
375 ) {
376 // Handle resize and get dimensions (scoped to release window borrow)
377 let (phys_width, phys_height) = {
378 let Some(window) = self.windows.get_mut(&window_id) else {
379 return;
380 };
381
382 events.dispatch(|event| {
383 if let astrelis_winit::event::Event::WindowResized(size) = event {
384 window.resized(*size);
385 astrelis_winit::event::HandleStatus::consumed()
386 } else {
387 astrelis_winit::event::HandleStatus::ignored()
388 }
389 });
390
391 let phys = window.physical_size();
392 (phys.width, phys.height)
393 };
394
395 let width = phys_width as f32;
396 let height = phys_height as f32;
397
398 if width < 1.0 || height < 1.0 {
399 return;
400 }
401
402 // Ensure depth buffer matches viewport
403 self.ensure_depth_buffer(phys_width, phys_height);
404
405 // Build instances and prepare GPU data
406 let instances = self.build_instances(width, height);
407 let batch = DrawBatch2D {
408 instances,
409 textures: vec![],
410 projection: Self::ortho_projection(width, height),
411 };
412 self.renderer.prepare(&batch);
413
414 let stats = self.renderer.stats();
415 if self.frame_count.is_multiple_of(120) {
416 tracing::info!(
417 "Frame {}: {} instances ({} opaque, {} transparent), {} draw calls",
418 self.frame_count,
419 stats.instance_count,
420 stats.opaque_count,
421 stats.transparent_count,
422 stats.draw_calls,
423 );
424 }
425
426 // Re-borrow window for rendering
427 let window = self.windows.get_mut(&window_id).unwrap();
428 let Some(frame) = window.begin_frame() else {
429 return; // Surface not available
430 };
431
432 // Create render pass with depth stencil attachment
433 {
434 let mut pass = frame
435 .render_pass()
436 .clear_color(Color::rgba(0.08, 0.08, 0.1, 1.0))
437 .depth_attachment(&self.depth_view)
438 .clear_depth(0.0) // 0.0 = far with GreaterEqual
439 .label("batched_example_pass")
440 .build();
441 self.renderer.render(pass.wgpu_pass());
442 }
443 // Frame auto-submits on drop
444 }Sourcepub fn wgpu_pass_ref(&self) -> &RenderPass<'static>
pub fn wgpu_pass_ref(&self) -> &RenderPass<'static>
Get the underlying wgpu RenderPass (immutable).
§Panics
Panics if the render pass has already been consumed.
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.
Sourcepub fn raw_pass(&mut self) -> &mut RenderPass<'static>
pub fn raw_pass(&mut self) -> &mut RenderPass<'static>
Get raw access to the pass (alias for wgpu_pass).
Sourcepub fn encoder(&self) -> Option<&CommandEncoder>
pub fn encoder(&self) -> Option<&CommandEncoder>
Get the command encoder.
Sourcepub fn encoder_mut(&mut self) -> Option<&mut CommandEncoder>
pub fn encoder_mut(&mut self) -> Option<&mut CommandEncoder>
Get mutable access to the command encoder.
Sourcepub fn graphics(&self) -> &GraphicsContext
pub fn graphics(&self) -> &GraphicsContext
Get the graphics context.
Sourcepub fn record_draw_call(&self)
pub fn record_draw_call(&self)
Record a draw call for statistics.
Sourcepub fn into_encoder(self) -> CommandEncoder
pub fn into_encoder(self) -> CommandEncoder
Consume the pass early and return the encoder for further use.
This ends the render pass but allows the encoder to be used for additional commands before submission.
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.
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.
Sourcepub fn set_viewport(&mut self, viewport: &Viewport)
pub fn set_viewport(&mut self, viewport: &Viewport)
Set the viewport from a Viewport struct.
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.
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.
Sourcepub fn set_pipeline(&mut self, pipeline: &RenderPipeline)
pub fn set_pipeline(&mut self, pipeline: &RenderPipeline)
Set the pipeline.
Examples found in repository?
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 }More examples
486 fn render(
487 &mut self,
488 _ctx: &mut astrelis_winit::app::AppCtx,
489 window_id: WindowId,
490 events: &mut astrelis_winit::event::EventBatch,
491 ) {
492 let Some(window) = self.windows.get_mut(&window_id) else {
493 return;
494 };
495
496 // Handle resize
497 events.dispatch(|event| {
498 if let astrelis_winit::event::Event::WindowResized(size) = event {
499 window.resized(*size);
500 astrelis_winit::event::HandleStatus::consumed()
501 } else {
502 astrelis_winit::event::HandleStatus::ignored()
503 }
504 });
505
506 let Some(frame) = window.begin_frame() else {
507 return; // Surface not available
508 };
509
510 {
511 let mut pass = frame
512 .render_pass()
513 .clear_color(Color::rgb(0.05, 0.05, 0.08))
514 .label("image_blitting_pass")
515 .build();
516 pass.set_pipeline(&self.pipeline);
517 pass.set_bind_group(0, &self.bind_group, &[]);
518 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
519 pass.draw(0..6, 0..1);
520 }
521 // Frame auto-submits on drop
522 }260 fn render(
261 &mut self,
262 _ctx: &mut astrelis_winit::app::AppCtx,
263 window_id: WindowId,
264 events: &mut astrelis_winit::event::EventBatch,
265 ) {
266 if window_id != self.window_id {
267 return;
268 }
269
270 // Handle window resize events
271 events.dispatch(|event| {
272 if let astrelis_winit::event::Event::WindowResized(size) = event {
273 self.window.resized(*size);
274 astrelis_winit::event::HandleStatus::consumed()
275 } else {
276 astrelis_winit::event::HandleStatus::ignored()
277 }
278 });
279
280 // --- Render Loop ---
281 let Some(frame) = self.window.begin_frame() else {
282 return; // Surface not available
283 };
284
285 {
286 let mut pass = frame
287 .render_pass()
288 .clear_color(Color::rgb(0.1, 0.2, 0.3))
289 .label("textured_window_pass")
290 .build();
291 pass.set_pipeline(&self.pipeline);
292 pass.set_bind_group(0, &self.bind_group, &[]);
293 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
294 pass.draw(0..6, 0..1);
295 }
296 // Frame auto-submits on drop
297 }284 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
285 if window_id != self.window_id {
286 return;
287 }
288
289 // Handle window-specific resize events
290 events.dispatch(|event| {
291 if let astrelis_winit::event::Event::WindowResized(size) = event {
292 self.window.resized(*size);
293 astrelis_winit::event::HandleStatus::consumed()
294 } else {
295 astrelis_winit::event::HandleStatus::ignored()
296 }
297 });
298
299 let Some(frame) = self.window.begin_frame() else {
300 return; // Surface not available
301 };
302
303 // Pass 1: Render to offscreen framebuffer
304 {
305 let mut pass = frame
306 .render_pass()
307 .target(RenderTarget::Framebuffer(&self.offscreen_fb))
308 .clear_color(Color::rgb(0.2, 0.1, 0.3))
309 .label("offscreen_pass")
310 .build();
311 pass.set_pipeline(&self.pipeline);
312 pass.set_bind_group(0, &self.bind_group, &[]);
313 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
314 pass.draw(0..6, 0..1);
315 }
316
317 // Pass 2: Blit framebuffer to surface
318 {
319 let mut pass = frame
320 .render_pass()
321 .clear_color(Color::rgb(0.1, 0.2, 0.3))
322 .label("blit_pass")
323 .build();
324 pass.set_pipeline(&self.blit_pipeline);
325 pass.set_bind_group(0, &self.blit_bind_group, &[]);
326 // Draw fullscreen triangle
327 pass.draw(0..3, 0..1);
328 }
329 // Frame auto-submits on drop
330 }Sourcepub fn set_bind_group(
&mut self,
index: u32,
bind_group: &BindGroup,
offsets: &[u32],
)
pub fn set_bind_group( &mut self, index: u32, bind_group: &BindGroup, offsets: &[u32], )
Set a bind group.
Examples found in repository?
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 }More examples
486 fn render(
487 &mut self,
488 _ctx: &mut astrelis_winit::app::AppCtx,
489 window_id: WindowId,
490 events: &mut astrelis_winit::event::EventBatch,
491 ) {
492 let Some(window) = self.windows.get_mut(&window_id) else {
493 return;
494 };
495
496 // Handle resize
497 events.dispatch(|event| {
498 if let astrelis_winit::event::Event::WindowResized(size) = event {
499 window.resized(*size);
500 astrelis_winit::event::HandleStatus::consumed()
501 } else {
502 astrelis_winit::event::HandleStatus::ignored()
503 }
504 });
505
506 let Some(frame) = window.begin_frame() else {
507 return; // Surface not available
508 };
509
510 {
511 let mut pass = frame
512 .render_pass()
513 .clear_color(Color::rgb(0.05, 0.05, 0.08))
514 .label("image_blitting_pass")
515 .build();
516 pass.set_pipeline(&self.pipeline);
517 pass.set_bind_group(0, &self.bind_group, &[]);
518 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
519 pass.draw(0..6, 0..1);
520 }
521 // Frame auto-submits on drop
522 }260 fn render(
261 &mut self,
262 _ctx: &mut astrelis_winit::app::AppCtx,
263 window_id: WindowId,
264 events: &mut astrelis_winit::event::EventBatch,
265 ) {
266 if window_id != self.window_id {
267 return;
268 }
269
270 // Handle window resize events
271 events.dispatch(|event| {
272 if let astrelis_winit::event::Event::WindowResized(size) = event {
273 self.window.resized(*size);
274 astrelis_winit::event::HandleStatus::consumed()
275 } else {
276 astrelis_winit::event::HandleStatus::ignored()
277 }
278 });
279
280 // --- Render Loop ---
281 let Some(frame) = self.window.begin_frame() else {
282 return; // Surface not available
283 };
284
285 {
286 let mut pass = frame
287 .render_pass()
288 .clear_color(Color::rgb(0.1, 0.2, 0.3))
289 .label("textured_window_pass")
290 .build();
291 pass.set_pipeline(&self.pipeline);
292 pass.set_bind_group(0, &self.bind_group, &[]);
293 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
294 pass.draw(0..6, 0..1);
295 }
296 // Frame auto-submits on drop
297 }284 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
285 if window_id != self.window_id {
286 return;
287 }
288
289 // Handle window-specific resize events
290 events.dispatch(|event| {
291 if let astrelis_winit::event::Event::WindowResized(size) = event {
292 self.window.resized(*size);
293 astrelis_winit::event::HandleStatus::consumed()
294 } else {
295 astrelis_winit::event::HandleStatus::ignored()
296 }
297 });
298
299 let Some(frame) = self.window.begin_frame() else {
300 return; // Surface not available
301 };
302
303 // Pass 1: Render to offscreen framebuffer
304 {
305 let mut pass = frame
306 .render_pass()
307 .target(RenderTarget::Framebuffer(&self.offscreen_fb))
308 .clear_color(Color::rgb(0.2, 0.1, 0.3))
309 .label("offscreen_pass")
310 .build();
311 pass.set_pipeline(&self.pipeline);
312 pass.set_bind_group(0, &self.bind_group, &[]);
313 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
314 pass.draw(0..6, 0..1);
315 }
316
317 // Pass 2: Blit framebuffer to surface
318 {
319 let mut pass = frame
320 .render_pass()
321 .clear_color(Color::rgb(0.1, 0.2, 0.3))
322 .label("blit_pass")
323 .build();
324 pass.set_pipeline(&self.blit_pipeline);
325 pass.set_bind_group(0, &self.blit_bind_group, &[]);
326 // Draw fullscreen triangle
327 pass.draw(0..3, 0..1);
328 }
329 // Frame auto-submits on drop
330 }Sourcepub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'_>)
pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'_>)
Set a vertex buffer.
Examples found in repository?
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 }More examples
486 fn render(
487 &mut self,
488 _ctx: &mut astrelis_winit::app::AppCtx,
489 window_id: WindowId,
490 events: &mut astrelis_winit::event::EventBatch,
491 ) {
492 let Some(window) = self.windows.get_mut(&window_id) else {
493 return;
494 };
495
496 // Handle resize
497 events.dispatch(|event| {
498 if let astrelis_winit::event::Event::WindowResized(size) = event {
499 window.resized(*size);
500 astrelis_winit::event::HandleStatus::consumed()
501 } else {
502 astrelis_winit::event::HandleStatus::ignored()
503 }
504 });
505
506 let Some(frame) = window.begin_frame() else {
507 return; // Surface not available
508 };
509
510 {
511 let mut pass = frame
512 .render_pass()
513 .clear_color(Color::rgb(0.05, 0.05, 0.08))
514 .label("image_blitting_pass")
515 .build();
516 pass.set_pipeline(&self.pipeline);
517 pass.set_bind_group(0, &self.bind_group, &[]);
518 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
519 pass.draw(0..6, 0..1);
520 }
521 // Frame auto-submits on drop
522 }260 fn render(
261 &mut self,
262 _ctx: &mut astrelis_winit::app::AppCtx,
263 window_id: WindowId,
264 events: &mut astrelis_winit::event::EventBatch,
265 ) {
266 if window_id != self.window_id {
267 return;
268 }
269
270 // Handle window resize events
271 events.dispatch(|event| {
272 if let astrelis_winit::event::Event::WindowResized(size) = event {
273 self.window.resized(*size);
274 astrelis_winit::event::HandleStatus::consumed()
275 } else {
276 astrelis_winit::event::HandleStatus::ignored()
277 }
278 });
279
280 // --- Render Loop ---
281 let Some(frame) = self.window.begin_frame() else {
282 return; // Surface not available
283 };
284
285 {
286 let mut pass = frame
287 .render_pass()
288 .clear_color(Color::rgb(0.1, 0.2, 0.3))
289 .label("textured_window_pass")
290 .build();
291 pass.set_pipeline(&self.pipeline);
292 pass.set_bind_group(0, &self.bind_group, &[]);
293 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
294 pass.draw(0..6, 0..1);
295 }
296 // Frame auto-submits on drop
297 }284 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
285 if window_id != self.window_id {
286 return;
287 }
288
289 // Handle window-specific resize events
290 events.dispatch(|event| {
291 if let astrelis_winit::event::Event::WindowResized(size) = event {
292 self.window.resized(*size);
293 astrelis_winit::event::HandleStatus::consumed()
294 } else {
295 astrelis_winit::event::HandleStatus::ignored()
296 }
297 });
298
299 let Some(frame) = self.window.begin_frame() else {
300 return; // Surface not available
301 };
302
303 // Pass 1: Render to offscreen framebuffer
304 {
305 let mut pass = frame
306 .render_pass()
307 .target(RenderTarget::Framebuffer(&self.offscreen_fb))
308 .clear_color(Color::rgb(0.2, 0.1, 0.3))
309 .label("offscreen_pass")
310 .build();
311 pass.set_pipeline(&self.pipeline);
312 pass.set_bind_group(0, &self.bind_group, &[]);
313 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
314 pass.draw(0..6, 0..1);
315 }
316
317 // Pass 2: Blit framebuffer to surface
318 {
319 let mut pass = frame
320 .render_pass()
321 .clear_color(Color::rgb(0.1, 0.2, 0.3))
322 .label("blit_pass")
323 .build();
324 pass.set_pipeline(&self.blit_pipeline);
325 pass.set_bind_group(0, &self.blit_bind_group, &[]);
326 // Draw fullscreen triangle
327 pass.draw(0..3, 0..1);
328 }
329 // Frame auto-submits on drop
330 }Sourcepub fn set_index_buffer(
&mut self,
buffer_slice: BufferSlice<'_>,
format: IndexFormat,
)
pub fn set_index_buffer( &mut self, buffer_slice: BufferSlice<'_>, format: IndexFormat, )
Set the index buffer.
Sourcepub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>)
pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>)
Draw primitives.
Examples found in repository?
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 }More examples
486 fn render(
487 &mut self,
488 _ctx: &mut astrelis_winit::app::AppCtx,
489 window_id: WindowId,
490 events: &mut astrelis_winit::event::EventBatch,
491 ) {
492 let Some(window) = self.windows.get_mut(&window_id) else {
493 return;
494 };
495
496 // Handle resize
497 events.dispatch(|event| {
498 if let astrelis_winit::event::Event::WindowResized(size) = event {
499 window.resized(*size);
500 astrelis_winit::event::HandleStatus::consumed()
501 } else {
502 astrelis_winit::event::HandleStatus::ignored()
503 }
504 });
505
506 let Some(frame) = window.begin_frame() else {
507 return; // Surface not available
508 };
509
510 {
511 let mut pass = frame
512 .render_pass()
513 .clear_color(Color::rgb(0.05, 0.05, 0.08))
514 .label("image_blitting_pass")
515 .build();
516 pass.set_pipeline(&self.pipeline);
517 pass.set_bind_group(0, &self.bind_group, &[]);
518 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
519 pass.draw(0..6, 0..1);
520 }
521 // Frame auto-submits on drop
522 }260 fn render(
261 &mut self,
262 _ctx: &mut astrelis_winit::app::AppCtx,
263 window_id: WindowId,
264 events: &mut astrelis_winit::event::EventBatch,
265 ) {
266 if window_id != self.window_id {
267 return;
268 }
269
270 // Handle window resize events
271 events.dispatch(|event| {
272 if let astrelis_winit::event::Event::WindowResized(size) = event {
273 self.window.resized(*size);
274 astrelis_winit::event::HandleStatus::consumed()
275 } else {
276 astrelis_winit::event::HandleStatus::ignored()
277 }
278 });
279
280 // --- Render Loop ---
281 let Some(frame) = self.window.begin_frame() else {
282 return; // Surface not available
283 };
284
285 {
286 let mut pass = frame
287 .render_pass()
288 .clear_color(Color::rgb(0.1, 0.2, 0.3))
289 .label("textured_window_pass")
290 .build();
291 pass.set_pipeline(&self.pipeline);
292 pass.set_bind_group(0, &self.bind_group, &[]);
293 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
294 pass.draw(0..6, 0..1);
295 }
296 // Frame auto-submits on drop
297 }284 fn render(&mut self, _ctx: &mut AppCtx, window_id: WindowId, events: &mut EventBatch) {
285 if window_id != self.window_id {
286 return;
287 }
288
289 // Handle window-specific resize events
290 events.dispatch(|event| {
291 if let astrelis_winit::event::Event::WindowResized(size) = event {
292 self.window.resized(*size);
293 astrelis_winit::event::HandleStatus::consumed()
294 } else {
295 astrelis_winit::event::HandleStatus::ignored()
296 }
297 });
298
299 let Some(frame) = self.window.begin_frame() else {
300 return; // Surface not available
301 };
302
303 // Pass 1: Render to offscreen framebuffer
304 {
305 let mut pass = frame
306 .render_pass()
307 .target(RenderTarget::Framebuffer(&self.offscreen_fb))
308 .clear_color(Color::rgb(0.2, 0.1, 0.3))
309 .label("offscreen_pass")
310 .build();
311 pass.set_pipeline(&self.pipeline);
312 pass.set_bind_group(0, &self.bind_group, &[]);
313 pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
314 pass.draw(0..6, 0..1);
315 }
316
317 // Pass 2: Blit framebuffer to surface
318 {
319 let mut pass = frame
320 .render_pass()
321 .clear_color(Color::rgb(0.1, 0.2, 0.3))
322 .label("blit_pass")
323 .build();
324 pass.set_pipeline(&self.blit_pipeline);
325 pass.set_bind_group(0, &self.blit_bind_group, &[]);
326 // Draw fullscreen triangle
327 pass.draw(0..3, 0..1);
328 }
329 // Frame auto-submits on drop
330 }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.
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.
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<'f> Freeze for RenderPass<'f>
impl<'f> !RefUnwindSafe for RenderPass<'f>
impl<'f> !Send for RenderPass<'f>
impl<'f> !Sync for RenderPass<'f>
impl<'f> Unpin for RenderPass<'f>
impl<'f> UnsafeUnpin for RenderPass<'f>
impl<'f> !UnwindSafe for RenderPass<'f>
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