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 288)
278fn main() {
279    logging::init();
280
281    run_app(|ctx| {
282        let tier_override = parse_tier();
283
284        // Use the capability API to configure GPU requirements.
285        // For auto-detect, request the best capability (graceful degradation).
286        // For a specific tier, require that tier's capability.
287        let descriptor = match tier_override {
288            None => GraphicsContextDescriptor::new().request_capability::<BestBatchCapability2D>(),
289            Some(RenderTier::Direct) => {
290                GraphicsContextDescriptor::new().require_capability::<DirectBatchCapability2D>()
291            }
292            Some(RenderTier::Indirect) => {
293                GraphicsContextDescriptor::new().require_capability::<IndirectBatchCapability2D>()
294            }
295            Some(RenderTier::Bindless) => {
296                GraphicsContextDescriptor::new().require_capability::<BindlessBatchCapability2D>()
297            }
298        };
299        let graphics_ctx =
300            pollster::block_on(GraphicsContext::new_owned_with_descriptor(descriptor))
301                .expect("Failed to create graphics context");
302
303        let window = ctx
304            .create_window(WindowDescriptor {
305                title: "Batched Renderer Example".to_string(),
306                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
307                ..Default::default()
308            })
309            .expect("Failed to create window");
310
311        let surface_format = wgpu::TextureFormat::Bgra8UnormSrgb;
312
313        let renderable_window = RenderWindowBuilder::new()
314            .color_format(surface_format)
315            .with_depth_default()
316            .build(window, graphics_ctx.clone())
317            .expect("Failed to create render window");
318
319        let window_id = renderable_window.id();
320
321        let renderer =
322            create_batch_renderer_2d(graphics_ctx.clone(), surface_format, tier_override);
323
324        tracing::info!("Using render tier: {}", renderer.tier());
325
326        // Create initial depth buffer
327        let depth_texture = graphics_ctx
328            .device()
329            .create_texture(&wgpu::TextureDescriptor {
330                label: Some("example_depth"),
331                size: wgpu::Extent3d {
332                    width: 1,
333                    height: 1,
334                    depth_or_array_layers: 1,
335                },
336                mip_level_count: 1,
337                sample_count: 1,
338                dimension: wgpu::TextureDimension::D2,
339                format: DEPTH_FORMAT,
340                usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
341                view_formats: &[],
342            });
343        let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
344
345        let mut windows = HashMap::new();
346        windows.insert(window_id, renderable_window);
347
348        Box::new(App {
349            context: graphics_ctx,
350            windows,
351            renderer,
352            depth_texture,
353            depth_view,
354            depth_width: 1,
355            depth_height: 1,
356            frame_count: 0,
357        })
358    });
359}
More examples
Hide additional examples
examples/profiling_demo.rs (line 49)
40fn main() {
41    logging::init();
42    init_profiling(ProfilingBackend::PuffinHttp);
43
44    run_app(|ctx| {
45        profile_function!();
46
47        // Request TIMESTAMP_QUERY for GPU profiling (best-effort, won't fail if unavailable)
48        let graphics_ctx = pollster::block_on(GraphicsContext::new_owned_with_descriptor(
49            GraphicsContextDescriptor::new()
50                .request_capability::<astrelis_render::gpu_profiling::GpuFrameProfiler>(),
51        ))
52        .expect("Failed to create graphics context");
53
54        let window = ctx
55            .create_window(WindowDescriptor {
56                title: "Profiling Demo — CPU + GPU".to_string(),
57                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
58                ..Default::default()
59            })
60            .expect("Failed to create window");
61
62        #[allow(unused_mut)]
63        let mut window = RenderWindowBuilder::new()
64            .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
65            .with_depth_default()
66            .build(window, graphics_ctx.clone())
67            .expect("Failed to create render window");
68
69        let window_id = window.id();
70
71        // Attach GPU profiler to the window — all frames will be automatically profiled
72        let has_gpu_profiling;
73        #[cfg(feature = "gpu-profiling")]
74        {
75            match astrelis_render::gpu_profiling::GpuFrameProfiler::new(&graphics_ctx) {
76                Ok(profiler) => {
77                    let has_timestamps = profiler.has_timestamp_queries();
78                    window.set_gpu_profiler(Arc::new(profiler));
79                    has_gpu_profiling = true;
80                    if has_timestamps {
81                        println!("  GPU profiling: enabled with TIMESTAMP_QUERY (full timing)");
82                    } else {
83                        println!("  GPU profiling: enabled (debug groups only, no timing data)");
84                        println!("                 TIMESTAMP_QUERY not supported by this GPU");
85                    }
86                }
87                Err(e) => {
88                    has_gpu_profiling = false;
89                    tracing::warn!("Failed to create GPU profiler: {e}. GPU profiling disabled.");
90                    println!("  GPU profiling: failed to create profiler");
91                }
92            }
93        }
94        #[cfg(not(feature = "gpu-profiling"))]
95        {
96            has_gpu_profiling = false;
97        }
98
99        println!();
100        println!("═══════════════════════════════════════════════════");
101        println!("  PROFILING DEMO — CPU + GPU");
102        println!("═══════════════════════════════════════════════════");
103        println!();
104        println!("  CPU profiling: enabled (puffin)");
105        if !has_gpu_profiling {
106            #[cfg(not(feature = "gpu-profiling"))]
107            println!("  GPU profiling: disabled (compile with --features gpu-profiling)");
108        }
109        println!();
110        println!("  Open puffin_viewer at 127.0.0.1:8585 to see the flame graph.");
111        println!("  Install with: cargo install puffin_viewer");
112        println!("═══════════════════════════════════════════════════");
113        println!();
114
115        Box::new(ProfilingDemo {
116            context: graphics_ctx,
117            window,
118            window_id,
119            frame_count: 0,
120        })
121    });
122}
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 290)
278fn main() {
279    logging::init();
280
281    run_app(|ctx| {
282        let tier_override = parse_tier();
283
284        // Use the capability API to configure GPU requirements.
285        // For auto-detect, request the best capability (graceful degradation).
286        // For a specific tier, require that tier's capability.
287        let descriptor = match tier_override {
288            None => GraphicsContextDescriptor::new().request_capability::<BestBatchCapability2D>(),
289            Some(RenderTier::Direct) => {
290                GraphicsContextDescriptor::new().require_capability::<DirectBatchCapability2D>()
291            }
292            Some(RenderTier::Indirect) => {
293                GraphicsContextDescriptor::new().require_capability::<IndirectBatchCapability2D>()
294            }
295            Some(RenderTier::Bindless) => {
296                GraphicsContextDescriptor::new().require_capability::<BindlessBatchCapability2D>()
297            }
298        };
299        let graphics_ctx =
300            pollster::block_on(GraphicsContext::new_owned_with_descriptor(descriptor))
301                .expect("Failed to create graphics context");
302
303        let window = ctx
304            .create_window(WindowDescriptor {
305                title: "Batched Renderer Example".to_string(),
306                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
307                ..Default::default()
308            })
309            .expect("Failed to create window");
310
311        let surface_format = wgpu::TextureFormat::Bgra8UnormSrgb;
312
313        let renderable_window = RenderWindowBuilder::new()
314            .color_format(surface_format)
315            .with_depth_default()
316            .build(window, graphics_ctx.clone())
317            .expect("Failed to create render window");
318
319        let window_id = renderable_window.id();
320
321        let renderer =
322            create_batch_renderer_2d(graphics_ctx.clone(), surface_format, tier_override);
323
324        tracing::info!("Using render tier: {}", renderer.tier());
325
326        // Create initial depth buffer
327        let depth_texture = graphics_ctx
328            .device()
329            .create_texture(&wgpu::TextureDescriptor {
330                label: Some("example_depth"),
331                size: wgpu::Extent3d {
332                    width: 1,
333                    height: 1,
334                    depth_or_array_layers: 1,
335                },
336                mip_level_count: 1,
337                sample_count: 1,
338                dimension: wgpu::TextureDimension::D2,
339                format: DEPTH_FORMAT,
340                usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
341                view_formats: &[],
342            });
343        let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
344
345        let mut windows = HashMap::new();
346        windows.insert(window_id, renderable_window);
347
348        Box::new(App {
349            context: graphics_ctx,
350            windows,
351            renderer,
352            depth_texture,
353            depth_view,
354            depth_width: 1,
355            depth_height: 1,
356            frame_count: 0,
357        })
358    });
359}
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 288)
278fn main() {
279    logging::init();
280
281    run_app(|ctx| {
282        let tier_override = parse_tier();
283
284        // Use the capability API to configure GPU requirements.
285        // For auto-detect, request the best capability (graceful degradation).
286        // For a specific tier, require that tier's capability.
287        let descriptor = match tier_override {
288            None => GraphicsContextDescriptor::new().request_capability::<BestBatchCapability2D>(),
289            Some(RenderTier::Direct) => {
290                GraphicsContextDescriptor::new().require_capability::<DirectBatchCapability2D>()
291            }
292            Some(RenderTier::Indirect) => {
293                GraphicsContextDescriptor::new().require_capability::<IndirectBatchCapability2D>()
294            }
295            Some(RenderTier::Bindless) => {
296                GraphicsContextDescriptor::new().require_capability::<BindlessBatchCapability2D>()
297            }
298        };
299        let graphics_ctx =
300            pollster::block_on(GraphicsContext::new_owned_with_descriptor(descriptor))
301                .expect("Failed to create graphics context");
302
303        let window = ctx
304            .create_window(WindowDescriptor {
305                title: "Batched Renderer Example".to_string(),
306                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
307                ..Default::default()
308            })
309            .expect("Failed to create window");
310
311        let surface_format = wgpu::TextureFormat::Bgra8UnormSrgb;
312
313        let renderable_window = RenderWindowBuilder::new()
314            .color_format(surface_format)
315            .with_depth_default()
316            .build(window, graphics_ctx.clone())
317            .expect("Failed to create render window");
318
319        let window_id = renderable_window.id();
320
321        let renderer =
322            create_batch_renderer_2d(graphics_ctx.clone(), surface_format, tier_override);
323
324        tracing::info!("Using render tier: {}", renderer.tier());
325
326        // Create initial depth buffer
327        let depth_texture = graphics_ctx
328            .device()
329            .create_texture(&wgpu::TextureDescriptor {
330                label: Some("example_depth"),
331                size: wgpu::Extent3d {
332                    width: 1,
333                    height: 1,
334                    depth_or_array_layers: 1,
335                },
336                mip_level_count: 1,
337                sample_count: 1,
338                dimension: wgpu::TextureDimension::D2,
339                format: DEPTH_FORMAT,
340                usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
341                view_formats: &[],
342            });
343        let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
344
345        let mut windows = HashMap::new();
346        windows.insert(window_id, renderable_window);
347
348        Box::new(App {
349            context: graphics_ctx,
350            windows,
351            renderer,
352            depth_texture,
353            depth_view,
354            depth_width: 1,
355            depth_height: 1,
356            frame_count: 0,
357        })
358    });
359}
More examples
Hide additional examples
examples/profiling_demo.rs (line 50)
40fn main() {
41    logging::init();
42    init_profiling(ProfilingBackend::PuffinHttp);
43
44    run_app(|ctx| {
45        profile_function!();
46
47        // Request TIMESTAMP_QUERY for GPU profiling (best-effort, won't fail if unavailable)
48        let graphics_ctx = pollster::block_on(GraphicsContext::new_owned_with_descriptor(
49            GraphicsContextDescriptor::new()
50                .request_capability::<astrelis_render::gpu_profiling::GpuFrameProfiler>(),
51        ))
52        .expect("Failed to create graphics context");
53
54        let window = ctx
55            .create_window(WindowDescriptor {
56                title: "Profiling Demo — CPU + GPU".to_string(),
57                size: Some(WinitPhysicalSize::new(800.0, 600.0)),
58                ..Default::default()
59            })
60            .expect("Failed to create window");
61
62        #[allow(unused_mut)]
63        let mut window = RenderWindowBuilder::new()
64            .color_format(wgpu::TextureFormat::Bgra8UnormSrgb)
65            .with_depth_default()
66            .build(window, graphics_ctx.clone())
67            .expect("Failed to create render window");
68
69        let window_id = window.id();
70
71        // Attach GPU profiler to the window — all frames will be automatically profiled
72        let has_gpu_profiling;
73        #[cfg(feature = "gpu-profiling")]
74        {
75            match astrelis_render::gpu_profiling::GpuFrameProfiler::new(&graphics_ctx) {
76                Ok(profiler) => {
77                    let has_timestamps = profiler.has_timestamp_queries();
78                    window.set_gpu_profiler(Arc::new(profiler));
79                    has_gpu_profiling = true;
80                    if has_timestamps {
81                        println!("  GPU profiling: enabled with TIMESTAMP_QUERY (full timing)");
82                    } else {
83                        println!("  GPU profiling: enabled (debug groups only, no timing data)");
84                        println!("                 TIMESTAMP_QUERY not supported by this GPU");
85                    }
86                }
87                Err(e) => {
88                    has_gpu_profiling = false;
89                    tracing::warn!("Failed to create GPU profiler: {e}. GPU profiling disabled.");
90                    println!("  GPU profiling: failed to create profiler");
91                }
92            }
93        }
94        #[cfg(not(feature = "gpu-profiling"))]
95        {
96            has_gpu_profiling = false;
97        }
98
99        println!();
100        println!("═══════════════════════════════════════════════════");
101        println!("  PROFILING DEMO — CPU + GPU");
102        println!("═══════════════════════════════════════════════════");
103        println!();
104        println!("  CPU profiling: enabled (puffin)");
105        if !has_gpu_profiling {
106            #[cfg(not(feature = "gpu-profiling"))]
107            println!("  GPU profiling: disabled (compile with --features gpu-profiling)");
108        }
109        println!();
110        println!("  Open puffin_viewer at 127.0.0.1:8585 to see the flame graph.");
111        println!("  Install with: cargo install puffin_viewer");
112        println!("═══════════════════════════════════════════════════");
113        println!();
114
115        Box::new(ProfilingDemo {
116            context: graphics_ctx,
117            window,
118            window_id,
119            frame_count: 0,
120        })
121    });
122}

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,