[−][src]Module web_glitz::runtime::single_threaded
This module implements a runtime designed to run on a single thread (the main thread). This runtime's RenderingContext implementation, [SingleThreadedContext], may be Cloned (which results in another handle to the same context), but neither it nor any of its clones may be send to or shared with other threads/workers.
Tasks submitted to a single threaded context (see RenderingContext::submit) are executed immediately and typically don't involve dynamic dispatch (unless the task becomes fenced, in which case it will be "boxed" and stored in the "fenced-task queue" from where it will be invoked dynamically once its fence becomes signalled, see below).
Example
A new single threaded runtime may be initialized by calling [init] with a web_sys::HtmlCanvasElement and ContextOptions:
use wasm_bindgen::JsCast; use web_glitz::runtime::{single_threaded, ContextOptions}; use web_sys::{window, HtmlCanvasElement}; let canvas: HtmlCanvasElement = window() .unwrap() .document() .unwrap() .get_element_by_id("canvas") .unwrap() .dyn_into() .unwrap(); let options = ContextOptions::default(); let (context, render_target) = unsafe { single_threaded::init(&canvas, &options).unwrap() };
This returns a tuple of the [SingleThreadedContext] and the [DefaultRenderTarget] for the canvas or an error if the requested ContextOptions could not be supported. For more details on the options available when initializing a single threaded runtime, see ContextOptions.
Unsafe
Note that the [init] function is marked unsafe
: the canvas's WebGL2 context must be in its
original state when [init] was called and for the lifetime of the [SingleThreadedContext] or any
of its clones, the state of the context should not be modified through another handle to the
canvas's raw WebGL2 context; the [SingleThreadedContext] tracks the changes it makes to the
state of its associated WebGL2 context in a state cache and if at any point during the execution
of a task the actual state of the WebGL2 and the state cache don't match, unexpected results may
ocurr. In short: if you only initialize one WebGlitz RenderingContext or raw WebGL2 context
per canvas, then calling [init] is safe.
Multi-part Tasks and Fencing
A [GpuTask] may consists of multiple stages where in between stages the task has to wait for a GPU fence to become signalled. This mostly concerns tasks that contain "read" or download" commands (commands with non-void outputs), where the first part of the command sets up the command, then a fence is inserted and then the actual download occurs; this may avoid stalling both the CPU and GPU. This runtime handles such tasks by maintaining a "fenced-task" queue for tasks where [Gpu::progress] returns [Progress::ContinueFenced]. If this queue is not empty, then a 1ms timeout is scheduled with the JavaScript event queue. After this timeout expires it will try to again make progress on the tasks in the fenced-task queue (this shortcuts on the first fence that has not yet become signalled, as WebGL/OpenGL fences cannot become signalled out of order). If the fenced-task queue is not emptied (either because not all fences became signalled, or because one of the tasks again returned [Progress::ContinueFenced]), then a new 1ms timeout is scheduled on the JavaScript event loop. Note that such repeated scheduling of timeout events in nested callback results in throttling (to ~4ms) in most browsers after a certain number of iterations (5 in Chrome and FireFox, 6 in Safari and 3 in Edge, at the time of this writing). Note also that timeouts indicate a minimum timeout: if the JavaScript main thread is already busy, or higher priority events exists in the queue (micro-tasks or macro-tasks that were scheduled earlier), then the JavaScript/WASM runtime will finish this work before checking the fenced-task queue again.
Structs
SingleThreadedContext | A handle to a single-threaded WebGlitz rendering context. |
Traits
Options |
Functions
init⚠ | Initializes a single threaded WebGlitz runtime for the |