Skip to main content

RenderContext

Struct RenderContext 

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

Owns the wgpu::Instance and the single logical device this crate’s consumers render with.

A single RenderContext is shared across every surface a shell creates (frust is single-window); the device is created lazily on the first surface and reused across surface loss/recreation (rotation, backgrounding) since a logical device is display-independent. RenderContext::new performs no adapter enumeration at all, so a host may build one early (before it has a window, or on a thread that will never render) and pay for the device only at the first surface — or at an explicit ensure_device_headless pre-init.

Implementations§

Source§

impl RenderContext

Source

pub fn new() -> RenderContext

Creates a context with a fresh wgpu Instance and no device yet (the device is created lazily on first surface creation).

The instance flags come from the build configuration (InstanceFlags::from_build_config, which turns DEBUG/VALIDATION on in debug builds) plus the standard WGPU_* environment overrides. When actually running on an Android emulator they are then run through effective_instance_flags, which strips DEBUG/VALIDATION: the DEBUG flag makes wgpu enable VK_EXT_debug_utils and set object-name labels via vkSetDebugUtilsObjectNameEXT, and the emulator’s gfxstream Vulkan HAL (vulkan.ranchu.so) segfaults inside that entry point during adapter enumeration (observed crash: #00 vulkan.ranchu.so vk_common_SetDebugUtilsObjectNameEXT) — the same class of debug-utils fragility a MoltenVK Vulkan backend is also known to have. Debug object labels are only a developer convenience, so dropping them on the emulator is a safe way to keep GPU bring-up alive there while leaving physical devices’ validation safety net — and desktop behavior — untouched.

Source

pub fn with_options(options: ContextOptions) -> RenderContext

Self::new with an explicit ContextOptions — a headless harness that must label its device or pin one backend regardless of the ambient environment. Every shell takes new()’s defaults instead.

Source

pub fn surface_factory(&self) -> SurfaceFactory

A cloneable SurfaceFactory sharing this context’s wgpu Instance, for creating a DetachedSurface on the windowing/main thread when the context itself lives on the render thread (the render-thread split). The surface a clone produces stays compatible with the device this context creates, since both share one Arc-backed instance.

Source

pub async fn device(&mut self) -> Result<&DeviceHandle, Error>

The logical device, creating it on first call and returning the same one afterwards.

Adapter selection goes through wgpu::util::initialize_adapter_from_env_or_default, so WGPU_ADAPTER_NAME/WGPU_POWER_PREF pick the adapter on a host with more than one — the only way to pin a specific GPU on a multi-adapter machine.

§Errors

When no adapter is available at all, or when the device request the adapter’s own limits were computed for is nonetheless refused. Both are terminal for GPU rendering; neither is retryable by calling again.

Source

pub fn caps(&self) -> Option<&TierCaps>

What the live device’s adapter reported, or None while the device is still uncreated — capabilities are an adapter’s answer, and no adapter has been selected before the first device creation.

Source

pub fn pipeline_cache_supported(&self) -> bool

Whether the live device was created with wgpu::Features::PIPELINE_CACHE.

wgpu only implements the persisted pipeline cache on Vulkan — every Vulkan adapter advertises it (Android, Linux, Windows-on-Vulkan); Metal and DX12 adapters never do, so it is absent there and create_pipeline_cache returns None — the renderer then behaves exactly as it did before this path existed. Panics if no surface (and thus no device) has been created yet.

Source

pub fn adapter_cache_key(&self) -> String

The adapter fingerprint a persisted pipeline-cache blob is tagged with (see crate::pipeline_cache). Panics if no device has been created yet.

Source

pub async fn ensure_device_headless(&mut self) -> Result<(), Error>

Create the logical device before any surface exists, so the wgpu instance/adapter/device bring-up can run on a background thread kicked at native-library load (JNI_OnLoad) and be joined by nativeInit instead of running serially after surfaceCreated. Idempotent: a no-op when a device already exists.

§Android singular-adapter assumption

Requesting the adapter with compatible_surface: None picks wgpu’s default adapter rather than one filtered to a specific surface. On Android the Vulkan backend exposes a single physical device, so the adapter chosen here is the same one a later surface-filtered request would pick, and ensure_device’s is_surface_supported reuse check accepts it — the surface created at nativeInit reuses this device with no rebuild. On a hypothetical multi-adapter device where the pre-init adapter did not support the eventual surface, ensure_device simply rebuilds the device against that surface (still correct, just without the overlap win). This is the sole production caller that passes None below; desktop/iOS create their device through the surface path and never invoke it.

Trait Implementations§

Source§

impl Default for RenderContext

Source§

fn default() -> RenderContext

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

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> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,