aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/shader/piet/backdrop.comp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/shader/piet/backdrop.comp')
-rw-r--r--vendor/gioui.org/shader/piet/backdrop.comp109
1 files changed, 109 insertions, 0 deletions
diff --git a/vendor/gioui.org/shader/piet/backdrop.comp b/vendor/gioui.org/shader/piet/backdrop.comp
new file mode 100644
index 0000000..12ae5b1
--- /dev/null
+++ b/vendor/gioui.org/shader/piet/backdrop.comp
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense
+
+// Propagation of tile backdrop for filling.
+//
+// Each thread reads one path element and calculates the number of spanned tiles
+// based on the bounding box.
+// In a further compaction step, the workgroup loops over the corresponding tile rows per element in parallel.
+// For each row the per tile backdrop will be read, as calculated in the previous coarse path segment kernel,
+// and propagated from the left to the right (prefix summed).
+//
+// Output state:
+// - Each path element has an array of tiles covering the whole path based on boundig box
+// - Each tile per path element contains the 'backdrop' and a list of subdivided path segments
+
+#version 450
+#extension GL_GOOGLE_include_directive : enable
+
+#include "mem.h"
+#include "setup.h"
+
+#define LG_BACKDROP_WG (7 + LG_WG_FACTOR)
+#define BACKDROP_WG (1 << LG_BACKDROP_WG)
+
+layout(local_size_x = BACKDROP_WG, local_size_y = 1) in;
+
+layout(set = 0, binding = 1) readonly buffer ConfigBuf {
+ Config conf;
+};
+
+#include "annotated.h"
+#include "tile.h"
+
+shared uint sh_row_count[BACKDROP_WG];
+shared Alloc sh_row_alloc[BACKDROP_WG];
+shared uint sh_row_width[BACKDROP_WG];
+
+void main() {
+ uint th_ix = gl_LocalInvocationID.x;
+ uint element_ix = gl_GlobalInvocationID.x;
+ AnnotatedRef ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size);
+
+ // Work assignment: 1 thread : 1 path element
+ uint row_count = 0;
+ bool mem_ok = mem_error == NO_ERROR;
+ if (element_ix < conf.n_elements) {
+ AnnotatedTag tag = Annotated_tag(conf.anno_alloc, ref);
+ switch (tag.tag) {
+ case Annotated_Image:
+ case Annotated_BeginClip:
+ case Annotated_Color:
+ if (fill_mode_from_flags(tag.flags) != MODE_NONZERO) {
+ break;
+ }
+ // Fall through.
+ PathRef path_ref = PathRef(conf.tile_alloc.offset + element_ix * Path_size);
+ Path path = Path_read(conf.tile_alloc, path_ref);
+ sh_row_width[th_ix] = path.bbox.z - path.bbox.x;
+ row_count = path.bbox.w - path.bbox.y;
+ // Paths that don't cross tile top edges don't have backdrops.
+ // Don't apply the optimization to paths that may cross the y = 0
+ // top edge, but clipped to 1 row.
+ if (row_count == 1 && path.bbox.y > 0) {
+ // Note: this can probably be expanded to width = 2 as
+ // long as it doesn't cross the left edge.
+ row_count = 0;
+ }
+ Alloc path_alloc = new_alloc(path.tiles.offset, (path.bbox.z - path.bbox.x) * (path.bbox.w - path.bbox.y) * Tile_size, mem_ok);
+ sh_row_alloc[th_ix] = path_alloc;
+ }
+ }
+
+ sh_row_count[th_ix] = row_count;
+ // Prefix sum of sh_row_count
+ for (uint i = 0; i < LG_BACKDROP_WG; i++) {
+ barrier();
+ if (th_ix >= (1 << i)) {
+ row_count += sh_row_count[th_ix - (1 << i)];
+ }
+ barrier();
+ sh_row_count[th_ix] = row_count;
+ }
+ barrier();
+ // Work assignment: 1 thread : 1 path element row
+ uint total_rows = sh_row_count[BACKDROP_WG - 1];
+ for (uint row = th_ix; row < total_rows; row += BACKDROP_WG) {
+ // Binary search to find element
+ uint el_ix = 0;
+ for (uint i = 0; i < LG_BACKDROP_WG; i++) {
+ uint probe = el_ix + ((BACKDROP_WG / 2) >> i);
+ if (row >= sh_row_count[probe - 1]) {
+ el_ix = probe;
+ }
+ }
+ uint width = sh_row_width[el_ix];
+ if (width > 0 && mem_ok) {
+ // Process one row sequentially
+ // Read backdrop value per tile and prefix sum it
+ Alloc tiles_alloc = sh_row_alloc[el_ix];
+ uint seq_ix = row - (el_ix > 0 ? sh_row_count[el_ix - 1] : 0);
+ uint tile_el_ix = (tiles_alloc.offset >> 2) + 1 + seq_ix * 2 * width;
+ uint sum = read_mem(tiles_alloc, tile_el_ix);
+ for (uint x = 1; x < width; x++) {
+ tile_el_ix += 2;
+ sum += read_mem(tiles_alloc, tile_el_ix);
+ write_mem(tiles_alloc, tile_el_ix, sum);
+ }
+ }
+ }
+}