diff --git a/piet-gpu-types/src/annotated.rs b/piet-gpu-types/src/annotated.rs index 2460992..da17481 100644 --- a/piet-gpu-types/src/annotated.rs +++ b/piet-gpu-types/src/annotated.rs @@ -3,20 +3,15 @@ use piet_gpu_derive::piet_gpu; piet_gpu! { #[gpu_write] mod annotated { - struct AnnoFill { - // The bbox is always first, as we take advantage of common - // layout when binning. - bbox: [f32; 4], - rgba_color: u32, - } struct AnnoFillImage { bbox: [f32; 4], index: u32, offset: [i16; 2], } - struct AnnoStroke { + struct AnnoColor { bbox: [f32; 4], rgba_color: u32, + // For stroked fills. // For the nonuniform scale case, this needs to be a 2x2 matrix. // That's expected to be uncommon, so we could special-case it. linewidth: f32, @@ -26,8 +21,7 @@ piet_gpu! { } enum Annotated { Nop, - Stroke(AnnoStroke), - Fill(AnnoFill), + Color(TagFlags, AnnoColor), FillImage(AnnoFillImage), BeginClip(AnnoClip), EndClip(AnnoClip), diff --git a/piet-gpu/shader/annotated.h b/piet-gpu/shader/annotated.h index 63d4bdb..bcadd44 100644 --- a/piet-gpu/shader/annotated.h +++ b/piet-gpu/shader/annotated.h @@ -2,15 +2,11 @@ // Code auto-generated by piet-gpu-derive -struct AnnoFillRef { - uint offset; -}; - struct AnnoFillImageRef { uint offset; }; -struct AnnoStrokeRef { +struct AnnoColorRef { uint offset; }; @@ -22,17 +18,6 @@ struct AnnotatedRef { uint offset; }; -struct AnnoFill { - vec4 bbox; - uint rgba_color; -}; - -#define AnnoFill_size 20 - -AnnoFillRef AnnoFill_index(AnnoFillRef ref, uint index) { - return AnnoFillRef(ref.offset + index * AnnoFill_size); -} - struct AnnoFillImage { vec4 bbox; uint index; @@ -45,16 +30,16 @@ AnnoFillImageRef AnnoFillImage_index(AnnoFillImageRef ref, uint index) { return AnnoFillImageRef(ref.offset + index * AnnoFillImage_size); } -struct AnnoStroke { +struct AnnoColor { vec4 bbox; uint rgba_color; float linewidth; }; -#define AnnoStroke_size 24 +#define AnnoColor_size 24 -AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) { - return AnnoStrokeRef(ref.offset + index * AnnoStroke_size); +AnnoColorRef AnnoColor_index(AnnoColorRef ref, uint index) { + return AnnoColorRef(ref.offset + index * AnnoColor_size); } struct AnnoClip { @@ -68,11 +53,10 @@ AnnoClipRef AnnoClip_index(AnnoClipRef ref, uint index) { } #define Annotated_Nop 0 -#define Annotated_Stroke 1 -#define Annotated_Fill 2 -#define Annotated_FillImage 3 -#define Annotated_BeginClip 4 -#define Annotated_EndClip 5 +#define Annotated_Color 1 +#define Annotated_FillImage 2 +#define Annotated_BeginClip 3 +#define Annotated_EndClip 4 #define Annotated_size 28 AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) { @@ -84,28 +68,6 @@ struct AnnotatedTag { uint flags; }; -AnnoFill AnnoFill_read(Alloc a, AnnoFillRef ref) { - uint ix = ref.offset >> 2; - uint raw0 = read_mem(a, ix + 0); - uint raw1 = read_mem(a, ix + 1); - uint raw2 = read_mem(a, ix + 2); - uint raw3 = read_mem(a, ix + 3); - uint raw4 = read_mem(a, ix + 4); - AnnoFill s; - s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); - s.rgba_color = raw4; - return s; -} - -void AnnoFill_write(Alloc a, AnnoFillRef ref, AnnoFill s) { - uint ix = ref.offset >> 2; - write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); - write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); - write_mem(a, ix + 2, floatBitsToUint(s.bbox.z)); - write_mem(a, ix + 3, floatBitsToUint(s.bbox.w)); - write_mem(a, ix + 4, s.rgba_color); -} - AnnoFillImage AnnoFillImage_read(Alloc a, AnnoFillImageRef ref) { uint ix = ref.offset >> 2; uint raw0 = read_mem(a, ix + 0); @@ -131,7 +93,7 @@ void AnnoFillImage_write(Alloc a, AnnoFillImageRef ref, AnnoFillImage s) { write_mem(a, ix + 5, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16)); } -AnnoStroke AnnoStroke_read(Alloc a, AnnoStrokeRef ref) { +AnnoColor AnnoColor_read(Alloc a, AnnoColorRef ref) { uint ix = ref.offset >> 2; uint raw0 = read_mem(a, ix + 0); uint raw1 = read_mem(a, ix + 1); @@ -139,14 +101,14 @@ AnnoStroke AnnoStroke_read(Alloc a, AnnoStrokeRef ref) { uint raw3 = read_mem(a, ix + 3); uint raw4 = read_mem(a, ix + 4); uint raw5 = read_mem(a, ix + 5); - AnnoStroke s; + AnnoColor s; s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); s.rgba_color = raw4; s.linewidth = uintBitsToFloat(raw5); return s; } -void AnnoStroke_write(Alloc a, AnnoStrokeRef ref, AnnoStroke s) { +void AnnoColor_write(Alloc a, AnnoColorRef ref, AnnoColor s) { uint ix = ref.offset >> 2; write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); @@ -180,12 +142,8 @@ AnnotatedTag Annotated_tag(Alloc a, AnnotatedRef ref) { return AnnotatedTag(tag_and_flags & 0xffff, tag_and_flags >> 16); } -AnnoStroke Annotated_Stroke_read(Alloc a, AnnotatedRef ref) { - return AnnoStroke_read(a, AnnoStrokeRef(ref.offset + 4)); -} - -AnnoFill Annotated_Fill_read(Alloc a, AnnotatedRef ref) { - return AnnoFill_read(a, AnnoFillRef(ref.offset + 4)); +AnnoColor Annotated_Color_read(Alloc a, AnnotatedRef ref) { + return AnnoColor_read(a, AnnoColorRef(ref.offset + 4)); } AnnoFillImage Annotated_FillImage_read(Alloc a, AnnotatedRef ref) { @@ -204,14 +162,9 @@ void Annotated_Nop_write(Alloc a, AnnotatedRef ref) { write_mem(a, ref.offset >> 2, Annotated_Nop); } -void Annotated_Stroke_write(Alloc a, AnnotatedRef ref, AnnoStroke s) { - write_mem(a, ref.offset >> 2, Annotated_Stroke); - AnnoStroke_write(a, AnnoStrokeRef(ref.offset + 4), s); -} - -void Annotated_Fill_write(Alloc a, AnnotatedRef ref, AnnoFill s) { - write_mem(a, ref.offset >> 2, Annotated_Fill); - AnnoFill_write(a, AnnoFillRef(ref.offset + 4), s); +void Annotated_Color_write(Alloc a, AnnotatedRef ref, uint flags, AnnoColor s) { + write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_Color); + AnnoColor_write(a, AnnoColorRef(ref.offset + 4), s); } void Annotated_FillImage_write(Alloc a, AnnotatedRef ref, AnnoFillImage s) { diff --git a/piet-gpu/shader/backdrop.comp b/piet-gpu/shader/backdrop.comp index 03212c9..3c94017 100644 --- a/piet-gpu/shader/backdrop.comp +++ b/piet-gpu/shader/backdrop.comp @@ -46,9 +46,13 @@ void main() { // Work assignment: 1 thread : 1 path element uint row_count = 0; if (element_ix < conf.n_elements) { - uint tag = Annotated_tag(conf.anno_alloc, ref).tag; - switch (tag) { - case Annotated_Fill: + AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref); + switch (tag.tag) { + case Annotated_Color: + if (fill_mode_from_flags(tag.flags) != MODE_NONZERO) { + break; + } + // Fall through. case Annotated_FillImage: case Annotated_BeginClip: PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size); diff --git a/piet-gpu/shader/backdrop.spv b/piet-gpu/shader/backdrop.spv index 932192a..8acb87f 100644 Binary files a/piet-gpu/shader/backdrop.spv and b/piet-gpu/shader/backdrop.spv differ diff --git a/piet-gpu/shader/binning.comp b/piet-gpu/shader/binning.comp index c5cc806..acebdc5 100644 --- a/piet-gpu/shader/binning.comp +++ b/piet-gpu/shader/binning.comp @@ -60,18 +60,17 @@ void main() { } int x0 = 0, y0 = 0, x1 = 0, y1 = 0; switch (tag) { - case Annotated_Fill: + case Annotated_Color: case Annotated_FillImage: - case Annotated_Stroke: case Annotated_BeginClip: case Annotated_EndClip: // Note: we take advantage of the fact that these drawing elements // have the bbox at the same place in their layout. - AnnoFill fill = Annotated_Fill_read(conf.anno_alloc, ref); - x0 = int(floor(fill.bbox.x * SX)); - y0 = int(floor(fill.bbox.y * SY)); - x1 = int(ceil(fill.bbox.z * SX)); - y1 = int(ceil(fill.bbox.w * SY)); + AnnoClip clip = Annotated_BeginClip_read(conf.anno_alloc, ref); + x0 = int(floor(clip.bbox.x * SX)); + y0 = int(floor(clip.bbox.y * SY)); + x1 = int(ceil(clip.bbox.z * SX)); + y1 = int(ceil(clip.bbox.w * SY)); break; } diff --git a/piet-gpu/shader/binning.spv b/piet-gpu/shader/binning.spv index 96fbcdd..82853e3 100644 Binary files a/piet-gpu/shader/binning.spv and b/piet-gpu/shader/binning.spv differ diff --git a/piet-gpu/shader/coarse.comp b/piet-gpu/shader/coarse.comp index 332fb48..fb7f448 100644 --- a/piet-gpu/shader/coarse.comp +++ b/piet-gpu/shader/coarse.comp @@ -202,9 +202,8 @@ void main() { // Bounding box of element in pixel coordinates. uint tile_count; switch (tag) { - case Annotated_Fill: + case Annotated_Color: case Annotated_FillImage: - case Annotated_Stroke: case Annotated_BeginClip: case Annotated_EndClip: // We have one "path" for each element, even if the element isn't @@ -305,25 +304,33 @@ void main() { // If that turns out to be expensive, maybe we can pack it into // shared memory (or perhaps just the tag). ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size); - tag = Annotated_tag(conf.anno_alloc, ref).tag; + AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref); if (clip_zero_depth == 0) { - switch (tag) { - case Annotated_Fill: + switch (tag.tag) { + case Annotated_Color: Tile tile = Tile_read(read_tile_alloc(element_ref_ix), TileRef(sh_tile_base[element_ref_ix] + (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size)); - AnnoFill fill = Annotated_Fill_read(conf.anno_alloc, ref); + AnnoColor fill = Annotated_Color_read(conf.anno_alloc, ref); if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) { break; } - if (tile.tile.offset != 0) { - CmdFill cmd_fill; - cmd_fill.tile_ref = tile.tile.offset; - cmd_fill.backdrop = tile.backdrop; - cmd_fill.rgba_color = fill.rgba_color; - Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill); + if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) { + if (tile.tile.offset != 0) { + CmdFill cmd_fill; + cmd_fill.tile_ref = tile.tile.offset; + cmd_fill.backdrop = tile.backdrop; + cmd_fill.rgba_color = fill.rgba_color; + Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill); + } else { + Cmd_Solid_write(cmd_alloc, cmd_ref, CmdSolid(fill.rgba_color)); + } } else { - Cmd_Solid_write(cmd_alloc, cmd_ref, CmdSolid(fill.rgba_color)); + CmdStroke cmd_stroke; + cmd_stroke.tile_ref = tile.tile.offset; + cmd_stroke.half_width = 0.5 * fill.linewidth; + cmd_stroke.rgba_color = fill.rgba_color; + Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke); } cmd_ref.offset += Cmd_size; break; @@ -387,24 +394,10 @@ void main() { cmd_ref.offset += Cmd_size; } break; - case Annotated_Stroke: - tile = Tile_read(read_tile_alloc(element_ref_ix), TileRef(sh_tile_base[element_ref_ix] - + (sh_tile_stride[element_ref_ix] * tile_y + tile_x) * Tile_size)); - AnnoStroke stroke = Annotated_Stroke_read(conf.anno_alloc, ref); - CmdStroke cmd_stroke; - cmd_stroke.tile_ref = tile.tile.offset; - cmd_stroke.half_width = 0.5 * stroke.linewidth; - cmd_stroke.rgba_color = stroke.rgba_color; - if (!alloc_cmd(cmd_alloc, cmd_ref, cmd_limit)) { - break; - } - Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke); - cmd_ref.offset += Cmd_size; - break; } } else { // In "clip zero" state, suppress all drawing - switch (tag) { + switch (tag.tag) { case Annotated_BeginClip: clip_depth++; break; diff --git a/piet-gpu/shader/coarse.spv b/piet-gpu/shader/coarse.spv index a7637c6..09bad96 100644 Binary files a/piet-gpu/shader/coarse.spv and b/piet-gpu/shader/coarse.spv differ diff --git a/piet-gpu/shader/elements.comp b/piet-gpu/shader/elements.comp index 1c8accb..1289cc2 100644 --- a/piet-gpu/shader/elements.comp +++ b/piet-gpu/shader/elements.comp @@ -288,7 +288,8 @@ void main() { // registers (though register pressure is an issue). ElementRef this_ref = Element_index(ref, i); ElementTag tag = Element_tag(this_ref); - bool is_stroke = fill_mode_from_flags(tag.flags) == MODE_STROKE; + uint fill_mode = fill_mode_from_flags(tag.flags); + bool is_stroke = fill_mode == MODE_STROKE; switch (tag.tag) { case Element_Line: LineSeg line = Element_Line_read(this_ref); @@ -353,22 +354,18 @@ void main() { break; case Element_FillColor: FillColor fill = Element_FillColor_read(this_ref); - // TODO: merge paths when annotations use tag flags. + AnnoColor anno_fill; + anno_fill.rgba_color = fill.rgba_color; if (is_stroke) { - AnnoStroke anno_stroke; - anno_stroke.rgba_color = fill.rgba_color; vec2 lw = get_linewidth(st); - anno_stroke.bbox = st.bbox + vec4(-lw, lw); - anno_stroke.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z)); - AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); - Annotated_Stroke_write(conf.anno_alloc, out_ref, anno_stroke); + anno_fill.bbox = st.bbox + vec4(-lw, lw); + anno_fill.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z)); } else { - AnnoFill anno_fill; - anno_fill.rgba_color = fill.rgba_color; anno_fill.bbox = st.bbox; - AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); - Annotated_Fill_write(conf.anno_alloc, out_ref, anno_fill); + anno_fill.linewidth = 0.0; } + AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); + Annotated_Color_write(conf.anno_alloc, out_ref, fill_mode, anno_fill); break; case Element_FillImage: FillImage fill_img = Element_FillImage_read(this_ref); @@ -376,7 +373,7 @@ void main() { anno_fill_img.index = fill_img.index; anno_fill_img.offset = fill_img.offset; anno_fill_img.bbox = st.bbox; - AnnotatedRef out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); + out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); Annotated_FillImage_write(conf.anno_alloc, out_ref, anno_fill_img); break; case Element_BeginClip: diff --git a/piet-gpu/shader/elements.spv b/piet-gpu/shader/elements.spv index 6ed690d..b83e065 100644 Binary files a/piet-gpu/shader/elements.spv and b/piet-gpu/shader/elements.spv differ diff --git a/piet-gpu/shader/tile_alloc.comp b/piet-gpu/shader/tile_alloc.comp index fd89bf7..21039c5 100644 --- a/piet-gpu/shader/tile_alloc.comp +++ b/piet-gpu/shader/tile_alloc.comp @@ -43,18 +43,17 @@ void main() { } int x0 = 0, y0 = 0, x1 = 0, y1 = 0; switch (tag) { - case Annotated_Fill: + case Annotated_Color: case Annotated_FillImage: - case Annotated_Stroke: case Annotated_BeginClip: case Annotated_EndClip: // Note: we take advantage of the fact that fills, strokes, and // clips have compatible layout. - AnnoFill fill = Annotated_Fill_read(conf.anno_alloc, ref); - x0 = int(floor(fill.bbox.x * SX)); - y0 = int(floor(fill.bbox.y * SY)); - x1 = int(ceil(fill.bbox.z * SX)); - y1 = int(ceil(fill.bbox.w * SY)); + AnnoClip clip = Annotated_BeginClip_read(conf.anno_alloc, ref); + x0 = int(floor(clip.bbox.x * SX)); + y0 = int(floor(clip.bbox.y * SY)); + x1 = int(ceil(clip.bbox.z * SX)); + y1 = int(ceil(clip.bbox.w * SY)); break; } x0 = clamp(x0, 0, int(conf.width_in_tiles)); diff --git a/piet-gpu/shader/tile_alloc.spv b/piet-gpu/shader/tile_alloc.spv index 66a9fd2..fc2e448 100644 Binary files a/piet-gpu/shader/tile_alloc.spv and b/piet-gpu/shader/tile_alloc.spv differ