Skip to main content

RenderableWindow

Struct RenderableWindow 

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

A renderable window that combines a winit Window with a WindowContext.

This is the primary type for rendering to a window. It implements Deref<Target = WindowContext>, so all WindowContext methods are available directly.

§GPU Profiling

Attach a GpuFrameProfiler via set_gpu_profiler to automatically profile render passes. Once attached, all frames created via begin_drawing will include GPU profiling:

  • Render passes in with_pass() / clear_and_render() get automatic GPU scopes
  • Queries are resolved and the profiler frame is ended in FrameContext::Drop

Implementations§

Source§

impl RenderableWindow

Source

pub fn new( window: Window, context: Arc<GraphicsContext>, ) -> Result<Self, GraphicsError>

Source

pub fn new_with_descriptor( window: Window, context: Arc<GraphicsContext>, descriptor: WindowContextDescriptor, ) -> Result<Self, GraphicsError>

Examples found in repository?
examples/multi_window.rs (lines 66-73)
27fn main() {
28    logging::init();
29
30    run_app(|ctx| {
31        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
32
33        let mut windows = HashMap::new();
34
35        // Create 3 windows with different colors
36        let colors = [
37            wgpu::Color {
38                r: 0.8,
39                g: 0.2,
40                b: 0.2,
41                a: 1.0,
42            },
43            wgpu::Color {
44                r: 0.2,
45                g: 0.8,
46                b: 0.2,
47                a: 1.0,
48            },
49            wgpu::Color {
50                r: 0.2,
51                g: 0.2,
52                b: 0.8,
53                a: 1.0,
54            },
55        ];
56
57        for (i, color) in colors.iter().enumerate() {
58            let window = ctx
59                .create_window(WindowDescriptor {
60                    title: format!("Window {} - Multi-Window Example", i + 1),
61                    size: Some(WinitPhysicalSize::new(400.0, 300.0)),
62                    ..Default::default()
63                })
64                .expect("Failed to create window");
65
66            let renderable_window = RenderableWindow::new_with_descriptor(
67                window,
68                graphics_ctx.clone(),
69                WindowContextDescriptor {
70                    format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
71                    ..Default::default()
72                },
73            ).expect("Failed to create renderable window");
74
75            let window_id = renderable_window.id();
76            windows.insert(window_id, (renderable_window, *color));
77        }
78
79        Box::new(App {
80            windows,
81        })
82    });
83}
More examples
Hide additional examples
examples/performance_benchmark.rs (lines 50-57)
36fn main() {
37    logging::init();
38
39    run_app(|ctx| {
40        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
41
42        let window = ctx
43            .create_window(WindowDescriptor {
44                title: "Performance Benchmark - Render Stress Test".to_string(),
45                size: Some(WinitPhysicalSize::new(1280.0, 720.0)),
46                ..Default::default()
47            })
48            .expect("Failed to create window");
49
50        let window = RenderableWindow::new_with_descriptor(
51            window,
52            graphics_ctx.clone(),
53            WindowContextDescriptor {
54                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
55                ..Default::default()
56            },
57        ).expect("Failed to create renderable window");
58
59        let window_id = window.id();
60
61        println!("\n═══════════════════════════════════════════════════════");
62        println!("  ⚡ PERFORMANCE BENCHMARK - Render Stress Test");
63        println!("═══════════════════════════════════════════════════════");
64        println!("  CONTROLS:");
65        println!("    [Space]  Toggle rendering on/off");
66        println!("    [+/-]    Increase/decrease object count");
67        println!("  Starting with 1000 objects");
68        println!("═══════════════════════════════════════════════════════\n");
69
70        Box::new(PerformanceBenchmark {
71            _context: graphics_ctx,
72            window,
73            window_id,
74            object_count: 1000,
75            rendering: true,
76            frame_count: 0,
77            last_fps_time: Instant::now(),
78            fps: 0.0,
79            last_frame_time: 0.0,
80        })
81    });
82}
examples/camera_demo.rs (lines 44-51)
30fn main() {
31    logging::init();
32
33    run_app(|ctx| {
34        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
35
36        let window = ctx
37            .create_window(WindowDescriptor {
38                title: "Camera Demo - View & Projection".to_string(),
39                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
40                ..Default::default()
41            })
42            .expect("Failed to create window");
43
44        let window = RenderableWindow::new_with_descriptor(
45            window,
46            graphics_ctx.clone(),
47            WindowContextDescriptor {
48                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
49                ..Default::default()
50            },
51        ).expect("Failed to create renderable window");
52
53        let window_id = window.id();
54
55        println!("\n═══════════════════════════════════════════════════════");
56        println!("  📹 CAMERA DEMO - View & Projection");
57        println!("═══════════════════════════════════════════════════════");
58        println!("\n  CAMERA API FEATURES:");
59        println!("    • Orthographic cameras (2D, UI, isometric)");
60        println!("    • Perspective cameras (3D scenes)");
61        println!("    • View matrix (position, rotation, look-at)");
62        println!("    • Projection matrix (FOV, aspect, near/far planes)");
63        println!("    • Screen-to-world coordinate conversion");
64        println!("    • Camera movement helpers");
65        println!("\n  CAMERA TYPES:");
66        println!("    • OrthographicCamera - 2D games, UI overlays");
67        println!("      camera.orthographic(left, right, bottom, top, near, far)");
68        println!("    • PerspectiveCamera - 3D scenes");
69        println!("      camera.perspective(fov, aspect, near, far)");
70        println!("\n  Camera API Usage:");
71        println!("    let camera = Camera::new()");
72        println!("        .position(Vec3::new(0.0, 5.0, 10.0))");
73        println!("        .look_at(Vec3::ZERO)");
74        println!("        .perspective(60.0, aspect, 0.1, 100.0);");
75        println!("    let view_proj = camera.view_projection_matrix();");
76        println!("═══════════════════════════════════════════════════════\n");
77
78        tracing::info!("Camera demo initialized");
79
80        Box::new(CameraDemo {
81            _context: graphics_ctx,
82            window,
83            window_id,
84        })
85    });
86}
examples/render_graph_demo.rs (lines 43-50)
29fn main() {
30    logging::init();
31
32    run_app(|ctx| {
33        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
34
35        let window = ctx
36            .create_window(WindowDescriptor {
37                title: "Render Graph Demo - Multi-Pass Rendering".to_string(),
38                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
39                ..Default::default()
40            })
41            .expect("Failed to create window");
42
43        let window = RenderableWindow::new_with_descriptor(
44            window,
45            graphics_ctx.clone(),
46            WindowContextDescriptor {
47                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
48                ..Default::default()
49            },
50        ).expect("Failed to create renderable window");
51
52        let window_id = window.id();
53
54        println!("\n═══════════════════════════════════════════════════════");
55        println!("  🔀 RENDER GRAPH DEMO - Multi-Pass Rendering");
56        println!("═══════════════════════════════════════════════════════");
57        println!("\n  RENDER GRAPH FEATURES:");
58        println!("    • Declarative pass definition");
59        println!("    • Automatic dependency resolution");
60        println!("    • Resource lifetime management");
61        println!("    • Parallel pass execution");
62        println!("    • Automatic optimization");
63        println!("\n  EXAMPLE PIPELINE:");
64        println!("    1. Shadow Pass → depth texture");
65        println!("    2. Geometry Pass → color + normal + depth");
66        println!("    3. Lighting Pass → lit scene");
67        println!("    4. Post-Processing → bloom, tone mapping");
68        println!("    5. UI Pass → final composite");
69        println!("\n  Render Graph API Usage:");
70        println!("    let mut graph = RenderGraph::new();");
71        println!("    graph.add_pass(\"shadow\", shadow_pass_descriptor);");
72        println!("    graph.add_pass(\"geometry\", geometry_pass_descriptor);");
73        println!("    graph.add_dependency(\"lighting\", \"geometry\");");
74        println!("    graph.compile();");
75        println!("    graph.execute(&mut encoder);");
76        println!("═══════════════════════════════════════════════════════\n");
77
78        tracing::info!("Render graph demo initialized");
79
80        Box::new(RenderGraphDemo {
81            _context: graphics_ctx,
82            window,
83            window_id,
84        })
85    });
86}
examples/mesh_primitives.rs (lines 43-50)
29fn main() {
30    logging::init();
31
32    run_app(|ctx| {
33        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
34
35        let window = ctx
36            .create_window(WindowDescriptor {
37                title: "Mesh Primitives Demo - Geometry API".to_string(),
38                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
39                ..Default::default()
40            })
41            .expect("Failed to create window");
42
43        let window = RenderableWindow::new_with_descriptor(
44            window,
45            graphics_ctx.clone(),
46            WindowContextDescriptor {
47                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
48                ..Default::default()
49            },
50        ).expect("Failed to create renderable window");
51
52        let window_id = window.id();
53
54        println!("\n═══════════════════════════════════════════════════════");
55        println!("  📐 MESH PRIMITIVES DEMO - Geometry API");
56        println!("═══════════════════════════════════════════════════════");
57        println!("\n  MESH API FEATURES:");
58        println!("    • MeshBuilder for custom geometry");
59        println!("    • Primitive generation (cube, sphere, plane, etc.)");
60        println!("    • Flexible vertex formats (Position, Normal, UV, Color)");
61        println!("    • Index buffer optimization");
62        println!("    • Instanced rendering support");
63        println!("\n  EXAMPLE PRIMITIVES:");
64        println!("    • Cube - box with 24 vertices (6 faces × 4 vertices)");
65        println!("    • Sphere - tessellated sphere with UV mapping");
66        println!("    • Plane - quad with optional subdivisions");
67        println!("    • Cylinder - sides + caps");
68        println!("    • Custom - arbitrary vertex/index data");
69        println!("\n  Mesh API Usage:");
70        println!("    let mesh = MeshBuilder::new()");
71        println!("        .with_positions(vertices)");
72        println!("        .with_normals(normals)");
73        println!("        .with_uvs(uvs)");
74        println!("        .with_indices(indices)");
75        println!("        .build(&ctx);");
76        println!("    mesh.draw(&mut pass);");
77        println!("    mesh.draw_instanced(&mut pass, instance_count);");
78        println!("═══════════════════════════════════════════════════════\n");
79
80        tracing::info!("Mesh primitives demo initialized");
81
82        Box::new(MeshPrimitivesDemo {
83            _context: graphics_ctx,
84            window,
85            window_id,
86        })
87    });
88}
examples/batched_renderer.rs (lines 308-315)
275fn main() {
276    logging::init();
277
278    run_app(|ctx| {
279        let tier_override = parse_tier();
280
281        // Use the capability API to configure GPU requirements.
282        // For auto-detect, request the best capability (graceful degradation).
283        // For a specific tier, require that tier's capability.
284        let descriptor = match tier_override {
285            None => GraphicsContextDescriptor::new()
286                .request_capability::<BestBatchCapability2D>(),
287            Some(RenderTier::Direct) => GraphicsContextDescriptor::new()
288                .require_capability::<DirectBatchCapability2D>(),
289            Some(RenderTier::Indirect) => GraphicsContextDescriptor::new()
290                .require_capability::<IndirectBatchCapability2D>(),
291            Some(RenderTier::Bindless) => GraphicsContextDescriptor::new()
292                .require_capability::<BindlessBatchCapability2D>(),
293        };
294        let graphics_ctx =
295            pollster::block_on(GraphicsContext::new_owned_with_descriptor(descriptor))
296                .expect("Failed to create graphics context");
297
298        let window = ctx
299            .create_window(WindowDescriptor {
300                title: "Batched Renderer Example".to_string(),
301                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
302                ..Default::default()
303            })
304            .expect("Failed to create window");
305
306        let surface_format = wgpu::TextureFormat::Bgra8UnormSrgb;
307
308        let renderable_window = RenderableWindow::new_with_descriptor(
309            window,
310            graphics_ctx.clone(),
311            WindowContextDescriptor {
312                format: Some(surface_format),
313                ..Default::default()
314            },
315        )
316        .expect("Failed to create renderable window");
317
318        let window_id = renderable_window.id();
319
320        let renderer = create_batch_renderer_2d(
321            graphics_ctx.clone(),
322            surface_format,
323            tier_override,
324        );
325
326        tracing::info!("Using render tier: {}", renderer.tier());
327
328        // Create initial depth buffer
329        let depth_texture = graphics_ctx
330            .device()
331            .create_texture(&wgpu::TextureDescriptor {
332                label: Some("example_depth"),
333                size: wgpu::Extent3d {
334                    width: 1,
335                    height: 1,
336                    depth_or_array_layers: 1,
337                },
338                mip_level_count: 1,
339                sample_count: 1,
340                dimension: wgpu::TextureDimension::D2,
341                format: DEPTH_FORMAT,
342                usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
343                view_formats: &[],
344            });
345        let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
346
347        let mut windows = HashMap::new();
348        windows.insert(window_id, renderable_window);
349
350        Box::new(App {
351            context: graphics_ctx,
352            windows,
353            renderer,
354            depth_texture,
355            depth_view,
356            depth_width: 1,
357            depth_height: 1,
358            frame_count: 0,
359        })
360    });
361}
Source

pub fn id(&self) -> WindowId

Examples found in repository?
examples/multi_window.rs (line 75)
27fn main() {
28    logging::init();
29
30    run_app(|ctx| {
31        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
32
33        let mut windows = HashMap::new();
34
35        // Create 3 windows with different colors
36        let colors = [
37            wgpu::Color {
38                r: 0.8,
39                g: 0.2,
40                b: 0.2,
41                a: 1.0,
42            },
43            wgpu::Color {
44                r: 0.2,
45                g: 0.8,
46                b: 0.2,
47                a: 1.0,
48            },
49            wgpu::Color {
50                r: 0.2,
51                g: 0.2,
52                b: 0.8,
53                a: 1.0,
54            },
55        ];
56
57        for (i, color) in colors.iter().enumerate() {
58            let window = ctx
59                .create_window(WindowDescriptor {
60                    title: format!("Window {} - Multi-Window Example", i + 1),
61                    size: Some(WinitPhysicalSize::new(400.0, 300.0)),
62                    ..Default::default()
63                })
64                .expect("Failed to create window");
65
66            let renderable_window = RenderableWindow::new_with_descriptor(
67                window,
68                graphics_ctx.clone(),
69                WindowContextDescriptor {
70                    format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
71                    ..Default::default()
72                },
73            ).expect("Failed to create renderable window");
74
75            let window_id = renderable_window.id();
76            windows.insert(window_id, (renderable_window, *color));
77        }
78
79        Box::new(App {
80            windows,
81        })
82    });
83}
More examples
Hide additional examples
examples/performance_benchmark.rs (line 59)
36fn main() {
37    logging::init();
38
39    run_app(|ctx| {
40        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
41
42        let window = ctx
43            .create_window(WindowDescriptor {
44                title: "Performance Benchmark - Render Stress Test".to_string(),
45                size: Some(WinitPhysicalSize::new(1280.0, 720.0)),
46                ..Default::default()
47            })
48            .expect("Failed to create window");
49
50        let window = RenderableWindow::new_with_descriptor(
51            window,
52            graphics_ctx.clone(),
53            WindowContextDescriptor {
54                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
55                ..Default::default()
56            },
57        ).expect("Failed to create renderable window");
58
59        let window_id = window.id();
60
61        println!("\n═══════════════════════════════════════════════════════");
62        println!("  ⚡ PERFORMANCE BENCHMARK - Render Stress Test");
63        println!("═══════════════════════════════════════════════════════");
64        println!("  CONTROLS:");
65        println!("    [Space]  Toggle rendering on/off");
66        println!("    [+/-]    Increase/decrease object count");
67        println!("  Starting with 1000 objects");
68        println!("═══════════════════════════════════════════════════════\n");
69
70        Box::new(PerformanceBenchmark {
71            _context: graphics_ctx,
72            window,
73            window_id,
74            object_count: 1000,
75            rendering: true,
76            frame_count: 0,
77            last_fps_time: Instant::now(),
78            fps: 0.0,
79            last_frame_time: 0.0,
80        })
81    });
82}
examples/camera_demo.rs (line 53)
30fn main() {
31    logging::init();
32
33    run_app(|ctx| {
34        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
35
36        let window = ctx
37            .create_window(WindowDescriptor {
38                title: "Camera Demo - View & Projection".to_string(),
39                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
40                ..Default::default()
41            })
42            .expect("Failed to create window");
43
44        let window = RenderableWindow::new_with_descriptor(
45            window,
46            graphics_ctx.clone(),
47            WindowContextDescriptor {
48                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
49                ..Default::default()
50            },
51        ).expect("Failed to create renderable window");
52
53        let window_id = window.id();
54
55        println!("\n═══════════════════════════════════════════════════════");
56        println!("  📹 CAMERA DEMO - View & Projection");
57        println!("═══════════════════════════════════════════════════════");
58        println!("\n  CAMERA API FEATURES:");
59        println!("    • Orthographic cameras (2D, UI, isometric)");
60        println!("    • Perspective cameras (3D scenes)");
61        println!("    • View matrix (position, rotation, look-at)");
62        println!("    • Projection matrix (FOV, aspect, near/far planes)");
63        println!("    • Screen-to-world coordinate conversion");
64        println!("    • Camera movement helpers");
65        println!("\n  CAMERA TYPES:");
66        println!("    • OrthographicCamera - 2D games, UI overlays");
67        println!("      camera.orthographic(left, right, bottom, top, near, far)");
68        println!("    • PerspectiveCamera - 3D scenes");
69        println!("      camera.perspective(fov, aspect, near, far)");
70        println!("\n  Camera API Usage:");
71        println!("    let camera = Camera::new()");
72        println!("        .position(Vec3::new(0.0, 5.0, 10.0))");
73        println!("        .look_at(Vec3::ZERO)");
74        println!("        .perspective(60.0, aspect, 0.1, 100.0);");
75        println!("    let view_proj = camera.view_projection_matrix();");
76        println!("═══════════════════════════════════════════════════════\n");
77
78        tracing::info!("Camera demo initialized");
79
80        Box::new(CameraDemo {
81            _context: graphics_ctx,
82            window,
83            window_id,
84        })
85    });
86}
examples/render_graph_demo.rs (line 52)
29fn main() {
30    logging::init();
31
32    run_app(|ctx| {
33        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
34
35        let window = ctx
36            .create_window(WindowDescriptor {
37                title: "Render Graph Demo - Multi-Pass Rendering".to_string(),
38                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
39                ..Default::default()
40            })
41            .expect("Failed to create window");
42
43        let window = RenderableWindow::new_with_descriptor(
44            window,
45            graphics_ctx.clone(),
46            WindowContextDescriptor {
47                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
48                ..Default::default()
49            },
50        ).expect("Failed to create renderable window");
51
52        let window_id = window.id();
53
54        println!("\n═══════════════════════════════════════════════════════");
55        println!("  🔀 RENDER GRAPH DEMO - Multi-Pass Rendering");
56        println!("═══════════════════════════════════════════════════════");
57        println!("\n  RENDER GRAPH FEATURES:");
58        println!("    • Declarative pass definition");
59        println!("    • Automatic dependency resolution");
60        println!("    • Resource lifetime management");
61        println!("    • Parallel pass execution");
62        println!("    • Automatic optimization");
63        println!("\n  EXAMPLE PIPELINE:");
64        println!("    1. Shadow Pass → depth texture");
65        println!("    2. Geometry Pass → color + normal + depth");
66        println!("    3. Lighting Pass → lit scene");
67        println!("    4. Post-Processing → bloom, tone mapping");
68        println!("    5. UI Pass → final composite");
69        println!("\n  Render Graph API Usage:");
70        println!("    let mut graph = RenderGraph::new();");
71        println!("    graph.add_pass(\"shadow\", shadow_pass_descriptor);");
72        println!("    graph.add_pass(\"geometry\", geometry_pass_descriptor);");
73        println!("    graph.add_dependency(\"lighting\", \"geometry\");");
74        println!("    graph.compile();");
75        println!("    graph.execute(&mut encoder);");
76        println!("═══════════════════════════════════════════════════════\n");
77
78        tracing::info!("Render graph demo initialized");
79
80        Box::new(RenderGraphDemo {
81            _context: graphics_ctx,
82            window,
83            window_id,
84        })
85    });
86}
examples/mesh_primitives.rs (line 52)
29fn main() {
30    logging::init();
31
32    run_app(|ctx| {
33        let graphics_ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
34
35        let window = ctx
36            .create_window(WindowDescriptor {
37                title: "Mesh Primitives Demo - Geometry API".to_string(),
38                size: Some(WinitPhysicalSize::new(1024.0, 768.0)),
39                ..Default::default()
40            })
41            .expect("Failed to create window");
42
43        let window = RenderableWindow::new_with_descriptor(
44            window,
45            graphics_ctx.clone(),
46            WindowContextDescriptor {
47                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
48                ..Default::default()
49            },
50        ).expect("Failed to create renderable window");
51
52        let window_id = window.id();
53
54        println!("\n═══════════════════════════════════════════════════════");
55        println!("  📐 MESH PRIMITIVES DEMO - Geometry API");
56        println!("═══════════════════════════════════════════════════════");
57        println!("\n  MESH API FEATURES:");
58        println!("    • MeshBuilder for custom geometry");
59        println!("    • Primitive generation (cube, sphere, plane, etc.)");
60        println!("    • Flexible vertex formats (Position, Normal, UV, Color)");
61        println!("    • Index buffer optimization");
62        println!("    • Instanced rendering support");
63        println!("\n  EXAMPLE PRIMITIVES:");
64        println!("    • Cube - box with 24 vertices (6 faces × 4 vertices)");
65        println!("    • Sphere - tessellated sphere with UV mapping");
66        println!("    • Plane - quad with optional subdivisions");
67        println!("    • Cylinder - sides + caps");
68        println!("    • Custom - arbitrary vertex/index data");
69        println!("\n  Mesh API Usage:");
70        println!("    let mesh = MeshBuilder::new()");
71        println!("        .with_positions(vertices)");
72        println!("        .with_normals(normals)");
73        println!("        .with_uvs(uvs)");
74        println!("        .with_indices(indices)");
75        println!("        .build(&ctx);");
76        println!("    mesh.draw(&mut pass);");
77        println!("    mesh.draw_instanced(&mut pass, instance_count);");
78        println!("═══════════════════════════════════════════════════════\n");
79
80        tracing::info!("Mesh primitives demo initialized");
81
82        Box::new(MeshPrimitivesDemo {
83            _context: graphics_ctx,
84            window,
85            window_id,
86        })
87    });
88}
examples/batched_renderer.rs (line 318)
275fn main() {
276    logging::init();
277
278    run_app(|ctx| {
279        let tier_override = parse_tier();
280
281        // Use the capability API to configure GPU requirements.
282        // For auto-detect, request the best capability (graceful degradation).
283        // For a specific tier, require that tier's capability.
284        let descriptor = match tier_override {
285            None => GraphicsContextDescriptor::new()
286                .request_capability::<BestBatchCapability2D>(),
287            Some(RenderTier::Direct) => GraphicsContextDescriptor::new()
288                .require_capability::<DirectBatchCapability2D>(),
289            Some(RenderTier::Indirect) => GraphicsContextDescriptor::new()
290                .require_capability::<IndirectBatchCapability2D>(),
291            Some(RenderTier::Bindless) => GraphicsContextDescriptor::new()
292                .require_capability::<BindlessBatchCapability2D>(),
293        };
294        let graphics_ctx =
295            pollster::block_on(GraphicsContext::new_owned_with_descriptor(descriptor))
296                .expect("Failed to create graphics context");
297
298        let window = ctx
299            .create_window(WindowDescriptor {
300                title: "Batched Renderer Example".to_string(),
301                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
302                ..Default::default()
303            })
304            .expect("Failed to create window");
305
306        let surface_format = wgpu::TextureFormat::Bgra8UnormSrgb;
307
308        let renderable_window = RenderableWindow::new_with_descriptor(
309            window,
310            graphics_ctx.clone(),
311            WindowContextDescriptor {
312                format: Some(surface_format),
313                ..Default::default()
314            },
315        )
316        .expect("Failed to create renderable window");
317
318        let window_id = renderable_window.id();
319
320        let renderer = create_batch_renderer_2d(
321            graphics_ctx.clone(),
322            surface_format,
323            tier_override,
324        );
325
326        tracing::info!("Using render tier: {}", renderer.tier());
327
328        // Create initial depth buffer
329        let depth_texture = graphics_ctx
330            .device()
331            .create_texture(&wgpu::TextureDescriptor {
332                label: Some("example_depth"),
333                size: wgpu::Extent3d {
334                    width: 1,
335                    height: 1,
336                    depth_or_array_layers: 1,
337                },
338                mip_level_count: 1,
339                sample_count: 1,
340                dimension: wgpu::TextureDimension::D2,
341                format: DEPTH_FORMAT,
342                usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
343                view_formats: &[],
344            });
345        let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
346
347        let mut windows = HashMap::new();
348        windows.insert(window_id, renderable_window);
349
350        Box::new(App {
351            context: graphics_ctx,
352            windows,
353            renderer,
354            depth_texture,
355            depth_view,
356            depth_width: 1,
357            depth_height: 1,
358            frame_count: 0,
359        })
360    });
361}
Source

pub fn window(&self) -> &Window

Source

pub fn context(&self) -> &WindowContext

Examples found in repository?
examples/sprite_sheet.rs (line 381)
367    fn update(&mut self, _ctx: &mut astrelis_winit::app::AppCtx, _time: &astrelis_winit::FrameTime) {
368        let now = Instant::now();
369        let dt = now.duration_since(self.last_update).as_secs_f32();
370        self.last_update = now;
371
372        // Update animation
373        if self.animation.update(dt) {
374            // Frame changed - update vertex buffer with new UVs
375            let frame = self.animation.current_frame();
376            let uv = self.sprite_sheet.sprite_uv(frame);
377            let vertices = create_quad_vertices(uv.u_min, uv.v_min, uv.u_max, uv.v_max);
378            
379            // Get context from first window
380            if let Some(window) = self.windows.values().next() {
381                window.context().graphics_context().queue().write_buffer(
382                    &self.vertex_buffer,
383                    0,
384                    bytemuck::cast_slice(&vertices),
385                );
386            }
387        }
388    }
Source

pub fn context_mut(&mut self) -> &mut WindowContext

Source

pub fn surface_format(&self) -> TextureFormat

Get the surface texture format.

This is the format that render pipelines must use when rendering to this window’s surface. Pass this to renderer constructors like LineRenderer::new.

Source

pub fn resized(&mut self, new_size: LogicalSize<u32>)

Handle window resize event (logical size).

Examples found in repository?
examples/camera_demo.rs (line 98)
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 100)
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 98)
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/material_system.rs (line 115)
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 403)
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    }
examples/image_blitting.rs (line 457)
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    }
Source

pub fn resized_physical(&mut self, new_size: PhysicalSize<u32>)

Handle window resize event (physical size).

Source

pub fn physical_size(&self) -> PhysicalSize<u32>

Get the physical size of the window.

Examples found in repository?
examples/batched_renderer.rs (line 393)
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 scale_factor(&self) -> ScaleFactor

Get the scale factor.

Source

pub fn viewport(&self) -> Viewport

Get the viewport for this window.

Source

pub fn set_gpu_profiler(&mut self, profiler: Arc<GpuFrameProfiler>)

Attach a GPU profiler to this window for automatic render pass profiling.

Once set, all frames created via begin_drawing will automatically:

  • Create GPU profiling scopes around render passes
  • Resolve timestamp queries before command submission
  • End the profiler frame after queue submit
§Example
let profiler = Arc::new(GpuFrameProfiler::new(&graphics_ctx)?);
window.set_gpu_profiler(profiler);

// Now all frames are automatically profiled:
let mut frame = window.begin_drawing();
frame.clear_and_render(RenderTarget::Surface, Color::BLACK, |pass| {
    // GPU scope "main_pass" is automatically active
});
frame.finish(); // auto: resolve_queries -> submit -> end_frame
Source

pub fn remove_gpu_profiler(&mut self) -> Option<Arc<GpuFrameProfiler>>

Remove the GPU profiler from this window.

Returns the profiler if one was attached.

Source

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

Get a reference to the GPU profiler, if one is attached.

Methods from Deref<Target = WindowContext>§

Source

pub fn resized(&mut self, new_size: LogicalSize<u32>)

Handle window resize event (logical size).

Source

pub fn resized_physical(&mut self, new_size: PhysicalSize<u32>)

Handle window resize event (physical size).

Source

pub fn window(&self) -> &Window

Source

pub fn graphics_context(&self) -> &GraphicsContext

Examples found in repository?
examples/sprite_sheet.rs (line 381)
367    fn update(&mut self, _ctx: &mut astrelis_winit::app::AppCtx, _time: &astrelis_winit::FrameTime) {
368        let now = Instant::now();
369        let dt = now.duration_since(self.last_update).as_secs_f32();
370        self.last_update = now;
371
372        // Update animation
373        if self.animation.update(dt) {
374            // Frame changed - update vertex buffer with new UVs
375            let frame = self.animation.current_frame();
376            let uv = self.sprite_sheet.sprite_uv(frame);
377            let vertices = create_quad_vertices(uv.u_min, uv.v_min, uv.u_max, uv.v_max);
378            
379            // Get context from first window
380            if let Some(window) = self.windows.values().next() {
381                window.context().graphics_context().queue().write_buffer(
382                    &self.vertex_buffer,
383                    0,
384                    bytemuck::cast_slice(&vertices),
385                );
386            }
387        }
388    }
Source

pub fn surface(&self) -> &Surface<'static>

Source

pub fn surface_config(&self) -> &SurfaceConfiguration

Source

pub fn surface_format(&self) -> TextureFormat

Get the surface texture format.

This is the format that render pipelines must use when rendering to this window’s surface. Pass this to renderer constructors like LineRenderer::new.

Source

pub fn logical_size(&self) -> LogicalSize<u32>

Get the logical size of the window.

Source

pub fn physical_size(&self) -> PhysicalSize<u32>

Get the physical size of the window.

Source

pub fn logical_size_f32(&self) -> LogicalSize<f32>

Get the logical size as f32.

Source

pub fn physical_size_f32(&self) -> PhysicalSize<f32>

Get the physical size as f32.

Source

pub fn reconfigure_surface(&mut self, config: SurfaceConfiguration)

Reconfigure the surface with a new configuration.

Trait Implementations§

Source§

impl Deref for RenderableWindow

Source§

type Target = WindowContext

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl DerefMut for RenderableWindow

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl WindowBackend for RenderableWindow

Source§

type FrameContext = FrameContext

Source§

type Error = GraphicsError

Source§

fn try_begin_drawing(&mut self) -> Result<Self::FrameContext, Self::Error>

Begin drawing a new frame. Read more
Source§

fn begin_drawing(&mut self) -> Self::FrameContext
where Self::Error: Debug,

Begin drawing a new frame, panicking on error. 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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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,