Skip to main content

GraphicsContextDescriptor

Struct GraphicsContextDescriptor 

Source
pub struct GraphicsContextDescriptor {
    pub backends: Backends,
    pub power_preference: PowerPreference,
    pub force_fallback_adapter: bool,
    pub required_gpu_features: GpuFeatures,
    pub requested_gpu_features: GpuFeatures,
    pub additional_wgpu_features: Features,
    pub limits: Limits,
    pub label: Option<&'static str>,
}
Expand description

Descriptor for configuring graphics context creation.

Fields§

§backends: Backends

GPU backends to use

§power_preference: PowerPreference

Power preference for adapter selection

§force_fallback_adapter: bool

Whether to force fallback adapter

§required_gpu_features: GpuFeatures

Required GPU features (panics if not available).

Use this for features that your application cannot function without.

§requested_gpu_features: GpuFeatures

Requested GPU features (best-effort, logs warning if unavailable).

Use this for features that would be nice to have but are not essential.

§additional_wgpu_features: Features

Additional raw wgpu features to enable (for features not covered by GpuFeatures).

§limits: Limits

Required device limits

§label: Option<&'static str>

Optional label for debugging

Implementations§

Source§

impl GraphicsContextDescriptor

Source

pub fn new() -> Self

Create a new descriptor with default settings.

Examples found in repository?
examples/batched_renderer.rs (line 285)
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}
More examples
Hide additional examples
examples/profiling_demo.rs (line 48)
39fn main() {
40    logging::init();
41    init_profiling(ProfilingBackend::PuffinHttp);
42
43    run_app(|ctx| {
44        profile_function!();
45
46        // Request TIMESTAMP_QUERY for GPU profiling (best-effort, won't fail if unavailable)
47        let graphics_ctx = pollster::block_on(GraphicsContext::new_owned_with_descriptor(
48            GraphicsContextDescriptor::new()
49                .request_capability::<astrelis_render::gpu_profiling::GpuFrameProfiler>(),
50        ))
51        .expect("Failed to create graphics context");
52
53        let window = ctx
54            .create_window(WindowDescriptor {
55                title: "Profiling Demo — CPU + GPU".to_string(),
56                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
57                ..Default::default()
58            })
59            .expect("Failed to create window");
60
61        #[allow(unused_mut)]
62        let mut window = RenderableWindow::new_with_descriptor(
63            window,
64            graphics_ctx.clone(),
65            WindowContextDescriptor {
66                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
67                ..Default::default()
68            },
69        )
70        .expect("Failed to create renderable window");
71
72        let window_id = window.id();
73
74        // Attach GPU profiler to the window — all frames will be automatically profiled
75        let has_gpu_profiling;
76        #[cfg(feature = "gpu-profiling")]
77        {
78            match astrelis_render::gpu_profiling::GpuFrameProfiler::new(&graphics_ctx) {
79                Ok(profiler) => {
80                    let has_timestamps = profiler.has_timestamp_queries();
81                    window.set_gpu_profiler(Arc::new(profiler));
82                    has_gpu_profiling = true;
83                    if has_timestamps {
84                        println!("  GPU profiling: enabled with TIMESTAMP_QUERY (full timing)");
85                    } else {
86                        println!("  GPU profiling: enabled (debug groups only, no timing data)");
87                        println!("                 TIMESTAMP_QUERY not supported by this GPU");
88                    }
89                }
90                Err(e) => {
91                    has_gpu_profiling = false;
92                    tracing::warn!("Failed to create GPU profiler: {e}. GPU profiling disabled.");
93                    println!("  GPU profiling: failed to create profiler");
94                }
95            }
96        }
97        #[cfg(not(feature = "gpu-profiling"))]
98        {
99            has_gpu_profiling = false;
100        }
101
102        println!();
103        println!("═══════════════════════════════════════════════════");
104        println!("  PROFILING DEMO — CPU + GPU");
105        println!("═══════════════════════════════════════════════════");
106        println!();
107        println!("  CPU profiling: enabled (puffin)");
108        if !has_gpu_profiling {
109            #[cfg(not(feature = "gpu-profiling"))]
110            println!("  GPU profiling: disabled (compile with --features gpu-profiling)");
111        }
112        println!();
113        println!("  Open puffin_viewer at 127.0.0.1:8585 to see the flame graph.");
114        println!("  Install with: cargo install puffin_viewer");
115        println!("═══════════════════════════════════════════════════");
116        println!();
117
118        Box::new(ProfilingDemo {
119            context: graphics_ctx,
120            window,
121            window_id,
122            frame_count: 0,
123        })
124    });
125}
Source

pub fn require_features(self, features: GpuFeatures) -> Self

Set required GPU features (panics if not available).

Source

pub fn request_features(self, features: GpuFeatures) -> Self

Set requested GPU features (best-effort, warns if unavailable).

Source

pub fn with_required_features(self, features: GpuFeatures) -> Self

Add additional required features.

Source

pub fn with_requested_features(self, features: GpuFeatures) -> Self

Add additional requested features.

Source

pub fn with_wgpu_features(self, features: Features) -> Self

Set additional raw wgpu features (for features not covered by GpuFeatures).

Source

pub fn power_preference(self, preference: PowerPreference) -> Self

Set the power preference.

Source

pub fn backends(self, backends: Backends) -> Self

Set the backends to use.

Source

pub fn limits(self, limits: Limits) -> Self

Set the device limits.

Source

pub fn label(self, label: &'static str) -> Self

Set the debug label.

Source

pub fn require_capability<T: RenderCapability>(self) -> Self

Require a capability — its features become required, limits are merged.

If the adapter doesn’t support the capability’s required features, device creation will fail with GraphicsError::MissingRequiredFeatures.

§Example
use astrelis_render::{GraphicsContextDescriptor, GpuProfiler};

let desc = GraphicsContextDescriptor::new()
    .require_capability::<GpuProfiler>();
Examples found in repository?
examples/batched_renderer.rs (line 288)
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 request_capability<T: RenderCapability>(self) -> Self

Request a capability — required features stay required, requested features stay optional, limits are merged.

The capability’s required features are added as required, and its requested features are added as requested (best-effort). Limits are merged and clamped to adapter capabilities during device creation.

§Example
use astrelis_render::GraphicsContextDescriptor;
use astrelis_render::batched::BestBatchCapability;

let desc = GraphicsContextDescriptor::new()
    .request_capability::<BestBatchCapability>();
Examples found in repository?
examples/batched_renderer.rs (line 286)
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}
More examples
Hide additional examples
examples/profiling_demo.rs (line 49)
39fn main() {
40    logging::init();
41    init_profiling(ProfilingBackend::PuffinHttp);
42
43    run_app(|ctx| {
44        profile_function!();
45
46        // Request TIMESTAMP_QUERY for GPU profiling (best-effort, won't fail if unavailable)
47        let graphics_ctx = pollster::block_on(GraphicsContext::new_owned_with_descriptor(
48            GraphicsContextDescriptor::new()
49                .request_capability::<astrelis_render::gpu_profiling::GpuFrameProfiler>(),
50        ))
51        .expect("Failed to create graphics context");
52
53        let window = ctx
54            .create_window(WindowDescriptor {
55                title: "Profiling Demo — CPU + GPU".to_string(),
56                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
57                ..Default::default()
58            })
59            .expect("Failed to create window");
60
61        #[allow(unused_mut)]
62        let mut window = RenderableWindow::new_with_descriptor(
63            window,
64            graphics_ctx.clone(),
65            WindowContextDescriptor {
66                format: Some(wgpu::TextureFormat::Bgra8UnormSrgb),
67                ..Default::default()
68            },
69        )
70        .expect("Failed to create renderable window");
71
72        let window_id = window.id();
73
74        // Attach GPU profiler to the window — all frames will be automatically profiled
75        let has_gpu_profiling;
76        #[cfg(feature = "gpu-profiling")]
77        {
78            match astrelis_render::gpu_profiling::GpuFrameProfiler::new(&graphics_ctx) {
79                Ok(profiler) => {
80                    let has_timestamps = profiler.has_timestamp_queries();
81                    window.set_gpu_profiler(Arc::new(profiler));
82                    has_gpu_profiling = true;
83                    if has_timestamps {
84                        println!("  GPU profiling: enabled with TIMESTAMP_QUERY (full timing)");
85                    } else {
86                        println!("  GPU profiling: enabled (debug groups only, no timing data)");
87                        println!("                 TIMESTAMP_QUERY not supported by this GPU");
88                    }
89                }
90                Err(e) => {
91                    has_gpu_profiling = false;
92                    tracing::warn!("Failed to create GPU profiler: {e}. GPU profiling disabled.");
93                    println!("  GPU profiling: failed to create profiler");
94                }
95            }
96        }
97        #[cfg(not(feature = "gpu-profiling"))]
98        {
99            has_gpu_profiling = false;
100        }
101
102        println!();
103        println!("═══════════════════════════════════════════════════");
104        println!("  PROFILING DEMO — CPU + GPU");
105        println!("═══════════════════════════════════════════════════");
106        println!();
107        println!("  CPU profiling: enabled (puffin)");
108        if !has_gpu_profiling {
109            #[cfg(not(feature = "gpu-profiling"))]
110            println!("  GPU profiling: disabled (compile with --features gpu-profiling)");
111        }
112        println!();
113        println!("  Open puffin_viewer at 127.0.0.1:8585 to see the flame graph.");
114        println!("  Install with: cargo install puffin_viewer");
115        println!("═══════════════════════════════════════════════════");
116        println!();
117
118        Box::new(ProfilingDemo {
119            context: graphics_ctx,
120            window,
121            window_id,
122            frame_count: 0,
123        })
124    });
125}

Trait Implementations§

Source§

impl Default for GraphicsContextDescriptor

Source§

fn default() -> Self

Returns the “default value” for a type. 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<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,