pub struct DeferredContext { /* private fields */ }Expand description
Defer the contstruction of the RenderContext until a surface is
constructed.
WebGL really screws up the normal workflow of “first create your wgpu
handles, then make windows and stuff”, because creating the
[wgpu::Adapter] requires a [wgpu::Surface] to be passed in from
[wgpu::Instance] and [winit::window::Window]. To top it off, this
annoying back-and-forth involves some async functions.
On wasm, this struct caches a builder and constructs the RenderContext
in a JS thread oppurtunistically when it is used to construct a
SurfaceWindow.
Native platforms block the thread when constructing, pollster doesn’t seem
to get along with wasm.
See example usage below. There’s a bit of jumping through hoops, but most of it is handled in the background.
impl ApplicationHandler for YourApp {
fn resume(&mut self, event_loop: &ActiveEventLoop) {
// Create a window and provide the surface to the deferred context to start building.
// In the worst case (wasm), at this point it will have an unconfigured surface and no config.
let window = self.window.get_or_insert_with(|| {
let attributes = WindowAttributes::default().with_canvas(get_webgl_canvas());
// Will additionally try to configure surface on native.
self.deferred_context.create_window(event_loop, attributes, Default::default())
.expect("Couldn't create window");
});
// Can't do much else until we have a valid context, which may take until the next
// function call to finish building. Move on to main loop.
self.suspended = false;
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: _, event: _) {
if self.suspended { return; }
let context = match self.defered_context.get_context() {
// Something went wrong building the context, abort.
GetDeferredContextError::Build(e) => panic!("Error building context: {e}"),
// resume() didn't run for some reason, RenderContext has no surface to use to initialize with.
GetDeferredContextError::RequiresSurface => unreachable!("Surface should have been provided in resume()"),
// Still building, will try again next window_event()
GetDeferredContextError::StillBuilding => return,
};
// Now that context is ready, we can finish configuring the window surface.
// init_surface() and init_with_context() will create everything when needed and make sure it's configured.
let (surface, config) = self.window.as_ref().expect("Window should have created in resume()")
.init_with_context(&context);
// Side-note: Vertex/shader buffers, pipelines, etc. are also dependent on the RenderContext being
// configured with a surface. Keep them in an Option and generate them ASAP.
let buffers_and_shit = self.buffers_and_shit.get_or_insert_with(|| init_buffers_and_shit(&context, config.format));
Self::finally_render(context, window, surface)
}
fn suspended(&mut self, event_loop: &ActiveEventLoop) {
// Android requires surfaces be dropped on suspend. init_surface() or init_with_context() above
// will re-create and configure the window surface automatically when unsuspended.
self.window.as_mut().map(|w| w.drop_surface());
self.suspended = true;
}
}Implementations§
Source§impl DeferredContext
impl DeferredContext
pub async fn new_async(builder: RenderContextBuilder) -> Self
pub fn create_window( &mut self, event_loop: &ActiveEventLoop, attributes: WindowAttributes, config_opts: SurfaceConfigOptions, ) -> Result<SurfaceWindow, CreateWindowError>
pub fn get_instance(&self) -> Instance
pub fn get_context( &mut self, ) -> Result<Rc<RenderContext>, GetDeferredContextError>
Trait Implementations§
Auto Trait Implementations§
impl Freeze for DeferredContext
impl !RefUnwindSafe for DeferredContext
impl !Send for DeferredContext
impl !Sync for DeferredContext
impl Unpin for DeferredContext
impl !UnwindSafe for DeferredContext
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
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.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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.§fn as_any(&self) -> &(dyn Any + 'static)
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.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
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.