clip changes/blend group alpha

Adds blend group alpha. Also changes the clip logic to sync blend mode and alpha from BeginClip to EndClip in clip_leaf.
This commit is contained in:
Chad Brokaw 2022-11-29 13:28:25 -05:00
parent 6d8428e377
commit 28082af9ec
13 changed files with 123 additions and 54 deletions

View file

@ -124,12 +124,14 @@ impl<'a> GlyphProvider<'a> {
if let Some(xform) = xform_stack.last() { if let Some(xform) = xform_stack.last() {
builder.push_layer( builder.push_layer(
Mix::Clip, Mix::Clip,
1.0,
Affine::IDENTITY, Affine::IDENTITY,
&convert_transformed_path(path.elements(), xform), &convert_transformed_path(path.elements(), xform),
); );
} else { } else {
builder.push_layer( builder.push_layer(
Mix::Clip, Mix::Clip,
1.0,
Affine::IDENTITY, Affine::IDENTITY,
&convert_path(path.elements()), &convert_path(path.elements()),
); );
@ -144,7 +146,7 @@ impl<'a> GlyphProvider<'a> {
max = *xform * max; max = *xform * max;
} }
let rect = Rect::from_points(min, max); let rect = Rect::from_points(min, max);
builder.push_layer(Mix::Normal, Affine::IDENTITY, &rect); builder.push_layer(Mix::Normal, 1.0, Affine::IDENTITY, &rect);
} }
Command::PopLayer => builder.pop_layer(), Command::PopLayer => builder.pop_layer(),
Command::BeginBlend(bounds, mode) => { Command::BeginBlend(bounds, mode) => {
@ -155,7 +157,7 @@ impl<'a> GlyphProvider<'a> {
max = *xform * max; max = *xform * max;
} }
let rect = Rect::from_points(min, max); let rect = Rect::from_points(min, max);
builder.push_layer(convert_blend(*mode), Affine::IDENTITY, &rect); builder.push_layer(convert_blend(*mode), 1.0, Affine::IDENTITY, &rect);
} }
Command::EndBlend => builder.pop_layer(), Command::EndBlend => builder.pop_layer(),
Command::SimpleFill(path_index, brush, brush_xform) => { Command::SimpleFill(path_index, brush, brush_xform) => {

View file

@ -24,7 +24,7 @@ use smallvec::SmallVec;
/// Builder for constructing a scene or scene fragment. /// Builder for constructing a scene or scene fragment.
pub struct SceneBuilder<'a> { pub struct SceneBuilder<'a> {
scene: &'a mut SceneData, scene: &'a mut SceneData,
layers: SmallVec<[BlendMode; 8]>, layer_depth: u32,
} }
impl<'a> SceneBuilder<'a> { impl<'a> SceneBuilder<'a> {
@ -45,7 +45,7 @@ impl<'a> SceneBuilder<'a> {
scene.reset(is_fragment); scene.reset(is_fragment);
Self { Self {
scene, scene,
layers: Default::default(), layer_depth: 0,
} }
} }
@ -54,6 +54,7 @@ impl<'a> SceneBuilder<'a> {
pub fn push_layer( pub fn push_layer(
&mut self, &mut self,
blend: impl Into<BlendMode>, blend: impl Into<BlendMode>,
alpha: f32,
transform: Affine, transform: Affine,
shape: &impl Shape, shape: &impl Shape,
) { ) {
@ -65,14 +66,15 @@ impl<'a> SceneBuilder<'a> {
// all drawing until the layer is popped. // all drawing until the layer is popped.
self.encode_path(&Rect::new(0.0, 0.0, 0.0, 0.0), true); self.encode_path(&Rect::new(0.0, 0.0, 0.0, 0.0), true);
} }
self.begin_clip(blend); self.begin_clip(blend, alpha.clamp(0.0, 1.0));
self.layers.push(blend); self.layer_depth += 1;
} }
/// Pops the current layer. /// Pops the current layer.
pub fn pop_layer(&mut self) { pub fn pop_layer(&mut self) {
if let Some(blend) = self.layers.pop() { if self.layer_depth > 0 {
self.end_clip(blend); self.end_clip();
self.layer_depth -= 1;
} }
} }
@ -127,8 +129,8 @@ impl<'a> SceneBuilder<'a> {
/// Completes construction and finalizes the underlying scene. /// Completes construction and finalizes the underlying scene.
pub fn finish(mut self) { pub fn finish(mut self) {
while !self.layers.is_empty() { for _ in 0..self.layer_depth {
self.pop_layer(); self.end_clip();
} }
} }
} }
@ -250,10 +252,11 @@ impl<'a> SceneBuilder<'a> {
} }
/// Start a clip. /// Start a clip.
fn begin_clip(&mut self, blend: BlendMode) { fn begin_clip(&mut self, blend: BlendMode, alpha: f32) {
self.scene.drawtag_stream.push(DRAWTAG_BEGINCLIP); self.scene.drawtag_stream.push(DRAWTAG_BEGINCLIP);
let element = Clip { let element = Clip {
blend: encode_blend_mode(blend), blend: encode_blend_mode(blend),
alpha,
}; };
self.scene self.scene
.drawdata_stream .drawdata_stream
@ -261,14 +264,8 @@ impl<'a> SceneBuilder<'a> {
self.scene.n_clip += 1; self.scene.n_clip += 1;
} }
fn end_clip(&mut self, blend: BlendMode) { fn end_clip(&mut self) {
self.scene.drawtag_stream.push(DRAWTAG_ENDCLIP); self.scene.drawtag_stream.push(DRAWTAG_ENDCLIP);
let element = Clip {
blend: encode_blend_mode(blend),
};
self.scene
.drawdata_stream
.extend(bytemuck::bytes_of(&element));
// This is a dummy path, and will go away with the new clip impl. // This is a dummy path, and will go away with the new clip impl.
self.scene.tag_stream.push(0x10); self.scene.tag_stream.push(0x10);
self.scene.n_path += 1; self.scene.n_path += 1;
@ -284,8 +281,8 @@ fn encode_blend_mode(mode: BlendMode) -> u32 {
const DRAWTAG_FILLCOLOR: u32 = 0x44; const DRAWTAG_FILLCOLOR: u32 = 0x44;
const DRAWTAG_FILLLINGRADIENT: u32 = 0x114; const DRAWTAG_FILLLINGRADIENT: u32 = 0x114;
const DRAWTAG_FILLRADGRADIENT: u32 = 0x2dc; const DRAWTAG_FILLRADGRADIENT: u32 = 0x2dc;
const DRAWTAG_BEGINCLIP: u32 = 0x05; const DRAWTAG_BEGINCLIP: u32 = 0x89;
const DRAWTAG_ENDCLIP: u32 = 0x25; const DRAWTAG_ENDCLIP: u32 = 0xa1;
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
@ -324,6 +321,7 @@ pub struct FillImage {
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
pub struct Clip { pub struct Clip {
blend: u32, blend: u32,
alpha: f32,
} }
struct PathBuilder<'a> { struct PathBuilder<'a> {

View file

@ -146,7 +146,7 @@ fn render_clip_test(sb: &mut SceneBuilder) {
PathEl::LineTo((X0, Y1).into()), PathEl::LineTo((X0, Y1).into()),
PathEl::ClosePath, PathEl::ClosePath,
]; ];
sb.push_layer(Mix::Clip, Affine::IDENTITY, &path); sb.push_layer(Mix::Clip, 1.0, Affine::IDENTITY, &path);
} }
let rect = Rect::new(X0, Y0, X1, Y1); let rect = Rect::new(X0, Y0, X1, Y1);
sb.fill( sb.fill(
@ -178,7 +178,12 @@ fn render_alpha_test(sb: &mut SceneBuilder) {
None, None,
&make_diamond(1024.0, 125.0), &make_diamond(1024.0, 125.0),
); );
sb.push_layer(Mix::Clip, Affine::IDENTITY, &make_diamond(1024.0, 150.0)); sb.push_layer(
Mix::Clip,
1.0,
Affine::IDENTITY,
&make_diamond(1024.0, 150.0),
);
sb.fill( sb.fill(
Fill::NonZero, Fill::NonZero,
Affine::IDENTITY, Affine::IDENTITY,
@ -240,10 +245,10 @@ fn render_blend_square(sb: &mut SceneBuilder, blend: BlendMode, transform: Affin
Color::rgb8(0, 255, 0), Color::rgb8(0, 255, 0),
Color::rgb8(0, 0, 255), Color::rgb8(0, 0, 255),
]; ];
sb.push_layer(Mix::Normal, transform, &rect); sb.push_layer(Mix::Normal, 1.0, transform, &rect);
for (i, c) in COLORS.iter().enumerate() { for (i, c) in COLORS.iter().enumerate() {
let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::WHITE, *c]); let linear = LinearGradient::new((0.0, 0.0), (0.0, 200.0)).stops([Color::WHITE, *c]);
sb.push_layer(blend, transform, &rect); sb.push_layer(blend, 1.0, transform, &rect);
// squash the ellipse // squash the ellipse
let a = transform let a = transform
* Affine::translate((100., 100.)) * Affine::translate((100., 100.))
@ -273,12 +278,13 @@ fn blend_square(blend: BlendMode) -> SceneFragment {
#[allow(unused)] #[allow(unused)]
pub fn render_anim_frame(sb: &mut SceneBuilder, text: &mut SimpleText, i: usize) { pub fn render_anim_frame(sb: &mut SceneBuilder, text: &mut SimpleText, i: usize) {
let rect = Rect::from_origin_size(Point::new(0.0, 0.0), (1000.0, 1000.0));
sb.fill( sb.fill(
Fill::NonZero, Fill::NonZero,
Affine::IDENTITY, Affine::IDENTITY,
&Brush::Solid(Color::rgb8(128, 128, 128)), &Brush::Solid(Color::rgb8(128, 128, 128)),
None, None,
&Rect::from_origin_size(Point::new(0.0, 0.0), (1000.0, 1000.0)), &rect,
); );
let text_size = 60.0 + 40.0 * (0.01 * i as f32).sin(); let text_size = 60.0 + 40.0 * (0.01 * i as f32).sin();
let s = "\u{1f600}hello piet-gpu text!"; let s = "\u{1f600}hello piet-gpu text!";
@ -308,8 +314,32 @@ pub fn render_anim_frame(sb: &mut SceneBuilder, text: &mut SimpleText, i: usize)
Affine::IDENTITY, Affine::IDENTITY,
&Brush::Solid(Color::rgb8(128, 0, 0)), &Brush::Solid(Color::rgb8(128, 0, 0)),
None, None,
&&[PathEl::MoveTo(center), PathEl::LineTo(p1)][..], &[PathEl::MoveTo(center), PathEl::LineTo(p1)],
); );
sb.fill(
Fill::NonZero,
Affine::translate((150.0, 150.0)) * Affine::scale(0.2),
Color::RED,
None,
&rect,
);
let alpha = (i as f64 * 0.03).sin() as f32 * 0.5 + 0.5;
sb.push_layer(Mix::Normal, alpha, Affine::IDENTITY, &rect);
sb.fill(
Fill::NonZero,
Affine::translate((100.0, 100.0)) * Affine::scale(0.2),
Color::BLUE,
None,
&rect,
);
sb.fill(
Fill::NonZero,
Affine::translate((200.0, 200.0)) * Affine::scale(0.2),
Color::GREEN,
None,
&rect,
);
sb.pop_layer();
} }
#[allow(unused)] #[allow(unused)]

View file

@ -9,7 +9,7 @@
var<storage> config: Config; var<storage> config: Config;
@group(0) @binding(1) @group(0) @binding(1)
var<storage> clip_inp: array<i32>; var<storage> clip_inp: array<ClipInp>;
@group(0) @binding(2) @group(0) @binding(2)
var<storage> path_bboxes: array<PathBbox>; var<storage> path_bboxes: array<PathBbox>;
@ -26,6 +26,9 @@ var<storage, read_write> draw_monoids: array<DrawMonoid>;
@group(0) @binding(6) @group(0) @binding(6)
var<storage, read_write> clip_bboxes: array<vec4<f32>>; var<storage, read_write> clip_bboxes: array<vec4<f32>>;
@group(0) @binding(7)
var<storage, read_write> info: array<u32>;
let WG_SIZE = 256u; let WG_SIZE = 256u;
var<workgroup> sh_bic: array<Bic, 510 >; var<workgroup> sh_bic: array<Bic, 510 >;
var<workgroup> sh_stack: array<u32, WG_SIZE>; var<workgroup> sh_stack: array<u32, WG_SIZE>;
@ -68,7 +71,7 @@ fn search_link(bic: ptr<function, Bic>, ix: u32) -> i32 {
fn load_clip_inp(ix: u32) -> i32 { fn load_clip_inp(ix: u32) -> i32 {
if ix < config.n_clip { if ix < config.n_clip {
return clip_inp[ix]; return clip_inp[ix].path_ix;
} else { } else {
return -2147483648; return -2147483648;
// literal too large? // literal too large?
@ -185,8 +188,16 @@ fn main(
if !is_push && global_id.x < config.n_clip { if !is_push && global_id.x < config.n_clip {
// Fix up drawmonoid so path_ix of EndClip matches BeginClip // Fix up drawmonoid so path_ix of EndClip matches BeginClip
let path_ix = clip_inp[parent]; let parent_clip = clip_inp[parent];
draw_monoids[~inp].path_ix = u32(path_ix); let path_ix = parent_clip.path_ix;
let parent_ix = parent_clip.ix;
let ix = ~inp;
draw_monoids[ix].path_ix = u32(path_ix);
// Copy blend mode and alpha from parent
let di = draw_monoids[ix].info_offset;
let parent_di = draw_monoids[parent_ix].info_offset;
info[di] = info[parent_di];
info[di + 1u] = info[parent_di + 1u];
if grandparent >= 0 { if grandparent >= 0 {
bbox = sh_bbox[grandparent]; bbox = sh_bbox[grandparent];

View file

@ -8,7 +8,7 @@
var<storage> config: Config; var<storage> config: Config;
@group(0) @binding(1) @group(0) @binding(1)
var<storage> clip_inp: array<i32>; var<storage> clip_inp: array<ClipInp>;
@group(0) @binding(2) @group(0) @binding(2)
var<storage> path_bboxes: array<PathBbox>; var<storage> path_bboxes: array<PathBbox>;
@ -30,7 +30,7 @@ fn main(
@builtin(local_invocation_id) local_id: vec3<u32>, @builtin(local_invocation_id) local_id: vec3<u32>,
@builtin(workgroup_id) wg_id: vec3<u32>, @builtin(workgroup_id) wg_id: vec3<u32>,
) { ) {
let inp = clip_inp[global_id.x]; let inp = clip_inp[global_id.x].path_ix;
let is_push = inp >= 0; let is_push = inp >= 0;
var bic = Bic(1u - u32(is_push), u32(is_push)); var bic = Bic(1u - u32(is_push), u32(is_push));
// reverse scan of bicyclic semigroup // reverse scan of bicyclic semigroup

View file

@ -127,11 +127,12 @@ fn write_begin_clip() {
cmd_offset += 1u; cmd_offset += 1u;
} }
fn write_end_clip(blend: u32) { fn write_end_clip(end_clip: CmdEndClip) {
alloc_cmd(2u); alloc_cmd(3u);
ptcl[cmd_offset] = CMD_END_CLIP; ptcl[cmd_offset] = CMD_END_CLIP;
ptcl[cmd_offset + 1u] = blend; ptcl[cmd_offset + 1u] = end_clip.blend;
cmd_offset += 2u; ptcl[cmd_offset + 2u] = bitcast<u32>(end_clip.alpha);
cmd_offset += 3u;
} }
@compute @workgroup_size(256) @compute @workgroup_size(256)
@ -270,7 +271,6 @@ fn main(
} }
drawobj_ix = sh_drawobj_ix[el_ix]; drawobj_ix = sh_drawobj_ix[el_ix];
tag = scene[config.drawtag_base + drawobj_ix]; tag = scene[config.drawtag_base + drawobj_ix];
// TODO: clip logic
let seq_ix = ix - select(0u, sh_tile_count[el_ix - 1u], el_ix > 0u); let seq_ix = ix - select(0u, sh_tile_count[el_ix - 1u], el_ix > 0u);
let width = sh_tile_width[el_ix]; let width = sh_tile_width[el_ix];
let x = sh_tile_x0[el_ix] + seq_ix % width; let x = sh_tile_x0[el_ix] + seq_ix % width;
@ -281,9 +281,8 @@ fn main(
var is_blend = false; var is_blend = false;
if is_clip { if is_clip {
let BLEND_CLIP = (128u << 8u) | 3u; let BLEND_CLIP = (128u << 8u) | 3u;
let scene_offset = draw_monoids[drawobj_ix].scene_offset; let di = draw_monoids[drawobj_ix].info_offset;
let dd = config.drawdata_base + scene_offset; let blend = info[di];
let blend = scene[dd];
is_blend = blend != BLEND_CLIP; is_blend = blend != BLEND_CLIP;
} }
let include_tile = tile.segments != 0u || (tile.backdrop == 0) == is_clip || is_blend; let include_tile = tile.segments != 0u || (tile.backdrop == 0) == is_clip || is_blend;
@ -348,7 +347,7 @@ fn main(
write_grad(CMD_RAD_GRAD, index, info_offset); write_grad(CMD_RAD_GRAD, index, info_offset);
} }
// DRAWTAG_BEGIN_CLIP // DRAWTAG_BEGIN_CLIP
case 0x05u: { case 0x89u: {
if tile.segments == 0u && tile.backdrop == 0 { if tile.segments == 0u && tile.backdrop == 0 {
clip_zero_depth = clip_depth + 1u; clip_zero_depth = clip_depth + 1u;
} else { } else {
@ -359,10 +358,12 @@ fn main(
clip_depth += 1u; clip_depth += 1u;
} }
// DRAWTAG_END_CLIP // DRAWTAG_END_CLIP
case 0x25u: { case 0xa1u: {
clip_depth -= 1u; clip_depth -= 1u;
write_path(tile, -1.0); write_path(tile, -1.0);
write_end_clip(scene[dd]); let blend = info[di];
let alpha = bitcast<f32>(info[di + 1u]);
write_end_clip(CmdEndClip(blend, alpha));
render_blend_depth -= 1u; render_blend_depth -= 1u;
} }
default: {} default: {}
@ -371,11 +372,11 @@ fn main(
// In "clip zero" state, suppress all drawing // In "clip zero" state, suppress all drawing
switch drawtag { switch drawtag {
// DRAWTAG_BEGIN_CLIP // DRAWTAG_BEGIN_CLIP
case 0x05u: { case 0x89u: {
clip_depth += 1u; clip_depth += 1u;
} }
// DRAWTAG_END_CLIP // DRAWTAG_END_CLIP
case 0x25u: { case 0xa1u: {
if clip_depth == clip_zero_depth { if clip_depth == clip_zero_depth {
clip_zero_depth = 0u; clip_zero_depth = 0u;
} }

View file

@ -26,7 +26,7 @@ var<storage, read_write> draw_monoid: array<DrawMonoid>;
var<storage, read_write> info: array<u32>; var<storage, read_write> info: array<u32>;
@group(0) @binding(6) @group(0) @binding(6)
var<storage, read_write> clip_inp: array<i32>; var<storage, read_write> clip_inp: array<ClipInp>;
let WG_SIZE = 256u; let WG_SIZE = 256u;
@ -170,6 +170,15 @@ fn main(
info[di + 9u] = bitcast<u32>(ra); info[di + 9u] = bitcast<u32>(ra);
info[di + 10u] = bitcast<u32>(roff); info[di + 10u] = bitcast<u32>(roff);
} }
// DRAWTAG_BEGIN_CLIP
case 0x89u: {
// Store blend mode and alpha in info for two reasons: 1) we don't need
// to bind scene in clip_leaf which keeps us at 8 buffer bindings and 2)
// the logic in coarse to check clip state for tile inclusion is the
// same for BeginClip/EndClip.
info[di] = scene[dd];
info[di + 1u] = scene[dd + 1u];
}
default: {} default: {}
} }
} }
@ -178,6 +187,6 @@ fn main(
if tag_word == DRAWTAG_BEGIN_CLIP { if tag_word == DRAWTAG_BEGIN_CLIP {
path_ix = m.path_ix; path_ix = m.path_ix;
} }
clip_inp[m.clip_ix] = i32(path_ix); clip_inp[m.clip_ix] = ClipInp(ix, i32(path_ix));
} }
} }

View file

@ -82,6 +82,12 @@ fn read_rad_grad(cmd_ix: u32) -> CmdRadGrad {
return CmdRadGrad(index, matrx, xlat, c1, ra, roff); return CmdRadGrad(index, matrx, xlat, c1, ra, roff);
} }
fn read_end_clip(cmd_ix: u32) -> CmdEndClip {
let blend = ptcl[cmd_ix + 1u];
let alpha = bitcast<f32>(ptcl[cmd_ix + 2u]);
return CmdEndClip(blend, alpha);
}
#else #else
@group(0) @binding(3) @group(0) @binding(3)
@ -260,7 +266,7 @@ fn main(
} }
// CMD_END_CLIP // CMD_END_CLIP
case 10u: { case 10u: {
let blend = ptcl[cmd_ix + 1u]; let end_clip = read_end_clip(cmd_ix);
clip_depth -= 1u; clip_depth -= 1u;
for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) { for (var i = 0u; i < PIXELS_PER_THREAD; i += 1u) {
var bg_rgba: u32; var bg_rgba: u32;
@ -270,10 +276,10 @@ fn main(
// load from memory // load from memory
} }
let bg = unpack4x8unorm(bg_rgba); let bg = unpack4x8unorm(bg_rgba);
let fg = rgba[i] * area[i]; let fg = rgba[i] * area[i] * end_clip.alpha;
rgba[i] = blend_mix_compose(bg, fg, blend); rgba[i] = blend_mix_compose(bg, fg, end_clip.blend);
} }
cmd_ix += 2u; cmd_ix += 3u;
} }
// CMD_JUMP // CMD_JUMP
case 11u: { case 11u: {

View file

@ -10,6 +10,11 @@ fn bic_combine(x: Bic, y: Bic) -> Bic {
return Bic(x.a + y.a - m, x.b + y.b - m); return Bic(x.a + y.a - m, x.b + y.b - m);
} }
struct ClipInp {
ix: u32,
path_ix: i32,
}
struct ClipEl { struct ClipEl {
parent_ix: u32, parent_ix: u32,
bbox: vec4<f32>, bbox: vec4<f32>,

View file

@ -20,8 +20,8 @@ let DRAWTAG_FILL_COLOR = 0x44u;
let DRAWTAG_FILL_LIN_GRADIENT = 0x114u; let DRAWTAG_FILL_LIN_GRADIENT = 0x114u;
let DRAWTAG_FILL_RAD_GRADIENT = 0x2dcu; let DRAWTAG_FILL_RAD_GRADIENT = 0x2dcu;
let DRAWTAG_FILL_IMAGE = 0x48u; let DRAWTAG_FILL_IMAGE = 0x48u;
let DRAWTAG_BEGIN_CLIP = 0x05u; let DRAWTAG_BEGIN_CLIP = 0x89u;
let DRAWTAG_END_CLIP = 0x25u; let DRAWTAG_END_CLIP = 0xa1u;
fn draw_monoid_identity() -> DrawMonoid { fn draw_monoid_identity() -> DrawMonoid {
return DrawMonoid(); return DrawMonoid();

View file

@ -56,3 +56,8 @@ struct CmdRadGrad {
ra: f32, ra: f32,
roff: f32, roff: f32,
} }
struct CmdEndClip {
blend: u32,
alpha: f32,
}

View file

@ -16,7 +16,7 @@ const DRAWMONOID_SIZE: u64 = 16;
const MAX_DRAWINFO_SIZE: u64 = 44; const MAX_DRAWINFO_SIZE: u64 = 44;
const CLIP_BIC_SIZE: u64 = 8; const CLIP_BIC_SIZE: u64 = 8;
const CLIP_EL_SIZE: u64 = 32; const CLIP_EL_SIZE: u64 = 32;
const CLIP_INP_SIZE: u64 = 4; const CLIP_INP_SIZE: u64 = 8;
const CLIP_BBOX_SIZE: u64 = 16; const CLIP_BBOX_SIZE: u64 = 16;
const PATH_SIZE: u64 = 32; const PATH_SIZE: u64 = 32;
const DRAW_BBOX_SIZE: u64 = 16; const DRAW_BBOX_SIZE: u64 = 16;
@ -324,6 +324,7 @@ pub fn render_full(
clip_el_buf, clip_el_buf,
draw_monoid_buf, draw_monoid_buf,
clip_bbox_buf, clip_bbox_buf,
info_buf,
], ],
); );
} }

View file

@ -212,6 +212,7 @@ pub fn full_shaders(device: &Device, engine: &mut Engine) -> Result<FullShaders,
BindType::BufReadOnly, BindType::BufReadOnly,
BindType::Buffer, BindType::Buffer,
BindType::Buffer, BindType::Buffer,
BindType::Buffer,
], ],
)?; )?;
let binning = engine.add_shader( let binning = engine.add_shader(