mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Add piet trait
Use piet render context to encode into scene buffer. This is adapted from piet-dx12.
This commit is contained in:
parent
4aaa6f1f29
commit
7528eaff22
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -6,6 +6,12 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
|
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ash"
|
name = "ash"
|
||||||
version = "0.30.0"
|
version = "0.30.0"
|
||||||
|
@ -84,6 +90,15 @@ dependencies = [
|
||||||
"adler32",
|
"adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kurbo"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf50e17a1697110c694d47c5b1a6b64faf5eb3ffe5a286df23fb8cd516e33be6"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.69"
|
version = "0.2.69"
|
||||||
|
@ -100,10 +115,20 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "piet"
|
||||||
|
version = "0.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29420eccb68d6b9ad2f8dd87caf9c3bcd3bbd056bfe67871c48b6efab9316b79"
|
||||||
|
dependencies = [
|
||||||
|
"kurbo",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "piet-gpu"
|
name = "piet-gpu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"piet",
|
||||||
"piet-gpu-hal",
|
"piet-gpu-hal",
|
||||||
"piet-gpu-types",
|
"piet-gpu-types",
|
||||||
"png",
|
"png",
|
||||||
|
|
|
@ -13,5 +13,6 @@ path = "../piet-gpu-hal"
|
||||||
path = "../piet-gpu-types"
|
path = "../piet-gpu-types"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
piet = "0.0.12"
|
||||||
png = "0.16.2"
|
png = "0.16.2"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
|
|
|
@ -4,11 +4,16 @@ use std::path::Path;
|
||||||
|
|
||||||
use rand::{Rng, RngCore};
|
use rand::{Rng, RngCore};
|
||||||
|
|
||||||
|
use piet::{Color, RenderContext};
|
||||||
|
use piet::kurbo::{Circle, Point};
|
||||||
|
|
||||||
use piet_gpu_hal::vulkan::VkInstance;
|
use piet_gpu_hal::vulkan::VkInstance;
|
||||||
use piet_gpu_hal::{CmdBuf, Device, MemFlags};
|
use piet_gpu_hal::{CmdBuf, Device, MemFlags};
|
||||||
|
|
||||||
use piet_gpu_types::encoder::{Encode, Encoder};
|
|
||||||
use piet_gpu_types::scene::{Bbox, PietCircle, PietItem, Point, SimpleGroup};
|
mod render_ctx;
|
||||||
|
|
||||||
|
use render_ctx::PietGpuRenderContext;
|
||||||
|
|
||||||
const WIDTH: usize = 2048;
|
const WIDTH: usize = 2048;
|
||||||
const HEIGHT: usize = 1536;
|
const HEIGHT: usize = 1536;
|
||||||
|
@ -18,50 +23,16 @@ const TILE_H: usize = 16;
|
||||||
|
|
||||||
const N_CIRCLES: usize = 3000;
|
const N_CIRCLES: usize = 3000;
|
||||||
|
|
||||||
fn make_scene() -> Vec<u8> {
|
fn render_scene(rc: &mut impl RenderContext) {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let mut encoder = Encoder::new();
|
|
||||||
let _reserve_root = encoder.alloc_chunk(PietItem::fixed_size() as u32);
|
|
||||||
|
|
||||||
let mut items = Vec::new();
|
|
||||||
let mut bboxes = Vec::new();
|
|
||||||
for _ in 0..N_CIRCLES {
|
for _ in 0..N_CIRCLES {
|
||||||
let circle = PietCircle {
|
let color = Color::from_rgba32_u32(rng.next_u32());
|
||||||
rgba_color: rng.next_u32(),
|
let center = Point::new(rng.gen_range(0.0, WIDTH as f64),
|
||||||
center: Point {
|
rng.gen_range(0.0, HEIGHT as f64));
|
||||||
xy: [
|
let radius = rng.gen_range(0.0, 50.0);
|
||||||
rng.gen_range(0.0, WIDTH as f32),
|
let circle = Circle::new(center, radius);
|
||||||
rng.gen_range(0.0, HEIGHT as f32),
|
rc.fill(circle, &color);
|
||||||
],
|
|
||||||
},
|
|
||||||
radius: rng.gen_range(0.0, 50.0),
|
|
||||||
};
|
|
||||||
let bbox = Bbox {
|
|
||||||
bbox: [
|
|
||||||
(circle.center.xy[0] - circle.radius).floor() as i16,
|
|
||||||
(circle.center.xy[1] - circle.radius).floor() as i16,
|
|
||||||
(circle.center.xy[0] + circle.radius).ceil() as i16,
|
|
||||||
(circle.center.xy[1] + circle.radius).ceil() as i16,
|
|
||||||
],
|
|
||||||
};
|
|
||||||
items.push(PietItem::Circle(circle));
|
|
||||||
bboxes.push(bbox);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let n_items = bboxes.len() as u32;
|
|
||||||
let bboxes = bboxes.encode(&mut encoder).transmute();
|
|
||||||
let items = items.encode(&mut encoder).transmute();
|
|
||||||
let offset = Point { xy: [0.0, 0.0] };
|
|
||||||
let simple_group = SimpleGroup {
|
|
||||||
n_items,
|
|
||||||
bboxes,
|
|
||||||
items,
|
|
||||||
offset,
|
|
||||||
};
|
|
||||||
let root_item = PietItem::Group(simple_group);
|
|
||||||
root_item.encode_to(&mut encoder.buf_mut()[0..PietItem::fixed_size()]);
|
|
||||||
// We should avoid this clone.
|
|
||||||
encoder.buf().to_owned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -88,7 +59,9 @@ fn main() {
|
||||||
let device = instance.device().unwrap();
|
let device = instance.device().unwrap();
|
||||||
let host = MemFlags::host_coherent();
|
let host = MemFlags::host_coherent();
|
||||||
let dev = MemFlags::device_local();
|
let dev = MemFlags::device_local();
|
||||||
let scene = make_scene();
|
let mut ctx = PietGpuRenderContext::new();
|
||||||
|
render_scene(&mut ctx);
|
||||||
|
let scene = ctx.get_scene_buf();
|
||||||
//dump_scene(&scene);
|
//dump_scene(&scene);
|
||||||
let scene_buf = device
|
let scene_buf = device
|
||||||
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, host)
|
.create_buffer(std::mem::size_of_val(&scene[..]) as u64, host)
|
||||||
|
@ -98,8 +71,8 @@ fn main() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
device.write_buffer(&scene_buf, &scene).unwrap();
|
device.write_buffer(&scene_buf, &scene).unwrap();
|
||||||
// These should only be on the host if we're going to examine them from Rust.
|
// These should only be on the host if we're going to examine them from Rust.
|
||||||
let tilegroup_buf = device.create_buffer(384 * 1024, host).unwrap();
|
let tilegroup_buf = device.create_buffer(384 * 1024, dev).unwrap();
|
||||||
let ptcl_buf = device.create_buffer(12 * 1024 * 4096, host).unwrap();
|
let ptcl_buf = device.create_buffer(12 * 1024 * 4096, dev).unwrap();
|
||||||
let image_buf = device
|
let image_buf = device
|
||||||
.create_buffer((WIDTH * HEIGHT * 4) as u64, host)
|
.create_buffer((WIDTH * HEIGHT * 4) as u64, host)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
297
piet-gpu/src/render_ctx.rs
Normal file
297
piet-gpu/src/render_ctx.rs
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use piet_gpu_types::encoder::{Encode, Encoder};
|
||||||
|
use piet_gpu_types::scene;
|
||||||
|
use piet_gpu_types::scene::{Bbox, PietCircle, PietItem, SimpleGroup};
|
||||||
|
|
||||||
|
use piet::kurbo::{Affine, Point, Rect, Shape};
|
||||||
|
|
||||||
|
use piet::{
|
||||||
|
Color, Error, FixedGradient, Font, FontBuilder, HitTestPoint, HitTestTextPosition, ImageFormat,
|
||||||
|
InterpolationMode, IntoBrush, LineMetric, RenderContext, StrokeStyle, Text, TextLayout,
|
||||||
|
TextLayoutBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PietGpuImage;
|
||||||
|
|
||||||
|
pub struct PietGpuFont;
|
||||||
|
|
||||||
|
pub struct PietGpuFontBuilder;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PietGpuTextLayout;
|
||||||
|
|
||||||
|
pub struct PietGpuTextLayoutBuilder;
|
||||||
|
|
||||||
|
pub struct PietGpuText;
|
||||||
|
|
||||||
|
pub struct PietGpuRenderContext {
|
||||||
|
encoder: Encoder,
|
||||||
|
bboxes: Vec<Bbox>,
|
||||||
|
items: Vec<PietItem>,
|
||||||
|
// Will probably need direct accesss to hal Device to create images etc.
|
||||||
|
inner_text: PietGpuText,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum PietGpuBrush {
|
||||||
|
Solid(u32),
|
||||||
|
Gradient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PietGpuRenderContext {
|
||||||
|
pub fn new() -> PietGpuRenderContext {
|
||||||
|
let mut encoder = Encoder::new();
|
||||||
|
let _reserve_root = encoder.alloc_chunk(PietItem::fixed_size() as u32);
|
||||||
|
let bboxes = Vec::new();
|
||||||
|
let items = Vec::new();
|
||||||
|
let inner_text = PietGpuText;
|
||||||
|
PietGpuRenderContext {
|
||||||
|
encoder,
|
||||||
|
bboxes,
|
||||||
|
items,
|
||||||
|
inner_text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_scene_buf(&mut self) -> &[u8] {
|
||||||
|
let n_items = self.bboxes.len() as u32;
|
||||||
|
let bboxes = self.bboxes.encode(&mut self.encoder).transmute();
|
||||||
|
let items = self.items.encode(&mut self.encoder).transmute();
|
||||||
|
let offset = scene::Point { xy: [0.0, 0.0] };
|
||||||
|
let simple_group = SimpleGroup {
|
||||||
|
n_items,
|
||||||
|
bboxes,
|
||||||
|
items,
|
||||||
|
offset,
|
||||||
|
};
|
||||||
|
let root_item = PietItem::Group(simple_group);
|
||||||
|
root_item.encode_to(&mut self.encoder.buf_mut()[0..PietItem::fixed_size()]);
|
||||||
|
self.encoder.buf()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_item(&mut self, item: PietItem, bbox: Rect) {
|
||||||
|
let scene_bbox = Bbox {
|
||||||
|
bbox: [
|
||||||
|
bbox.x0.floor() as i16,
|
||||||
|
bbox.y0.floor() as i16,
|
||||||
|
bbox.x1.ceil() as i16,
|
||||||
|
bbox.y1.ceil() as i16,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
self.items.push(item);
|
||||||
|
self.bboxes.push(scene_bbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderContext for PietGpuRenderContext {
|
||||||
|
type Brush = PietGpuBrush;
|
||||||
|
type Image = PietGpuImage;
|
||||||
|
type Text = PietGpuText;
|
||||||
|
type TextLayout = PietGpuTextLayout;
|
||||||
|
|
||||||
|
fn status(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solid_brush(&mut self, color: Color) -> Self::Brush {
|
||||||
|
PietGpuBrush::Solid(color.as_rgba_u32())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gradient(&mut self, _gradient: impl Into<FixedGradient>) -> Result<Self::Brush, Error> {
|
||||||
|
Ok(Self::Brush::Gradient)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear(&mut self, _color: Color) {}
|
||||||
|
|
||||||
|
fn stroke(&mut self, _shape: impl Shape, _brush: &impl IntoBrush<Self>, _width: f64) {}
|
||||||
|
|
||||||
|
fn stroke_styled(
|
||||||
|
&mut self,
|
||||||
|
_shape: impl Shape,
|
||||||
|
_brush: &impl IntoBrush<Self>,
|
||||||
|
_width: f64,
|
||||||
|
_style: &StrokeStyle,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
||||||
|
let dummy_closure = || Rect {
|
||||||
|
x0: 0.0,
|
||||||
|
x1: 0.0,
|
||||||
|
y0: 0.0,
|
||||||
|
y1: 0.0,
|
||||||
|
};
|
||||||
|
let brush = brush.make_brush(self, dummy_closure).into_owned();
|
||||||
|
|
||||||
|
match shape.as_circle() {
|
||||||
|
Some(circle) => match brush {
|
||||||
|
PietGpuBrush::Solid(rgba_color) => {
|
||||||
|
let piet_circle = PietCircle {
|
||||||
|
rgba_color,
|
||||||
|
center: to_scene_point(circle.center),
|
||||||
|
radius: circle.radius as f32,
|
||||||
|
};
|
||||||
|
let bbox = circle.bounding_box();
|
||||||
|
self.push_item(PietItem::Circle(piet_circle), bbox);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_even_odd(&mut self, _shape: impl Shape, _brush: &impl IntoBrush<Self>) {}
|
||||||
|
|
||||||
|
fn clip(&mut self, _shape: impl Shape) {}
|
||||||
|
|
||||||
|
fn text(&mut self) -> &mut Self::Text {
|
||||||
|
&mut self.inner_text
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_text(
|
||||||
|
&mut self,
|
||||||
|
_layout: &Self::TextLayout,
|
||||||
|
pos: impl Into<Point>,
|
||||||
|
brush: &impl IntoBrush<Self>,
|
||||||
|
) {
|
||||||
|
let _pos = pos.into();
|
||||||
|
|
||||||
|
let brush: PietGpuBrush = brush.make_brush(self, || Rect::ZERO).into_owned();
|
||||||
|
|
||||||
|
match brush {
|
||||||
|
PietGpuBrush::Solid(_rgba) => {
|
||||||
|
// TODO: draw text
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn restore(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn finish(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn transform(&mut self, _transform: Affine) {}
|
||||||
|
|
||||||
|
fn make_image(
|
||||||
|
&mut self,
|
||||||
|
_width: usize,
|
||||||
|
_height: usize,
|
||||||
|
_buf: &[u8],
|
||||||
|
_format: ImageFormat,
|
||||||
|
) -> Result<Self::Image, Error> {
|
||||||
|
Ok(PietGpuImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_image(
|
||||||
|
&mut self,
|
||||||
|
_image: &Self::Image,
|
||||||
|
_rect: impl Into<Rect>,
|
||||||
|
_interp: InterpolationMode,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_image_area(
|
||||||
|
&mut self,
|
||||||
|
_image: &Self::Image,
|
||||||
|
_src_rect: impl Into<Rect>,
|
||||||
|
_dst_rect: impl Into<Rect>,
|
||||||
|
_interp: InterpolationMode,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blurred_rect(&mut self, _rect: Rect, _blur_radius: f64, _brush: &impl IntoBrush<Self>) {}
|
||||||
|
|
||||||
|
fn current_transform(&self) -> Affine {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Text for PietGpuText {
|
||||||
|
type Font = PietGpuFont;
|
||||||
|
type FontBuilder = PietGpuFontBuilder;
|
||||||
|
type TextLayout = PietGpuTextLayout;
|
||||||
|
type TextLayoutBuilder = PietGpuTextLayoutBuilder;
|
||||||
|
|
||||||
|
fn new_font_by_name(&mut self, _name: &str, _size: f64) -> Self::FontBuilder {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_text_layout(
|
||||||
|
&mut self,
|
||||||
|
_font: &Self::Font,
|
||||||
|
_text: &str,
|
||||||
|
_width: f64,
|
||||||
|
) -> Self::TextLayoutBuilder {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Font for PietGpuFont {}
|
||||||
|
|
||||||
|
impl FontBuilder for PietGpuFontBuilder {
|
||||||
|
type Out = PietGpuFont;
|
||||||
|
|
||||||
|
fn build(self) -> Result<Self::Out, Error> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextLayoutBuilder for PietGpuTextLayoutBuilder {
|
||||||
|
type Out = PietGpuTextLayout;
|
||||||
|
|
||||||
|
fn build(self) -> Result<Self::Out, Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextLayout for PietGpuTextLayout {
|
||||||
|
fn width(&self) -> f64 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_width(&mut self, _new_width: f64) -> Result<(), Error> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_text(&self, _line_number: usize) -> Option<&str> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_metric(&self, _line_number: usize) -> Option<LineMetric> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_count(&self) -> usize {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hit_test_point(&self, _point: Point) -> HitTestPoint {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hit_test_text_position(&self, _text_position: usize) -> Option<HitTestTextPosition> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBrush<PietGpuRenderContext> for PietGpuBrush {
|
||||||
|
fn make_brush<'b>(
|
||||||
|
&'b self,
|
||||||
|
_piet: &mut PietGpuRenderContext,
|
||||||
|
_bbox: impl FnOnce() -> Rect,
|
||||||
|
) -> std::borrow::Cow<'b, PietGpuBrush> {
|
||||||
|
Cow::Borrowed(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_scene_point(point: Point) -> scene::Point {
|
||||||
|
scene::Point {
|
||||||
|
xy: [point.x as f32, point.y as f32],
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue