From ed4ed307089c3d77b6b2468343a1c612cd2c01f9 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Wed, 20 May 2020 11:48:05 -0700 Subject: [PATCH] Adding backdrop logic Calculation of backdrops kinda works but with issues, so WIP. --- piet-gpu/shader/binning.comp | 11 +++++- piet-gpu/shader/binning.spv | Bin 22016 -> 22592 bytes piet-gpu/shader/coarse.comp | 64 ++++++++++++++++++++++++++++++----- piet-gpu/shader/coarse.spv | Bin 33272 -> 38016 bytes piet-gpu/src/lib.rs | 2 +- 5 files changed, 67 insertions(+), 10 deletions(-) diff --git a/piet-gpu/shader/binning.comp b/piet-gpu/shader/binning.comp index 60b12e0..138621e 100644 --- a/piet-gpu/shader/binning.comp +++ b/piet-gpu/shader/binning.comp @@ -35,6 +35,8 @@ layout(set = 0, binding = 3) buffer BinsBuf { #define SX (1.0 / float(N_TILE_X * TILE_WIDTH_PX)) #define SY (1.0 / float(N_TILE_Y * TILE_HEIGHT_PX)) +#define TSY (1.0 / float(TILE_HEIGHT_PX)) + // Constant not available in GLSL. Also consider uintBitsToFloat(0x7f800000) #define INFINITY (1.0 / 0.0) @@ -83,6 +85,7 @@ void main() { } int x0 = 0, y0 = 0, x1 = 0, y1 = 0; float my_right_edge = INFINITY; + bool crosses_edge = false; switch (tag) { case Annotated_FillLine: case Annotated_StrokeLine: @@ -91,6 +94,7 @@ void main() { y0 = int(floor((min(line.p0.y, line.p1.y) - line.stroke.y) * SY)); x1 = int(ceil((max(line.p0.x, line.p1.x) + line.stroke.x) * SX)); y1 = int(ceil((max(line.p0.y, line.p1.y) + line.stroke.y) * SY)); + crosses_edge = tag == Annotated_FillLine && ceil(line.p0.y * TSY) != ceil(line.p1.y * TSY); break; case Annotated_Fill: case Annotated_Stroke: @@ -101,7 +105,9 @@ void main() { y0 = int(floor(fill.bbox.y * SY)); x1 = int(ceil(fill.bbox.z * SX)); y1 = int(ceil(fill.bbox.w * SY)); - my_right_edge = x1; + // It probably makes more sense to track x1, to avoid having to redo + // the rounding to tile coords. + my_right_edge = fill.bbox.z; break; } @@ -131,6 +137,9 @@ void main() { } barrier(); } + if (crosses_edge) { + x1 = int(ceil(my_right_edge * SX)); + } // At this point, we run an iterator over the coverage area, // trying to keep divergence low. diff --git a/piet-gpu/shader/binning.spv b/piet-gpu/shader/binning.spv index 4fda673c4aea604390b10ba4ceb6b93a76378ee0..dc1713b5505929835d055744fc3124cd12d0d6e1 100644 GIT binary patch literal 22592 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 literal 22016 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 T3`LvYEyiC0R`>oAdw=~e9^Xm4 diff --git a/piet-gpu/shader/coarse.comp b/piet-gpu/shader/coarse.comp index 57abd73..2389e27 100644 --- a/piet-gpu/shader/coarse.comp +++ b/piet-gpu/shader/coarse.comp @@ -43,6 +43,7 @@ shared uint sh_elements_ref; shared uint sh_bitmaps[N_SLICE][N_TILE]; shared uint sh_backdrop[N_SLICE][N_TILE]; +shared uint sh_bd_sign[N_SLICE]; // scale factors useful for converting coordinates to tiles #define SX (1.0 / float(TILE_WIDTH_PX)) @@ -111,7 +112,10 @@ void main() { sh_first_el[th_ix] = chunk.n > 0 ? BinInstance_read(BinInstanceRef(start_chunk + BinChunk_size)).element_ix : ~0; } - uint count = 0; + if (th_ix < N_SLICE) { + sh_bd_sign[th_ix] = 0; + } + int backdrop = 0; while (true) { for (uint i = 0; i < N_SLICE; i++) { sh_bitmaps[i][th_ix] = 0; @@ -174,8 +178,11 @@ void main() { // Read one element, compute coverage. uint tag = Annotated_Nop; AnnotatedRef ref; + float right_edge = 0.0; if (th_ix + rd_ix < wr_ix) { - uint element_ix = sh_elements[(rd_ix + th_ix) % N_RINGBUF]; + uint rd_el_ix = (rd_ix + th_ix) % N_RINGBUF; + uint element_ix = sh_elements[rd_el_ix]; + right_edge = sh_right_edge[rd_el_ix]; ref = AnnotatedRef(element_ix * Annotated_size); tag = Annotated_tag(ref); } @@ -184,6 +191,8 @@ void main() { float a, b, c; // Bounding box of element in pixel coordinates. float xmin, xmax, ymin, ymax; + uint my_slice = th_ix / 32; + uint my_mask = 1 << (th_ix & 31); switch (tag) { case Annotated_FillLine: case Annotated_StrokeLine: @@ -194,6 +203,14 @@ void main() { ymax = max(line.p0.y, line.p1.y) + line.stroke.y; float dx = line.p1.x - line.p0.x; float dy = line.p1.y - line.p0.y; + if (tag == Annotated_FillLine) { + // Set bit for backdrop sign calculation, 1 is +1, 0 is -1. + if (dy < 0) { + atomicOr(sh_bd_sign[my_slice], my_mask); + } else { + atomicAnd(sh_bd_sign[my_slice], ~my_mask); + } + } // Set up for per-scanline coverage formula, below. float invslope = abs(dy) < 1e-9 ? 1e9 : dx / dy; c = abs(invslope) * (0.5 * float(TILE_HEIGHT_PX) + line.stroke.y) * SX; @@ -226,14 +243,14 @@ void main() { // Compute bounding box in tiles and clip to this bin. int x0 = int(floor((xmin - xy0.x) * SX)); int x1 = int(ceil((xmax - xy0.x) * SX)); + int xr = int(ceil((right_edge - xy0.x) * SX)); int y0 = int(floor((ymin - xy0.y) * SY)); int y1 = int(ceil((ymax - xy0.y) * SY)); x0 = clamp(x0, 0, N_TILE_X); x1 = clamp(x1, x0, N_TILE_X); + xr = clamp(xr, 0, N_TILE_X); y0 = clamp(y0, 0, N_TILE_Y); y1 = clamp(y1, y0, N_TILE_Y); - uint my_slice = th_ix / 32; - uint my_mask = 1 << (th_ix & 31); float t = a + b * float(y0); for (uint y = y0; y < y1; y++) { uint xx0 = clamp(int(floor(t - c)), x0, x1); @@ -241,6 +258,15 @@ void main() { for (uint x = xx0; x < xx1; x++) { atomicOr(sh_bitmaps[my_slice][y * N_TILE_X + x], my_mask); } + if (tag == Annotated_FillLine && ymin <= xy0.y + float(y * TILE_HEIGHT_PX)) { + // Assign backdrop to all tiles to the right of the ray crossing the + // top edge of this tile, up to the right edge of the fill bbox. + float xray = t - 0.5 * b; + xx0 = max(int(ceil(xray)), 0); + for (uint x = xx0; x < xr; x++) { + atomicOr(sh_backdrop[my_slice][y * N_TILE_X + x], my_mask); + } + } t += b; } barrier(); @@ -248,20 +274,34 @@ void main() { // Output elements for this tile, based on bitmaps. uint slice_ix = 0; uint bitmap = sh_bitmaps[0][th_ix]; + uint bd_bitmap = sh_backdrop[0][th_ix]; + uint combined = bitmap | bd_bitmap; while (true) { - if (bitmap == 0) { + if (combined == 0) { slice_ix++; if (slice_ix == N_SLICE) { break; } bitmap = sh_bitmaps[slice_ix][th_ix]; - if (bitmap == 0) { + bd_bitmap = sh_backdrop[slice_ix][th_ix]; + combined = bitmap | bd_bitmap; + if (combined == 0) { continue; } } - uint element_ref_ix = slice_ix * 32 + findLSB(bitmap); + uint element_ref_ix = slice_ix * 32 + findLSB(combined); uint element_ix = sh_elements[(rd_ix + element_ref_ix) % N_RINGBUF]; + // TODO: use bit magic to aggregate this calculation. + if ((bd_bitmap & (1 << (element_ref_ix & 31))) != 0) { + if ((sh_bd_sign[slice_ix] & (1 << (element_ref_ix & 31))) != 0) { + backdrop += 1; + } else { + backdrop -= 1; + } + } + + if ((bitmap & (1 << (element_ref_ix & 31))) != 0) { // At this point, we read the element again from global memory. // If that turns out to be expensive, maybe we can pack it into // shared memory (or perhaps just the tag). @@ -284,12 +324,19 @@ void main() { seg_chunk_ref.offset += SegChunk_size + Segment_size * chunk_n_segs; CmdFill cmd_fill; cmd_fill.seg_ref = first_seg_chunk.offset; + cmd_fill.backdrop = backdrop; cmd_fill.rgba_color = fill.rgba_color; alloc_cmd(cmd_ref, cmd_limit); Cmd_Fill_write(cmd_ref, cmd_fill); cmd_ref.offset += Cmd_size; chunk_n_segs = 0; + } else if (backdrop != 0) { + AnnoFill fill = Annotated_Fill_read(ref); + alloc_cmd(cmd_ref, cmd_limit); + Cmd_Solid_write(cmd_ref, CmdSolid(fill.rgba_color)); + cmd_ref.offset += Cmd_size; } + backdrop = 0; break; case Annotated_Stroke: if (chunk_n_segs > 0) { @@ -307,9 +354,10 @@ void main() { } break; } + } // clear LSB - bitmap &= bitmap - 1; + combined &= combined - 1; } barrier(); diff --git a/piet-gpu/shader/coarse.spv b/piet-gpu/shader/coarse.spv index e201c5ee594c6bd6ed8b29c3756015d10c16c85a..bc097e44388cf90bb53859a8801d1fe1b4f343e3 100644 GIT binary patch literal 38016 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

3dIb`ZoUe;A+OOA9;NDs(rIh_lB!E zuA`U-$Gk6CeIJT3oLe>jhA8u9-MT+6!q4kmiu=PoabAs2qCUUC7t~mv3n{L}PpGqR z4kv#0jcrdTxcBu*HP5*AgWFgBrm7RJb`6?)U?|wjJ)muW%4CZDinHH_fz7krZ^O~l zGiM{fYR*sk?*coH?7@+6{nYJ$G_{xgYa2yTvwv~+U^lpR4~{`o&mKIW_IK{af|IXn zCD%XW8CTeo>v%NvjAsH^&A8bE2ZGfnQjF`^)Z7Ef+uE2XVw(gu4}D!*xxUW3V|1>Q zQ%~(%&hbHL>dEO~u$u2e$@>tvYn<=vQ{d*Oo_15gw$+w)-v^g#^8>hk>aNXU)LyQQ zwnHgu<}J?J{1Du_Hb7TRaWU$XxeYB;|Q^59_wLBGE?mxLc V#%$h?&3%yhv@Z9B`y=Pb{{z)BoU8x< literal 33272 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 diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 70b02f5..65bbe5c 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -46,8 +46,8 @@ pub fn render_scene(rc: &mut impl RenderContext) { let circle = Circle::new(center, radius); rc.fill(circle, &color); } - let mut path = BezPath::new(); /* + let mut path = BezPath::new(); path.move_to((100.0, 1150.0)); path.line_to((200.0, 1200.0)); path.line_to((150.0, 1250.0));