Skip to content

Commit

Permalink
feat: VelloRenderer is now a resource
Browse files Browse the repository at this point in the history
  • Loading branch information
simbleau committed Aug 4, 2024
1 parent 7c28ad6 commit 23b3598
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 41 deletions.
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe
- There is now a `default_font` feature that uses the same `FiraMono-subset.ttf` font used in the bevy/default_font feature.
- There is now a `render_layers` example.
- There is now a `cube_3d` example.
- Added `VelloRenderer::from_device` to create a renderer manually.
- You may now choose the render layers for the Vello canvas. This can be configured through the `VelloPlugin`.
- You may now choose to use CPU rendering with Vello and configure anti-aliasing. This can be configured through the `VelloPlugin`.

### Changed

- `VelloPlugin` now has configuration. To retain previous behavior, use `VelloPlugin::default()`.
- `VelloRenderer` is now a resource.
- The font API has changed significantly. Please visit `examples/text` for further usage. This is to prepare for additional text features such as linebreak behavior, bounded text, and text justification.
- `VelloText` has been renamed to `VelloTextSection`.
- `VelloText.content` has been renamed to `VelloText.value`.
Expand All @@ -28,12 +30,13 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe
- The field `VelloAssetBundle.vector` was renamed to `VelloAssetBundle.asset`.
- Renamed `VelloAssetAlignment` to `VelloAssetAnchor`. Fields were renamed `alignment` were renamed to `asset_anchor`.
- Renamed `VelloTextAlignment` to `VelloTextAnchor`. Fields were renamed `alignment` were renamed to `text_anchor`.
- The `SSRenderTarget` (fullscreen quad that renders your frame) no longer renders at a zepth of `-0.001`. This was a legacy hack used to ensure Gizmos rendered on-top.
- The `SSRenderTarget` (fullscreen quad that renders your frame) no longer renders at a zepth of `-0.001`. This was a legacy hack used to ensure Gizmos rendered on-top. `RenderLayers` should be used now (there's an example).

### Removed

- Removed `ZFunction`s from the render pipeline. Now ordering is based solely on the `Transform`'s z component. If you dependeded on this behavior, you'll need to adjust the transform Z in a system prior to render.
- Removed `VelloCanvasMaterial` from prelude, as it's not typically meant to be used under normal circumstances and could be a common footgun.
- `VelloRenderPlugin` is now private, as it is not helpful for downstream developers to add manually.
- Removed `VelloCanvasMaterial` from prelude, as it is not typical to use.

### Fixed

Expand Down
29 changes: 11 additions & 18 deletions examples/cube3d/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ use bevy::{
Render, RenderApp, RenderSet,
},
};
use bevy_vello::{
prelude::*,
render::{VelloRenderPlugin, VelloRenderer},
VelloPlugin,
};
use bevy_vello::{prelude::*, render::VelloRenderer, VelloPlugin};

#[derive(Component)]
pub struct VelloTarget(Handle<Image>);
Expand All @@ -37,7 +33,11 @@ fn main() {
let mut app = App::new();

app.add_plugins(DefaultPlugins)
.add_plugins(VelloRenderPlugin::default())
.add_plugins(VelloPlugin {
use_cpu: false,
antialiasing: vello::AaConfig::Msaa8,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, cube_rotator_system)
.add_plugins(ExtractComponentPlugin::<VelloTarget>::default());
Expand Down Expand Up @@ -119,23 +119,14 @@ fn setup(
}

fn render_texture(
mut vello_renderer: Local<Option<VelloRenderer>>,
renderer: Res<VelloRenderer>,
render_settings: Res<VelloRenderSettings>,
target: Query<&VelloTarget>,
device: Res<RenderDevice>,
gpu_images: Res<RenderAssets<GpuImage>>,
queue: Res<RenderQueue>,
time: Res<Time>,
) {
let renderer = vello_renderer.get_or_insert_with(|| {
VelloRenderer::from_device(
device.wgpu_device(),
&VelloRenderSettings {
use_cpu: false,
antialiasing: vello::AaConfig::Msaa8,
..default()
},
)
});
let target = target.single();

let mut scene = VelloScene::default();
Expand All @@ -159,9 +150,11 @@ fn render_texture(
base_color: vello::peniko::Color::WHITE,
width: gpu_image.size.x,
height: gpu_image.size.y,
antialiasing_method: vello::AaConfig::Area,
antialiasing_method: render_settings.antialiasing,
};
renderer
.lock()
.unwrap()
.render_to_texture(
device.wgpu_device(),
&queue,
Expand Down
46 changes: 38 additions & 8 deletions src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ use bevy::{
AsBindGroup, RenderPipelineDescriptor, ShaderRef, SpecializedMeshPipelineError,
VertexBufferLayout, VertexFormat, VertexStepMode,
},
renderer::RenderDevice,
view::RenderLayers,
},
sprite::{Material2d, Material2dKey},
};
use std::sync::{Arc, Mutex};
use vello::{AaConfig, AaSupport};

mod extract;
mod plugin;
mod prepare;
mod systems;

pub use plugin::VelloRenderPlugin;
pub(crate) use plugin::VelloRenderPlugin;

/// A handle to the screen space render target shader.
pub const SSRT_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(2314894693238056781);
Expand Down Expand Up @@ -61,12 +63,15 @@ impl Material2d for VelloCanvasMaterial {
}
}

#[derive(Deref, DerefMut)]
pub struct VelloRenderer(vello::Renderer);
#[derive(Resource, Deref, DerefMut)]
pub struct VelloRenderer(Arc<Mutex<vello::Renderer>>);

impl VelloRenderer {
pub fn from_device(device: &vello::wgpu::Device, settings: &VelloRenderSettings) -> Self {
let renderer = vello::Renderer::new(
pub fn new(
device: &vello::wgpu::Device,
settings: &VelloRenderSettings,
) -> Result<Self, vello::Error> {
vello::Renderer::new(
device,
vello::RendererOptions {
surface_format: None,
Expand All @@ -79,9 +84,34 @@ impl VelloRenderer {
num_init_threads: None,
},
)
// TODO: Attempt CPU fallback. Support changing antialias settings.
.expect("No GPU Device");
VelloRenderer(renderer)
.map(Mutex::new)
.map(Arc::new)
.map(VelloRenderer)
}
}

impl FromWorld for VelloRenderer {
fn from_world(world: &mut World) -> Self {
match VelloRenderer::new(
world.get_resource::<RenderDevice>().unwrap().wgpu_device(),
world.get_resource::<VelloRenderSettings>().unwrap(),
) {
Ok(r) => r,
Err(e) => {
error!("Attempting CPU fallback, failed to initialize renderer: {e:}");
{
let mut settings = world.get_resource_mut::<VelloRenderSettings>().unwrap();
settings.use_cpu = true;
}
match VelloRenderer::new(
world.get_resource::<RenderDevice>().unwrap().wgpu_device(),
world.get_resource::<VelloRenderSettings>().unwrap(),
) {
Ok(r) => r,
Err(e) => panic!("Failed to start vello: {e}"),
}
}
}
}
}

Expand Down
11 changes: 9 additions & 2 deletions src/render/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use super::{
prepare, systems, VelloCanvasSettings, VelloRenderSettings,
};
use crate::{
render::VelloCanvasMaterial, render::SSRT_SHADER_HANDLE, VelloAsset, VelloFont, VelloScene,
VelloTextSection,
render::{VelloCanvasMaterial, VelloRenderer, SSRT_SHADER_HANDLE},
VelloAsset, VelloFont, VelloScene, VelloTextSection,
};
use bevy::{
asset::load_internal_asset,
Expand Down Expand Up @@ -98,4 +98,11 @@ impl Plugin for VelloRenderPlugin {
.in_set(VisibilitySystems::CheckVisibility),
);
}

fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<VelloRenderer>();
}
}
16 changes: 6 additions & 10 deletions src/render/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,11 @@ pub fn render_frame(
gpu_images: Res<RenderAssets<GpuImage>>,
device: Res<RenderDevice>,
queue: Res<RenderQueue>,
mut vello_renderer: Local<Option<VelloRenderer>>,
settings: Res<VelloRenderSettings>,
renderer: Res<VelloRenderer>,
render_settings: Res<VelloRenderSettings>,

#[cfg(feature = "lottie")] mut velato_renderer: ResMut<super::VelatoRenderer>,
) {
let renderer = if settings.is_changed() {
vello_renderer.insert(VelloRenderer::from_device(device.wgpu_device(), &settings))
} else {
vello_renderer
.get_or_insert_with(|| VelloRenderer::from_device(device.wgpu_device(), &settings))
};

let Ok(SSRenderTarget(render_target_image)) = ss_render_target.get_single() else {
error!("No render target");
return;
Expand Down Expand Up @@ -230,6 +224,8 @@ pub fn render_frame(
}

renderer
.lock()
.unwrap()
.render_to_texture(
device.wgpu_device(),
&queue,
Expand All @@ -239,7 +235,7 @@ pub fn render_frame(
base_color: vello::peniko::Color::TRANSPARENT,
width: gpu_image.size.x,
height: gpu_image.size.y,
antialiasing_method: vello::AaConfig::Area,
antialiasing_method: render_settings.antialiasing,
},
)
.unwrap();
Expand Down

0 comments on commit 23b3598

Please sign in to comment.