diff --git a/piet-gpu-types/src/annotated.rs b/piet-gpu-types/src/annotated.rs index da17481..1bf3e9a 100644 --- a/piet-gpu-types/src/annotated.rs +++ b/piet-gpu-types/src/annotated.rs @@ -3,28 +3,33 @@ use piet_gpu_derive::piet_gpu; piet_gpu! { #[gpu_write] mod annotated { - struct AnnoFillImage { + struct AnnoImage { bbox: [f32; 4], + linewidth: f32, index: u32, offset: [i16; 2], } 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, + rgba_color: u32, } - struct AnnoClip { + struct AnnoBeginClip { + bbox: [f32; 4], + linewidth: f32, + } + struct AnnoEndClip { bbox: [f32; 4], } enum Annotated { Nop, Color(TagFlags, AnnoColor), - FillImage(AnnoFillImage), - BeginClip(AnnoClip), - EndClip(AnnoClip), + Image(TagFlags, AnnoImage), + BeginClip(TagFlags, AnnoBeginClip), + EndClip(AnnoEndClip), } } } diff --git a/piet-gpu/shader/annotated.h b/piet-gpu/shader/annotated.h index bcadd44..6b18155 100644 --- a/piet-gpu/shader/annotated.h +++ b/piet-gpu/shader/annotated.h @@ -2,7 +2,7 @@ // Code auto-generated by piet-gpu-derive -struct AnnoFillImageRef { +struct AnnoImageRef { uint offset; }; @@ -10,7 +10,11 @@ struct AnnoColorRef { uint offset; }; -struct AnnoClipRef { +struct AnnoBeginClipRef { + uint offset; +}; + +struct AnnoEndClipRef { uint offset; }; @@ -18,22 +22,23 @@ struct AnnotatedRef { uint offset; }; -struct AnnoFillImage { +struct AnnoImage { vec4 bbox; + float linewidth; uint index; ivec2 offset; }; -#define AnnoFillImage_size 24 +#define AnnoImage_size 28 -AnnoFillImageRef AnnoFillImage_index(AnnoFillImageRef ref, uint index) { - return AnnoFillImageRef(ref.offset + index * AnnoFillImage_size); +AnnoImageRef AnnoImage_index(AnnoImageRef ref, uint index) { + return AnnoImageRef(ref.offset + index * AnnoImage_size); } struct AnnoColor { vec4 bbox; - uint rgba_color; float linewidth; + uint rgba_color; }; #define AnnoColor_size 24 @@ -42,22 +47,33 @@ AnnoColorRef AnnoColor_index(AnnoColorRef ref, uint index) { return AnnoColorRef(ref.offset + index * AnnoColor_size); } -struct AnnoClip { +struct AnnoBeginClip { + vec4 bbox; + float linewidth; +}; + +#define AnnoBeginClip_size 20 + +AnnoBeginClipRef AnnoBeginClip_index(AnnoBeginClipRef ref, uint index) { + return AnnoBeginClipRef(ref.offset + index * AnnoBeginClip_size); +} + +struct AnnoEndClip { vec4 bbox; }; -#define AnnoClip_size 16 +#define AnnoEndClip_size 16 -AnnoClipRef AnnoClip_index(AnnoClipRef ref, uint index) { - return AnnoClipRef(ref.offset + index * AnnoClip_size); +AnnoEndClipRef AnnoEndClip_index(AnnoEndClipRef ref, uint index) { + return AnnoEndClipRef(ref.offset + index * AnnoEndClip_size); } #define Annotated_Nop 0 #define Annotated_Color 1 -#define Annotated_FillImage 2 +#define Annotated_Image 2 #define Annotated_BeginClip 3 #define Annotated_EndClip 4 -#define Annotated_size 28 +#define Annotated_size 32 AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) { return AnnotatedRef(ref.offset + index * Annotated_size); @@ -68,7 +84,7 @@ struct AnnotatedTag { uint flags; }; -AnnoFillImage AnnoFillImage_read(Alloc a, AnnoFillImageRef ref) { +AnnoImage AnnoImage_read(Alloc a, AnnoImageRef ref) { uint ix = ref.offset >> 2; uint raw0 = read_mem(a, ix + 0); uint raw1 = read_mem(a, ix + 1); @@ -76,21 +92,24 @@ AnnoFillImage AnnoFillImage_read(Alloc a, AnnoFillImageRef ref) { uint raw3 = read_mem(a, ix + 3); uint raw4 = read_mem(a, ix + 4); uint raw5 = read_mem(a, ix + 5); - AnnoFillImage s; + uint raw6 = read_mem(a, ix + 6); + AnnoImage s; s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); - s.index = raw4; - s.offset = ivec2(int(raw5 << 16) >> 16, int(raw5) >> 16); + s.linewidth = uintBitsToFloat(raw4); + s.index = raw5; + s.offset = ivec2(int(raw6 << 16) >> 16, int(raw6) >> 16); return s; } -void AnnoFillImage_write(Alloc a, AnnoFillImageRef ref, AnnoFillImage s) { +void AnnoImage_write(Alloc a, AnnoImageRef ref, AnnoImage 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.index); - write_mem(a, ix + 5, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16)); + write_mem(a, ix + 4, floatBitsToUint(s.linewidth)); + write_mem(a, ix + 5, s.index); + write_mem(a, ix + 6, (uint(s.offset.x) & 0xffff) | (uint(s.offset.y) << 16)); } AnnoColor AnnoColor_read(Alloc a, AnnoColorRef ref) { @@ -103,8 +122,8 @@ AnnoColor AnnoColor_read(Alloc a, AnnoColorRef ref) { uint raw5 = read_mem(a, ix + 5); AnnoColor s; s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); - s.rgba_color = raw4; - s.linewidth = uintBitsToFloat(raw5); + s.linewidth = uintBitsToFloat(raw4); + s.rgba_color = raw5; return s; } @@ -114,22 +133,44 @@ void AnnoColor_write(Alloc a, AnnoColorRef ref, AnnoColor s) { 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); - write_mem(a, ix + 5, floatBitsToUint(s.linewidth)); + write_mem(a, ix + 4, floatBitsToUint(s.linewidth)); + write_mem(a, ix + 5, s.rgba_color); } -AnnoClip AnnoClip_read(Alloc a, AnnoClipRef ref) { +AnnoBeginClip AnnoBeginClip_read(Alloc a, AnnoBeginClipRef 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); - AnnoClip s; + uint raw4 = read_mem(a, ix + 4); + AnnoBeginClip s; + s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); + s.linewidth = uintBitsToFloat(raw4); + return s; +} + +void AnnoBeginClip_write(Alloc a, AnnoBeginClipRef ref, AnnoBeginClip 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, floatBitsToUint(s.linewidth)); +} + +AnnoEndClip AnnoEndClip_read(Alloc a, AnnoEndClipRef 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); + AnnoEndClip s; s.bbox = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3)); return s; } -void AnnoClip_write(Alloc a, AnnoClipRef ref, AnnoClip s) { +void AnnoEndClip_write(Alloc a, AnnoEndClipRef ref, AnnoEndClip s) { uint ix = ref.offset >> 2; write_mem(a, ix + 0, floatBitsToUint(s.bbox.x)); write_mem(a, ix + 1, floatBitsToUint(s.bbox.y)); @@ -146,16 +187,16 @@ AnnoColor Annotated_Color_read(Alloc a, AnnotatedRef ref) { return AnnoColor_read(a, AnnoColorRef(ref.offset + 4)); } -AnnoFillImage Annotated_FillImage_read(Alloc a, AnnotatedRef ref) { - return AnnoFillImage_read(a, AnnoFillImageRef(ref.offset + 4)); +AnnoImage Annotated_Image_read(Alloc a, AnnotatedRef ref) { + return AnnoImage_read(a, AnnoImageRef(ref.offset + 4)); } -AnnoClip Annotated_BeginClip_read(Alloc a, AnnotatedRef ref) { - return AnnoClip_read(a, AnnoClipRef(ref.offset + 4)); +AnnoBeginClip Annotated_BeginClip_read(Alloc a, AnnotatedRef ref) { + return AnnoBeginClip_read(a, AnnoBeginClipRef(ref.offset + 4)); } -AnnoClip Annotated_EndClip_read(Alloc a, AnnotatedRef ref) { - return AnnoClip_read(a, AnnoClipRef(ref.offset + 4)); +AnnoEndClip Annotated_EndClip_read(Alloc a, AnnotatedRef ref) { + return AnnoEndClip_read(a, AnnoEndClipRef(ref.offset + 4)); } void Annotated_Nop_write(Alloc a, AnnotatedRef ref) { @@ -167,18 +208,18 @@ void Annotated_Color_write(Alloc a, AnnotatedRef ref, uint flags, AnnoColor s) { AnnoColor_write(a, AnnoColorRef(ref.offset + 4), s); } -void Annotated_FillImage_write(Alloc a, AnnotatedRef ref, AnnoFillImage s) { - write_mem(a, ref.offset >> 2, Annotated_FillImage); - AnnoFillImage_write(a, AnnoFillImageRef(ref.offset + 4), s); +void Annotated_Image_write(Alloc a, AnnotatedRef ref, uint flags, AnnoImage s) { + write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_Image); + AnnoImage_write(a, AnnoImageRef(ref.offset + 4), s); } -void Annotated_BeginClip_write(Alloc a, AnnotatedRef ref, AnnoClip s) { - write_mem(a, ref.offset >> 2, Annotated_BeginClip); - AnnoClip_write(a, AnnoClipRef(ref.offset + 4), s); +void Annotated_BeginClip_write(Alloc a, AnnotatedRef ref, uint flags, AnnoBeginClip s) { + write_mem(a, ref.offset >> 2, (flags << 16) | Annotated_BeginClip); + AnnoBeginClip_write(a, AnnoBeginClipRef(ref.offset + 4), s); } -void Annotated_EndClip_write(Alloc a, AnnotatedRef ref, AnnoClip s) { +void Annotated_EndClip_write(Alloc a, AnnotatedRef ref, AnnoEndClip s) { write_mem(a, ref.offset >> 2, Annotated_EndClip); - AnnoClip_write(a, AnnoClipRef(ref.offset + 4), s); + AnnoEndClip_write(a, AnnoEndClipRef(ref.offset + 4), s); } diff --git a/piet-gpu/shader/backdrop.comp b/piet-gpu/shader/backdrop.comp index 3c94017..8461275 100644 --- a/piet-gpu/shader/backdrop.comp +++ b/piet-gpu/shader/backdrop.comp @@ -53,7 +53,7 @@ void main() { break; } // Fall through. - case Annotated_FillImage: + case Annotated_Image: case Annotated_BeginClip: PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size); Path path = Path_read(conf.tile_alloc, path_ref); diff --git a/piet-gpu/shader/backdrop.spv b/piet-gpu/shader/backdrop.spv index 8acb87f..9233dd0 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 acebdc5..a43722d 100644 --- a/piet-gpu/shader/binning.comp +++ b/piet-gpu/shader/binning.comp @@ -61,12 +61,12 @@ void main() { int x0 = 0, y0 = 0, x1 = 0, y1 = 0; switch (tag) { case Annotated_Color: - case Annotated_FillImage: + case Annotated_Image: 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. - AnnoClip clip = Annotated_BeginClip_read(conf.anno_alloc, ref); + AnnoEndClip clip = Annotated_EndClip_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)); diff --git a/piet-gpu/shader/binning.spv b/piet-gpu/shader/binning.spv index 82853e3..46f1e47 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 0e37985..860be2e 100644 --- a/piet-gpu/shader/coarse.comp +++ b/piet-gpu/shader/coarse.comp @@ -208,7 +208,7 @@ void main() { uint tile_count; switch (tag) { case Annotated_Color: - case Annotated_FillImage: + case Annotated_Image: case Annotated_BeginClip: case Annotated_EndClip: // We have one "path" for each element, even if the element isn't @@ -322,37 +322,36 @@ void main() { } 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; + CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop); Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill); } else { Cmd_Solid_write(cmd_alloc, cmd_ref); } } else { - CmdStroke cmd_stroke; - cmd_stroke.tile_ref = tile.tile.offset; - cmd_stroke.half_width = 0.5 * fill.linewidth; + CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * fill.linewidth); Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke); } cmd_ref.offset += Cmd_size; Cmd_Color_write(cmd_alloc, cmd_ref, CmdColor(fill.rgba_color)); cmd_ref.offset += Cmd_size; break; - case Annotated_FillImage: + case Annotated_Image: 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)); - AnnoFillImage fill_img = Annotated_FillImage_read(conf.anno_alloc, ref); + AnnoImage fill_img = Annotated_Image_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_write(cmd_alloc, cmd_ref, cmd_fill); + if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) { + if (tile.tile.offset != 0) { + CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop); + Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill); + } else { + Cmd_Solid_write(cmd_alloc, cmd_ref); + } } else { - Cmd_Solid_write(cmd_alloc, cmd_ref); + CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * fill_img.linewidth); + Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke); } cmd_ref.offset += Cmd_size; Cmd_Image_write(cmd_alloc, cmd_ref, CmdImage(fill_img.index, fill_img.offset)); @@ -366,18 +365,22 @@ void main() { } else if (tile.tile.offset == 0 && clip_depth < 32) { clip_one_mask |= (1 << clip_depth); } else { + AnnoBeginClip begin_clip = Annotated_BeginClip_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_write(cmd_alloc, cmd_ref, cmd_fill); + if (fill_mode_from_flags(tag.flags) == MODE_NONZERO) { + if (tile.tile.offset != 0) { + CmdFill cmd_fill = CmdFill(tile.tile.offset, tile.backdrop); + Cmd_Fill_write(cmd_alloc, cmd_ref, cmd_fill); + } else { + // TODO: here is where a bunch of optimization magic should happen + float alpha = tile.backdrop == 0 ? 0.0 : 1.0; + Cmd_Alpha_write(cmd_alloc, cmd_ref, CmdAlpha(alpha)); + } } else { - // TODO: here is where a bunch of optimization magic should happen - float alpha = tile.backdrop == 0 ? 0.0 : 1.0; - Cmd_Alpha_write(cmd_alloc, cmd_ref, CmdAlpha(alpha)); + CmdStroke cmd_stroke = CmdStroke(tile.tile.offset, 0.5 * begin_clip.linewidth); + Cmd_Stroke_write(cmd_alloc, cmd_ref, cmd_stroke); } cmd_ref.offset += Cmd_size; Cmd_BeginClip_write(cmd_alloc, cmd_ref); diff --git a/piet-gpu/shader/coarse.spv b/piet-gpu/shader/coarse.spv index 9cc6cc6..7e85c00 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 b33ed66..80a456d 100644 --- a/piet-gpu/shader/elements.comp +++ b/piet-gpu/shader/elements.comp @@ -357,25 +357,39 @@ void main() { break; case Element_FillImage: FillImage fill_img = Element_FillImage_read(this_ref); - AnnoFillImage anno_fill_img; - anno_fill_img.index = fill_img.index; - anno_fill_img.offset = fill_img.offset; - anno_fill_img.bbox = st.bbox; + AnnoImage anno_img; + anno_img.index = fill_img.index; + anno_img.offset = fill_img.offset; + if (is_stroke) { + vec2 lw = get_linewidth(st); + anno_img.bbox = st.bbox + vec4(-lw, lw); + anno_img.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z)); + } else { + anno_img.bbox = st.bbox; + anno_img.linewidth = 0.0; + } out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); - Annotated_FillImage_write(conf.anno_alloc, out_ref, anno_fill_img); + Annotated_Image_write(conf.anno_alloc, out_ref, fill_mode, anno_img); break; case Element_BeginClip: Clip begin_clip = Element_BeginClip_read(this_ref); - AnnoClip anno_begin_clip = AnnoClip(begin_clip.bbox); - // This is the absolute bbox, it's been transformed during encoding. - anno_begin_clip.bbox = begin_clip.bbox; + AnnoBeginClip anno_begin_clip; + if (is_stroke) { + vec2 lw = get_linewidth(st); + // This is the absolute bbox, it's been transformed during encoding. + anno_begin_clip.bbox = begin_clip.bbox + vec4(-lw, lw); + anno_begin_clip.linewidth = st.linewidth * sqrt(abs(st.mat.x * st.mat.w - st.mat.y * st.mat.z)); + } else { + anno_begin_clip.bbox = begin_clip.bbox; + anno_fill.linewidth = 0.0; + } out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); - Annotated_BeginClip_write(conf.anno_alloc, out_ref, anno_begin_clip); + Annotated_BeginClip_write(conf.anno_alloc, out_ref, fill_mode, anno_begin_clip); break; case Element_EndClip: Clip end_clip = Element_EndClip_read(this_ref); // This bbox is expected to be the same as the begin one. - AnnoClip anno_end_clip = AnnoClip(end_clip.bbox); + AnnoEndClip anno_end_clip = AnnoEndClip(end_clip.bbox); out_ref = AnnotatedRef(conf.anno_alloc.offset + (st.path_count - 1) * Annotated_size); Annotated_EndClip_write(conf.anno_alloc, out_ref, anno_end_clip); break; diff --git a/piet-gpu/shader/elements.spv b/piet-gpu/shader/elements.spv index a49255b..c7bade5 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 21039c5..3a6e4ee 100644 --- a/piet-gpu/shader/tile_alloc.comp +++ b/piet-gpu/shader/tile_alloc.comp @@ -44,12 +44,12 @@ void main() { int x0 = 0, y0 = 0, x1 = 0, y1 = 0; switch (tag) { case Annotated_Color: - case Annotated_FillImage: + case Annotated_Image: case Annotated_BeginClip: case Annotated_EndClip: // Note: we take advantage of the fact that fills, strokes, and // clips have compatible layout. - AnnoClip clip = Annotated_BeginClip_read(conf.anno_alloc, ref); + AnnoEndClip clip = Annotated_EndClip_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)); diff --git a/piet-gpu/shader/tile_alloc.spv b/piet-gpu/shader/tile_alloc.spv index fc2e448..6d375bd 100644 Binary files a/piet-gpu/shader/tile_alloc.spv and b/piet-gpu/shader/tile_alloc.spv differ diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 21860e0..ac83c7e 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -232,7 +232,7 @@ impl Renderer { const PATH_SIZE: usize = 12; const BIN_SIZE: usize = 8; const PATHSEG_SIZE: usize = 52; - const ANNO_SIZE: usize = 28; + const ANNO_SIZE: usize = 32; const TRANS_SIZE: usize = 24; let mut alloc = 0; let tile_base = alloc;