Struct Renderer
pub struct Renderer { /* private fields */ }Expand description
Renders a scene into a texture or surface.
Currently, each renderer only supports a single surface format, if it supports drawing to surfaces at all. This is an assumption which is known to be limiting, and is planned to change.
Implementations§
§impl Renderer
impl Renderer
pub fn precompile_pipelines(
&self,
device: &Device,
queue: &Queue,
helpers: usize,
open_device: &(dyn Fn() -> Option<(Device, Queue)> + Sync),
)
pub fn precompile_pipelines( &self, device: &Device, queue: &Queue, helpers: usize, open_device: &(dyn Fn() -> Option<(Device, Queue)> + Sync), )
Run every GPU pipeline’s first dispatch now, spread over this device and up to
helpers more opened by open_device, each driven from its own thread.
Mesa’s CPU Vulkan driver (lavapipe) compiles a pipeline’s machine code on its first dispatch, so a cold first frame compiles every stage one after another. It also keeps the code in its shader disk cache, shared by every device in the process. This dispatches the largest pipeline here while the helpers take the rest, whose code this device then reads from the cache. When that one dispatch finds its code already compiled, the cache is warm and the helpers stop before compiling anything.
pub fn new(device: &Device, options: RendererOptions) -> Result<Renderer, Error>
pub fn new(device: &Device, options: RendererOptions) -> Result<Renderer, Error>
Creates a new renderer for the specified device.
pub fn new_deferring(
device: &Device,
options: RendererOptions,
deferral: PipelineDeferral,
) -> Result<Renderer, Error>
pub fn new_deferring( device: &Device, options: RendererOptions, deferral: PipelineDeferral, ) -> Result<Renderer, Error>
Self::new, building before it returns only the pipelines
deferral does not defer (Tilo patch). Call
Self::start_deferred_pipelines once the first frame is out.
pub async fn new_async(
device: &Device,
options: RendererOptions,
) -> Result<Renderer, Error>
pub async fn new_async( device: &Device, options: RendererOptions, ) -> Result<Renderer, Error>
Creates a new renderer for the specified device, compiling its
pipelines with Device::create_compute_pipeline_async (Tilo patch).
On WebGPU the browser then compiles them in parallel on worker threads, instead of one after another on its GPU process’s main thread. That thread also serves the page’s frames and every other page using the GPU process: a software rasteriser (SwiftShader) spends seconds per vello pipeline there, and in Chromium a page whose earlier WebGPU context is torn down meanwhile blocks its own main thread until the GPU process gets to it. Other backends create the pipelines synchronously, one after another.
pub fn start_deferred_pipelines(
&mut self,
device: &Device,
built: impl FnOnce() + Send + 'static,
)
pub fn start_deferred_pipelines( &mut self, device: &Device, built: impl FnOnce() + Send + 'static, )
Build the pipelines Self::new_deferring deferred, in the background
on the renderer’s init threads: those a full frame on the default path
dispatches first, the largest of each group first. Renders install them
as they arrive, and wait for one they dispatch. built
runs once every one is built (on that thread), or at once when nothing
was deferred: the moment to keep a pipeline cache. A second call does
nothing and drops its built.
pub fn deferred_pipelines(&mut self) -> DeferredPipelines
pub fn deferred_pipelines(&mut self) -> DeferredPipelines
The pipelines Self::new_deferring deferred that are not installed
yet, and how many a render had to build itself.
pub fn memory_stats(&self) -> RendererMemoryStats
pub fn memory_stats(&self) -> RendererMemoryStats
Return the GPU allocations whose byte sizes are directly known to the renderer. This is intended for performance budgets and diagnostics.
pub fn set_image_atlas_max(&mut self, max_size: u32)
pub fn set_image_atlas_max(&mut self, max_size: u32)
Limit the image atlas to max_size pixels per side (8192 by
default). Images that do not fit after eviction are omitted and
reported, instead of a 256 MB atlas taking a browser’s GPU process
past its memory limit.
pub fn image_cache_stats(&self) -> ImageCacheStats
pub fn image_cache_stats(&self) -> ImageCacheStats
The image atlas’s side and the images resident in it, with the CPU
pixels they keep alive. The atlas texture itself is in
Self::memory_stats’ image_bytes.
pub fn shrink_image_atlas_soon(&mut self)
pub fn shrink_image_atlas_soon(&mut self)
Images went for good (a window closed): an image atlas far bigger than what is still drawn comes down within the next few renders, not after sixty, so a desktop that goes idle gives the memory back.
pub fn set_bump_budget_grow_once(&mut self, grow_once: bool)
pub fn set_bump_budget_grow_once(&mut self, grow_once: bool)
Grow the bump buffers at most once, straight to the
Self::set_bump_budget_limit total, instead of doubling as a scene
fills up. Each growth reallocates every buffer, which a browser’s GPU
process briefly holds twice.
pub fn set_bump_budget_limit(&mut self, bytes: u64)
pub fn set_bump_budget_limit(&mut self, bytes: u64)
Limit the adaptive bump buffers to bytes in total, whatever frames
report using. Scenes past it drop geometry, which the shaders report,
instead of taking a browser’s GPU process past its memory limit.
Viewport floors come on top.
pub fn trim_pooled_buffers(&mut self)
pub fn trim_pooled_buffers(&mut self)
Drop transient GPU buffers held only for reuse. In-flight command buffers keep their own references, so this is safe at a damage-shape transition and prevents obsolete size classes living forever.
pub fn set_shrink_scratch(&mut self, enabled: bool)
pub fn set_shrink_scratch(&mut self, enabled: bool)
Hand back scratch a busier scene needed once the scene has stayed smaller (off by default): pooled buffers no render has taken for a while are destroyed, and the bump reservation comes down to a few times what recent dense frames used. Without it a renderer that once drew a busy scene keeps that scene’s working memory for good.
pub fn shrink_scratch_soon(&mut self)
pub fn shrink_scratch_soon(&mut self)
The scene got smaller for good (a window closed): with
Self::set_shrink_scratch, scratch comes down within the next few
renders rather than after a hundred, so a desktop that goes idle
gives the memory back.
pub fn scratch_shrinks(&self) -> u64
pub fn scratch_shrinks(&self) -> u64
Times the bump reservation shrank (Self::set_shrink_scratch):
each dropped every buffer pooled at the larger sizes.
pub fn invalidate_texture_bindings(&mut self, texture: &TextureView)
pub fn invalidate_texture_bindings(&mut self, texture: &TextureView)
Release cached bind groups referencing a scratch texture that its owner is about to replace. Other bind groups and GPU buffer pools stay warm, so animated damage resizing does not become a global cache flush.
pub fn render_to_texture(
&mut self,
device: &Device,
queue: &Queue,
scene: &Scene,
texture: &TextureView,
params: &RenderParams,
) -> Result<(), Error>
pub fn render_to_texture( &mut self, device: &Device, queue: &Queue, scene: &Scene, texture: &TextureView, params: &RenderParams, ) -> Result<(), Error>
Renders a scene to the target texture.
The texture is assumed to be of the specified dimensions and have been created with
the wgpu::TextureFormat::Rgba8Unorm format and the wgpu::TextureUsages::STORAGE_BINDING
flag set.
If you want to render Vello content to a surface (such as in a UI toolkit), you have two options:
- Render to an intermediate texture, which is the same size as the surface.
You would then use
TextureBlitterto blit the rendered result from that texture to the surface. This pattern is supported by theutilmodule. - Call
render_to_texturedirectly on theSurfaceTexture’s texture, if it has the right usages. This should generally be avoided, as some GPUs assume that you will not be rendering to the surface using a compute pipeline, and optimise accordingly.
pub fn poll_bump_budget(
&mut self,
device: &Device,
) -> Result<BumpBudgetPoll, BumpBudgetError>
pub fn poll_bump_budget( &mut self, device: &Device, ) -> Result<BumpBudgetPoll, BumpBudgetError>
Poll outstanding counter readbacks without waiting for the GPU.
Pending work retains any overflow collected by earlier renders. Only a completed poll consumes that overflow. Readback errors remain visible on subsequent polls, including errors found by ordinary render collection; replacing the renderer is required to discard a failed observation.
An idle renderer, or one with measurement deliberately disabled, has no outstanding counter work and reports complete. This method does not prove GPU submission or frame completion: callers must establish that separately.
pub fn override_image(
&mut self,
image: &ImageData,
texture: Option<TexelCopyTextureInfo<Texture>>,
) -> Option<TexelCopyTextureInfo<Texture>>
pub fn override_image( &mut self, image: &ImageData, texture: Option<TexelCopyTextureInfo<Texture>>, ) -> Option<TexelCopyTextureInfo<Texture>>
Overwrite image with texture.
Most users should prefer register_texture, which
ergonomically encapulates these requirements.
texture must have the wgpu::TextureFormat::Rgba8Unorm format and
the wgpu::TextureUsages::COPY_SRC flag set. The Rgba8UnormSrgb format
might also be supported, but this is not tested.
The given Texture’s data will be copied into the slot in Vello’s image
atlas where the image would be placed each frame.
This has the effect that wherever you request the image to be drawn (e.g.
through Scene::draw_image), the data from the texture will be used instead.
Correct behaviour is not guaranteed if the texture does not have the same dimensions as the image, nor if an image which uses the same blob but different dimensions would be rendered.
pub fn draw_image_from(
&mut self,
image: &ImageData,
source: Option<ImageSource>,
) -> Option<ImageSource>
pub fn draw_image_from( &mut self, image: &ImageData, source: Option<ImageSource>, ) -> Option<ImageSource>
Draw image from source (Tilo patch): its pixels are drawn into the
atlas slot through a render pass whenever the image is written there,
so source may be any colour format the device samples (a Bgra8Unorm
Wayland client buffer, imported as it is) and may be drawn opaque.
None stops drawing it from a source. Takes precedence over
override_image. Returns the previous source.
source.texture must have the wgpu::TextureUsages::TEXTURE_BINDING
flag and hold the image’s extent at source.origin. It is read only
while the image is written into the atlas: on its first draw, after
this call, and when the atlas is repacked. Keep it readable while any
scene that draws image can still be rendered.
pub fn image_source_writes(&self) -> (u64, u64)
pub fn image_source_writes(&self) -> (u64, u64)
Images drawn into the atlas from an ImageSource since this renderer
was made, and the bytes those draws wrote (Tilo patch).
pub fn mark_override_image_dirty(&mut self, image: &ImageData)
pub fn mark_override_image_dirty(&mut self, image: &ImageData)
Marks image as dirty in the atlas cache, so its override texture will be recopied on
the next render that uses it.
Call this for any image whose existing override texture has changed since the last render.
Otherwise, stale image data from the atlas may be used.
pub fn register_texture(&mut self, texture: Texture) -> ImageData
pub fn register_texture(&mut self, texture: Texture) -> ImageData
Register a wgpu::Texture with Vello, to allow drawing GPU-resident data.
The returned Image can be used in Scenes (only those rendered with this Renderer)
Rendering Scenes which use this Image with other Renderers will panic.
texture must have the wgpu::TextureFormat::Rgba8Unorm format and
the wgpu::TextureUsages::COPY_SRC flag set. This is because the data will
be copied into Vello’s image atlas at the start of each frame.
The Rgba8UnormSrgb format might also be supported, but this is not tested.
The texture is assumed to have unpremultiplied alpha.
This is a utility wrapper around override_image.
For greater control, use that method.
If the texture is no longer active then it should be unregistered using unregister_texture
pub fn unregister_texture(&mut self, handle: ImageData)
pub fn unregister_texture(&mut self, handle: ImageData)
Unregister a wgpu::Texture that was registered with register_texture.
pub async fn render_to_texture_async(
&mut self,
device: &Device,
queue: &Queue,
scene: &Scene,
texture: &TextureView,
params: &RenderParams,
debug_layers: DebugLayers,
) -> Result<Option<BumpAllocators>, Error>
👎Deprecated: render_to_texture should be preferred, as the _async version has no stability guarantees
pub async fn render_to_texture_async( &mut self, device: &Device, queue: &Queue, scene: &Scene, texture: &TextureView, params: &RenderParams, debug_layers: DebugLayers, ) -> Result<Option<BumpAllocators>, Error>
render_to_texture should be preferred, as the _async version has no stability guarantees
Renders a scene to the target texture using an async pipeline.
Almost all consumers should prefer Self::render_to_texture.
The return value is the value of the BumpAllocators in this rendering, which is currently used
for debug output.
This return type is not stable, and will likely be changed when a more principled way to access relevant statistics is implemented
Auto Trait Implementations§
impl Freeze for Renderer
impl !RefUnwindSafe for Renderer
impl Send for Renderer
impl !Sync for Renderer
impl Unpin for Renderer
impl UnsafeUnpin for Renderer
impl !UnwindSafe for Renderer
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
§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>
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>
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)
&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)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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