mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Merge branch 'master' into gradient
This commit is contained in:
commit
59728868de
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
**/shader/* linguist-language=glsl
|
|
@ -1,6 +1,8 @@
|
|||
use piet_gpu_hal::{Error, ImageLayout, Instance, Session, SubmittedCmdBuf};
|
||||
|
||||
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH};
|
||||
use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH, render_svg};
|
||||
|
||||
use clap::{App, Arg};
|
||||
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
|
@ -11,6 +13,17 @@ use winit::{
|
|||
const NUM_FRAMES: usize = 2;
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
let matches = App::new("piet-gpu test")
|
||||
.arg(Arg::with_name("INPUT").index(1))
|
||||
.arg(Arg::with_name("flip").short("f").long("flip"))
|
||||
.arg(
|
||||
Arg::with_name("scale")
|
||||
.short("s")
|
||||
.long("scale")
|
||||
.takes_value(true),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let event_loop = EventLoop::new();
|
||||
let window = WindowBuilder::new()
|
||||
.with_inner_size(winit::dpi::LogicalSize {
|
||||
|
@ -36,7 +49,18 @@ fn main() -> Result<(), Error> {
|
|||
.collect::<Result<Vec<_>, Error>>()?;
|
||||
|
||||
let mut ctx = PietGpuRenderContext::new();
|
||||
render_scene(&mut ctx);
|
||||
if let Some(input) = matches.value_of("INPUT") {
|
||||
let mut scale = matches
|
||||
.value_of("scale")
|
||||
.map(|scale| scale.parse().unwrap())
|
||||
.unwrap_or(8.0);
|
||||
if matches.is_present("flip") {
|
||||
scale = -scale;
|
||||
}
|
||||
render_svg(&mut ctx, input, scale);
|
||||
} else {
|
||||
render_scene(&mut ctx);
|
||||
}
|
||||
|
||||
let mut renderer = Renderer::new(&session)?;
|
||||
renderer.upload_render_ctx(&mut ctx)?;
|
||||
|
|
|
@ -148,12 +148,6 @@ void main() {
|
|||
uint part_start_ix = 0;
|
||||
uint ready_ix = 0;
|
||||
|
||||
// Leave room for the fine rasterizer scratch allocation.
|
||||
Alloc scratch_alloc = slice_mem(cmd_alloc, 0, Alloc_size);
|
||||
cmd_ref.offset += Alloc_size;
|
||||
|
||||
uint num_begin_slots = 0;
|
||||
uint begin_slot = 0;
|
||||
bool mem_ok = mem_error == NO_ERROR;
|
||||
while (true) {
|
||||
for (uint i = 0; i < N_SLICE; i++) {
|
||||
|
@ -390,8 +384,6 @@ void main() {
|
|||
if (clip_depth < 32) {
|
||||
clip_one_mask &= ~(1 << clip_depth);
|
||||
}
|
||||
begin_slot++;
|
||||
num_begin_slots = max(num_begin_slots, begin_slot);
|
||||
}
|
||||
clip_depth++;
|
||||
break;
|
||||
|
@ -403,7 +395,6 @@ void main() {
|
|||
}
|
||||
Cmd_Solid_write(cmd_alloc, cmd_ref);
|
||||
cmd_ref.offset += 4;
|
||||
begin_slot--;
|
||||
Cmd_EndClip_write(cmd_alloc, cmd_ref);
|
||||
cmd_ref.offset += 4;
|
||||
}
|
||||
|
@ -431,13 +422,5 @@ void main() {
|
|||
}
|
||||
if (bin_tile_x + tile_x < conf.width_in_tiles && bin_tile_y + tile_y < conf.height_in_tiles) {
|
||||
Cmd_End_write(cmd_alloc, cmd_ref);
|
||||
if (num_begin_slots > 0) {
|
||||
// Write scratch allocation: one state per BeginClip per rasterizer chunk.
|
||||
uint scratch_size = num_begin_slots * TILE_WIDTH_PX * TILE_HEIGHT_PX * CLIP_STATE_SIZE * 4;
|
||||
MallocResult scratch = malloc(scratch_size);
|
||||
// Ignore scratch.failed; we don't use the allocation and kernel4
|
||||
// checks for memory overflow before using it.
|
||||
alloc_write(scratch_alloc, scratch_alloc.offset, scratch.alloc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -35,6 +35,7 @@ layout(rgba8, set = 0, binding = 4) uniform restrict readonly image2D gradients;
|
|||
#include "ptcl.h"
|
||||
#include "tile.h"
|
||||
|
||||
#define MAX_BLEND_STACK 128
|
||||
mediump vec3 tosRGB(mediump vec3 rgb) {
|
||||
bvec3 cutoff = greaterThanEqual(rgb, vec3(0.0031308));
|
||||
mediump vec3 below = vec3(12.92)*rgb;
|
||||
|
@ -84,13 +85,11 @@ void main() {
|
|||
Alloc cmd_alloc = slice_mem(conf.ptcl_alloc, tile_ix * PTCL_INITIAL_ALLOC, PTCL_INITIAL_ALLOC);
|
||||
CmdRef cmd_ref = CmdRef(cmd_alloc.offset);
|
||||
|
||||
// Read scrach space allocation, written first in the command list.
|
||||
Alloc scratch_alloc = alloc_read(cmd_alloc, cmd_ref.offset);
|
||||
cmd_ref.offset += Alloc_size;
|
||||
|
||||
uvec2 xy_uint = uvec2(gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_WorkGroupID.x, gl_LocalInvocationID.y + TILE_HEIGHT_PX * gl_WorkGroupID.y);
|
||||
vec2 xy = vec2(xy_uint);
|
||||
mediump vec4 rgba[CHUNK];
|
||||
uint blend_stack[MAX_BLEND_STACK][CHUNK];
|
||||
mediump float blend_alpha_stack[MAX_BLEND_STACK][CHUNK];
|
||||
for (uint i = 0; i < CHUNK; i++) {
|
||||
rgba[i] = vec4(0.0);
|
||||
}
|
||||
|
@ -203,14 +202,12 @@ void main() {
|
|||
cmd_ref.offset += 4 + CmdImage_size;
|
||||
break;
|
||||
case Cmd_BeginClip:
|
||||
uint base_ix = (scratch_alloc.offset >> 2) + CLIP_STATE_SIZE * (clip_depth * TILE_WIDTH_PX * TILE_HEIGHT_PX +
|
||||
gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_LocalInvocationID.y);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
uvec2 offset = chunk_offset(k);
|
||||
uint srgb = packsRGB(vec4(rgba[k]));
|
||||
mediump float alpha = clamp(abs(area[k]), 0.0, 1.0);
|
||||
write_mem(scratch_alloc, base_ix + 0 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX), srgb);
|
||||
write_mem(scratch_alloc, base_ix + 1 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX), floatBitsToUint(alpha));
|
||||
// We reject any inputs that might overflow in render_ctx.rs.
|
||||
// The following is a sanity check so we don't corrupt memory should there be malformed inputs.
|
||||
uint d = min(clip_depth, MAX_BLEND_STACK - 1);
|
||||
blend_stack[d][k] = packsRGB(vec4(rgba[k]));
|
||||
blend_alpha_stack[d][k] = clamp(abs(area[k]), 0.0, 1.0);
|
||||
rgba[k] = vec4(0.0);
|
||||
}
|
||||
clip_depth++;
|
||||
|
@ -218,14 +215,10 @@ void main() {
|
|||
break;
|
||||
case Cmd_EndClip:
|
||||
clip_depth--;
|
||||
base_ix = (scratch_alloc.offset >> 2) + CLIP_STATE_SIZE * (clip_depth * TILE_WIDTH_PX * TILE_HEIGHT_PX +
|
||||
gl_LocalInvocationID.x + TILE_WIDTH_PX * gl_LocalInvocationID.y);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
uvec2 offset = chunk_offset(k);
|
||||
uint srgb = read_mem(scratch_alloc, base_ix + 0 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX));
|
||||
uint alpha = read_mem(scratch_alloc, base_ix + 1 + CLIP_STATE_SIZE * (offset.x + offset.y * TILE_WIDTH_PX));
|
||||
mediump vec4 bg = unpacksRGB(srgb);
|
||||
mediump vec4 fg = rgba[k] * area[k] * uintBitsToFloat(alpha);
|
||||
uint d = min(clip_depth, MAX_BLEND_STACK - 1);
|
||||
mediump vec4 bg = unpacksRGB(blend_stack[d][k]);
|
||||
mediump vec4 fg = rgba[k] * area[k] * blend_alpha_stack[d][k];
|
||||
rgba[k] = bg * (1.0 - fg.a) + fg;
|
||||
}
|
||||
cmd_ref.offset += 4;
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -30,6 +30,7 @@ layout(set = 0, binding = 1) readonly buffer ConfigBuf {
|
|||
#define Q_ACCURACY (ACCURACY * 0.1)
|
||||
#define REM_ACCURACY (ACCURACY - Q_ACCURACY)
|
||||
#define MAX_HYPOT2 (432.0 * Q_ACCURACY * Q_ACCURACY)
|
||||
#define MAX_QUADS 16
|
||||
|
||||
vec2 eval_quad(vec2 p0, vec2 p1, vec2 p2, float t) {
|
||||
float mt = 1.0 - t;
|
||||
|
@ -113,6 +114,8 @@ void main() {
|
|||
float err = err_v.x * err_v.x + err_v.y * err_v.y;
|
||||
// The number of quadratics.
|
||||
uint n_quads = max(uint(ceil(pow(err * (1.0 / MAX_HYPOT2), 1.0 / 6.0))), 1);
|
||||
n_quads = min(n_quads, MAX_QUADS);
|
||||
SubdivResult keep_params[MAX_QUADS];
|
||||
// Iterate over quadratics and tote up the estimated number of segments.
|
||||
float val = 0.0;
|
||||
vec2 qp0 = cubic.p0;
|
||||
|
@ -123,6 +126,7 @@ void main() {
|
|||
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t - 0.5 * step);
|
||||
qp1 = 2.0 * qp1 - 0.5 * (qp0 + qp2);
|
||||
SubdivResult params = estimate_subdiv(qp0, qp1, qp2, sqrt(REM_ACCURACY));
|
||||
keep_params[i] = params;
|
||||
val += params.val;
|
||||
|
||||
qp0 = qp2;
|
||||
|
@ -144,7 +148,7 @@ void main() {
|
|||
vec2 qp2 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t);
|
||||
vec2 qp1 = eval_cubic(cubic.p0, cubic.p1, cubic.p2, cubic.p3, t - 0.5 * step);
|
||||
qp1 = 2.0 * qp1 - 0.5 * (qp0 + qp2);
|
||||
SubdivResult params = estimate_subdiv(qp0, qp1, qp2, sqrt(REM_ACCURACY));
|
||||
SubdivResult params = keep_params[i];
|
||||
float u0 = approx_parabola_inv_integral(params.a0);
|
||||
float u2 = approx_parabola_inv_integral(params.a2);
|
||||
float uscale = 1.0 / (u2 - u0);
|
||||
|
|
Binary file not shown.
|
@ -34,6 +34,8 @@ const WIDTH_IN_TILES: usize = 128;
|
|||
const HEIGHT_IN_TILES: usize = 96;
|
||||
const PTCL_INITIAL_ALLOC: usize = 1024;
|
||||
|
||||
const MAX_BLEND_STACK: usize = 128;
|
||||
|
||||
const N_CIRCLES: usize = 0;
|
||||
|
||||
pub fn render_svg(rc: &mut impl RenderContext, filename: &str, scale: f64) {
|
||||
|
|
|
@ -8,6 +8,7 @@ use piet::{
|
|||
Color, Error, FixedGradient, FontFamily, HitTestPoint, ImageFormat, InterpolationMode,
|
||||
IntoBrush, LineMetric, RenderContext, StrokeStyle, Text, TextLayout, TextLayoutBuilder,
|
||||
};
|
||||
use crate::MAX_BLEND_STACK;
|
||||
|
||||
use piet_gpu_types::encoder::{Encode, Encoder};
|
||||
use piet_gpu_types::scene::{
|
||||
|
@ -215,6 +216,9 @@ impl RenderContext for PietGpuRenderContext {
|
|||
self.elements.push(Element::BeginClip(Clip {
|
||||
bbox: Default::default(),
|
||||
}));
|
||||
if self.clip_stack.len() >= MAX_BLEND_STACK {
|
||||
panic!("Maximum clip/blend stack size {} exceeded", MAX_BLEND_STACK);
|
||||
}
|
||||
self.clip_stack.push(ClipElement {
|
||||
bbox: None,
|
||||
begin_ix,
|
||||
|
|
Loading…
Reference in a new issue