mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Encode stroke in scene
This just adds the first step of polyline stroking, which is adding it to the scene. Also just a bit of cleaning up of dimensions into one header file.
This commit is contained in:
parent
7528eaff22
commit
e1c0e448ef
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -93,8 +93,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kurbo"
|
name = "kurbo"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/linebender/kurbo?rev=7bd7e66bd137e757305d170a0f9f2b4f7beeb299#7bd7e66bd137e757305d170a0f9f2b4f7beeb299"
|
||||||
checksum = "bf50e17a1697110c694d47c5b1a6b64faf5eb3ffe5a286df23fb8cd516e33be6"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
]
|
]
|
||||||
|
@ -128,6 +127,7 @@ dependencies = [
|
||||||
name = "piet-gpu"
|
name = "piet-gpu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"kurbo",
|
||||||
"piet",
|
"piet",
|
||||||
"piet-gpu-hal",
|
"piet-gpu-hal",
|
||||||
"piet-gpu-types",
|
"piet-gpu-types",
|
||||||
|
|
|
@ -6,3 +6,7 @@ members = [
|
||||||
"piet-gpu-hal",
|
"piet-gpu-hal",
|
||||||
"piet-gpu-types"
|
"piet-gpu-types"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# TODO: remove when the flatten feature is published
|
||||||
|
[patch.crates-io]
|
||||||
|
kurbo = { git = "https://github.com/linebender/kurbo", rev = "7bd7e66bd137e757305d170a0f9f2b4f7beeb299" }
|
||||||
|
|
|
@ -13,6 +13,7 @@ path = "../piet-gpu-hal"
|
||||||
path = "../piet-gpu-types"
|
path = "../piet-gpu-types"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
kurbo = "0.5.11"
|
||||||
piet = "0.0.12"
|
piet = "0.0.12"
|
||||||
png = "0.16.2"
|
png = "0.16.2"
|
||||||
rand = "0.7.3"
|
rand = "0.7.3"
|
||||||
|
|
|
@ -9,8 +9,8 @@ rule glsl
|
||||||
|
|
||||||
build image.spv: glsl image.comp | scene.h
|
build image.spv: glsl image.comp | scene.h
|
||||||
|
|
||||||
build kernel1.spv: glsl kernel1.comp | scene.h tilegroup.h
|
build kernel1.spv: glsl kernel1.comp | scene.h tilegroup.h setup.h
|
||||||
|
|
||||||
build kernel3.spv: glsl kernel3.comp | scene.h tilegroup.h ptcl.h
|
build kernel3.spv: glsl kernel3.comp | scene.h tilegroup.h ptcl.h setup.h
|
||||||
|
|
||||||
build kernel4.spv: glsl kernel4.comp | ptcl.h
|
build kernel4.spv: glsl kernel4.comp | ptcl.h setup.h
|
||||||
|
|
|
@ -28,13 +28,7 @@ layout(set = 0, binding = 1) buffer TilegroupBuf {
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
#include "tilegroup.h"
|
#include "tilegroup.h"
|
||||||
|
|
||||||
// TODO: compute this
|
#include "setup.h"
|
||||||
#define WIDTH_IN_TILEGROUPS 4
|
|
||||||
|
|
||||||
#define TILEGROUP_WIDTH_PX 512
|
|
||||||
#define TILEGROUP_HEIGHT_PX 16
|
|
||||||
|
|
||||||
#define TILEGROUP_INITIAL_ALLOC 1024
|
|
||||||
|
|
||||||
#define MAX_STACK 8
|
#define MAX_STACK 8
|
||||||
|
|
||||||
|
|
|
@ -24,19 +24,7 @@ layout(set = 0, binding = 2) buffer PtclBuf {
|
||||||
#include "tilegroup.h"
|
#include "tilegroup.h"
|
||||||
#include "ptcl.h"
|
#include "ptcl.h"
|
||||||
|
|
||||||
// TODO: compute all these
|
#include "setup.h"
|
||||||
|
|
||||||
#define WIDTH_IN_TILEGROUPS 4
|
|
||||||
#define WIDTH_IN_TILES 128
|
|
||||||
#define TILEGROUP_WIDTH_TILES 32
|
|
||||||
#define TILE_WIDTH_PX 16
|
|
||||||
#define TILE_HEIGHT_PX 16
|
|
||||||
|
|
||||||
// Must be the same as kernel1. Might be a good idea to move these particular
|
|
||||||
// constants to their own .h file.
|
|
||||||
#define TILEGROUP_INITIAL_ALLOC 1024
|
|
||||||
|
|
||||||
#define PTCL_INITIAL_ALLOC 4096
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint tile_ix = gl_GlobalInvocationID.y * WIDTH_IN_TILES + gl_GlobalInvocationID.x;
|
uint tile_ix = gl_GlobalInvocationID.y * WIDTH_IN_TILES + gl_GlobalInvocationID.x;
|
||||||
|
|
|
@ -20,13 +20,7 @@ layout(set = 0, binding = 1) buffer ImageBuf {
|
||||||
|
|
||||||
#include "ptcl.h"
|
#include "ptcl.h"
|
||||||
|
|
||||||
// TODO: make the image size dynamic.
|
#include "setup.h"
|
||||||
#define IMAGE_WIDTH 2048
|
|
||||||
#define IMAGE_HEIGHT 1535
|
|
||||||
|
|
||||||
#define WIDTH_IN_TILES 128
|
|
||||||
|
|
||||||
#define PTCL_INITIAL_ALLOC 4096
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
uint tile_ix = gl_WorkGroupID.y * WIDTH_IN_TILES + gl_WorkGroupID.x;
|
uint tile_ix = gl_WorkGroupID.y * WIDTH_IN_TILES + gl_WorkGroupID.x;
|
||||||
|
|
Binary file not shown.
25
piet-gpu/shader/setup.h
Normal file
25
piet-gpu/shader/setup.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Various constants for the sizes of groups and tiles.
|
||||||
|
|
||||||
|
// Much of this will be made dynamic in various ways, but for now it's easiest
|
||||||
|
// to hardcode and keep all in one place.
|
||||||
|
|
||||||
|
// TODO: make the image size dynamic.
|
||||||
|
#define IMAGE_WIDTH 2048
|
||||||
|
#define IMAGE_HEIGHT 1536
|
||||||
|
|
||||||
|
// TODO: compute this
|
||||||
|
#define WIDTH_IN_TILEGROUPS 4
|
||||||
|
|
||||||
|
#define TILEGROUP_WIDTH_PX 512
|
||||||
|
#define TILEGROUP_HEIGHT_PX 16
|
||||||
|
|
||||||
|
#define TILEGROUP_INITIAL_ALLOC 1024
|
||||||
|
|
||||||
|
// TODO: compute all these
|
||||||
|
|
||||||
|
#define WIDTH_IN_TILES 128
|
||||||
|
#define TILEGROUP_WIDTH_TILES 32
|
||||||
|
#define TILE_WIDTH_PX 16
|
||||||
|
#define TILE_HEIGHT_PX 16
|
||||||
|
|
||||||
|
#define PTCL_INITIAL_ALLOC 4096
|
|
@ -4,13 +4,12 @@ use std::path::Path;
|
||||||
|
|
||||||
use rand::{Rng, RngCore};
|
use rand::{Rng, RngCore};
|
||||||
|
|
||||||
use piet::{Color, RenderContext};
|
|
||||||
use piet::kurbo::{Circle, Point};
|
use piet::kurbo::{Circle, Point};
|
||||||
|
use piet::{Color, RenderContext};
|
||||||
|
|
||||||
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};
|
||||||
|
|
||||||
|
|
||||||
mod render_ctx;
|
mod render_ctx;
|
||||||
|
|
||||||
use render_ctx::PietGpuRenderContext;
|
use render_ctx::PietGpuRenderContext;
|
||||||
|
@ -27,8 +26,10 @@ fn render_scene(rc: &mut impl RenderContext) {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
for _ in 0..N_CIRCLES {
|
for _ in 0..N_CIRCLES {
|
||||||
let color = Color::from_rgba32_u32(rng.next_u32());
|
let color = Color::from_rgba32_u32(rng.next_u32());
|
||||||
let center = Point::new(rng.gen_range(0.0, WIDTH as f64),
|
let center = Point::new(
|
||||||
rng.gen_range(0.0, HEIGHT as f64));
|
rng.gen_range(0.0, WIDTH as f64),
|
||||||
|
rng.gen_range(0.0, HEIGHT as f64),
|
||||||
|
);
|
||||||
let radius = rng.gen_range(0.0, 50.0);
|
let radius = rng.gen_range(0.0, 50.0);
|
||||||
let circle = Circle::new(center, radius);
|
let circle = Circle::new(center, radius);
|
||||||
rc.fill(circle, &color);
|
rc.fill(circle, &color);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use piet_gpu_types::encoder::{Encode, Encoder};
|
use piet_gpu_types::encoder::{Encode, Encoder, Ref};
|
||||||
use piet_gpu_types::scene;
|
use piet_gpu_types::scene;
|
||||||
use piet_gpu_types::scene::{Bbox, PietCircle, PietItem, SimpleGroup};
|
use piet_gpu_types::scene::{Bbox, PietCircle, PietItem, PietStrokePolyLine, SimpleGroup};
|
||||||
|
|
||||||
use piet::kurbo::{Affine, Point, Rect, Shape};
|
use piet::kurbo::{Affine, PathEl, Point, Rect, Shape};
|
||||||
|
|
||||||
use piet::{
|
use piet::{
|
||||||
Color, Error, FixedGradient, Font, FontBuilder, HitTestPoint, HitTestTextPosition, ImageFormat,
|
Color, Error, FixedGradient, Font, FontBuilder, HitTestPoint, HitTestTextPosition, ImageFormat,
|
||||||
|
@ -39,6 +39,8 @@ pub enum PietGpuBrush {
|
||||||
Gradient,
|
Gradient,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TOLERANCE: f64 = 0.1;
|
||||||
|
|
||||||
impl PietGpuRenderContext {
|
impl PietGpuRenderContext {
|
||||||
pub fn new() -> PietGpuRenderContext {
|
pub fn new() -> PietGpuRenderContext {
|
||||||
let mut encoder = Encoder::new();
|
let mut encoder = Encoder::new();
|
||||||
|
@ -104,7 +106,24 @@ impl RenderContext for PietGpuRenderContext {
|
||||||
|
|
||||||
fn clear(&mut self, _color: Color) {}
|
fn clear(&mut self, _color: Color) {}
|
||||||
|
|
||||||
fn stroke(&mut self, _shape: impl Shape, _brush: &impl IntoBrush<Self>, _width: f64) {}
|
fn stroke(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>, width: f64) {
|
||||||
|
let bbox = shape.bounding_box();
|
||||||
|
let brush = brush.make_brush(self, || bbox).into_owned();
|
||||||
|
let path = shape.to_bez_path(TOLERANCE);
|
||||||
|
let (n_points, points) = flatten_shape(&mut self.encoder, path);
|
||||||
|
match brush {
|
||||||
|
PietGpuBrush::Solid(rgba_color) => {
|
||||||
|
let poly_line = PietStrokePolyLine {
|
||||||
|
rgba_color,
|
||||||
|
width: width as f32,
|
||||||
|
n_points,
|
||||||
|
points,
|
||||||
|
};
|
||||||
|
self.push_item(PietItem::Poly(poly_line), bbox);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn stroke_styled(
|
fn stroke_styled(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -116,13 +135,7 @@ impl RenderContext for PietGpuRenderContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
||||||
let dummy_closure = || Rect {
|
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
||||||
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() {
|
match shape.as_circle() {
|
||||||
Some(circle) => match brush {
|
Some(circle) => match brush {
|
||||||
|
@ -212,6 +225,45 @@ impl RenderContext for PietGpuRenderContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn flatten_shape(
|
||||||
|
encoder: &mut Encoder,
|
||||||
|
path: impl Iterator<Item = PathEl>,
|
||||||
|
) -> (u32, Ref<scene::Point>) {
|
||||||
|
let mut points = Vec::new();
|
||||||
|
let mut start_pt = None;
|
||||||
|
let mut last_pt = None;
|
||||||
|
kurbo::flatten(path, TOLERANCE, |el| {
|
||||||
|
match el {
|
||||||
|
PathEl::MoveTo(p) => {
|
||||||
|
let scene_pt = to_scene_point(p);
|
||||||
|
start_pt = Some(clone_scene_pt(&scene_pt));
|
||||||
|
if !points.is_empty() {
|
||||||
|
points.push(scene::Point { xy: [std::f32::NAN, std::f32::NAN ]});
|
||||||
|
}
|
||||||
|
last_pt = Some(clone_scene_pt(&scene_pt));
|
||||||
|
points.push(scene_pt);
|
||||||
|
}
|
||||||
|
PathEl::LineTo(p) => {
|
||||||
|
let scene_pt = to_scene_point(p);
|
||||||
|
last_pt = Some(clone_scene_pt(&scene_pt));
|
||||||
|
points.push(scene_pt);
|
||||||
|
}
|
||||||
|
PathEl::ClosePath => {
|
||||||
|
if let (Some(start), Some(last)) = (start_pt.take(), last_pt.take()) {
|
||||||
|
if start.xy != last.xy {
|
||||||
|
points.push(start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
println!("{:?}", el);
|
||||||
|
});
|
||||||
|
let n_points = points.len() as u32;
|
||||||
|
let points_ref = points.encode(encoder).transmute();
|
||||||
|
(n_points, points_ref)
|
||||||
|
}
|
||||||
|
|
||||||
impl Text for PietGpuText {
|
impl Text for PietGpuText {
|
||||||
type Font = PietGpuFont;
|
type Font = PietGpuFont;
|
||||||
type FontBuilder = PietGpuFontBuilder;
|
type FontBuilder = PietGpuFontBuilder;
|
||||||
|
@ -295,3 +347,10 @@ fn to_scene_point(point: Point) -> scene::Point {
|
||||||
xy: [point.x as f32, point.y as f32],
|
xy: [point.x as f32, point.y as f32],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: allow #[derive(Clone)] in piet-gpu-derive.
|
||||||
|
fn clone_scene_pt(p: &scene::Point) -> scene::Point {
|
||||||
|
scene::Point {
|
||||||
|
xy: p.xy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue