mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 20:31:29 +11:00
Merge pull request #14 from linebender/faster_k4
Output multiple pixels per thread in k4
This commit is contained in:
commit
9c0bdd664d
|
@ -6,10 +6,13 @@
|
|||
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
#extension GL_KHR_shader_subgroup_basic : enable
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16) in;
|
||||
#define CHUNK 8
|
||||
#define CHUNK_DY (16 / CHUNK)
|
||||
layout(local_size_x = 16, local_size_y = 2) in;
|
||||
|
||||
// This should be annotated readonly but infra doesn't support that yet.
|
||||
// Same concern that this should be readonly as in kernel 3.
|
||||
layout(set = 0, binding = 0) buffer PtclBuf {
|
||||
uint[] ptcl;
|
||||
};
|
||||
|
@ -24,11 +27,14 @@ void main() {
|
|||
uint tile_ix = gl_WorkGroupID.y * WIDTH_IN_TILES + gl_WorkGroupID.x;
|
||||
CmdRef cmd_ref = CmdRef(tile_ix * PTCL_INITIAL_ALLOC);
|
||||
|
||||
uvec2 xy_uint = gl_GlobalInvocationID.xy;
|
||||
uvec2 xy_uint = uvec2(gl_GlobalInvocationID.x, gl_LocalInvocationID.y + TILE_HEIGHT_PX * gl_WorkGroupID.y);
|
||||
vec2 xy = vec2(xy_uint);
|
||||
vec2 uv = xy * vec2(1.0 / IMAGE_WIDTH, 1.0 / IMAGE_HEIGHT);
|
||||
//vec3 rgb = uv.xyy;
|
||||
vec3 rgb = vec3(0.75);
|
||||
vec3 rgb[CHUNK];
|
||||
for (uint i = 0; i < CHUNK; i++) {
|
||||
rgb[i] = vec3(0.5);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
uint tag = Cmd_tag(cmd_ref);
|
||||
|
@ -38,15 +44,19 @@ void main() {
|
|||
switch (tag) {
|
||||
case Cmd_Circle:
|
||||
CmdCircle circle = Cmd_Circle_read(cmd_ref);
|
||||
float r = length(xy + vec2(0.5, 0.5) - circle.center.xy);
|
||||
float alpha = clamp(0.5 + circle.radius - r, 0.0, 1.0);
|
||||
vec4 fg_rgba = unpackUnorm4x8(circle.rgba_color).wzyx;
|
||||
// TODO: sRGB
|
||||
rgb = mix(rgb, fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
for (uint i = 0; i < CHUNK; i++) {
|
||||
float dy = float(i * CHUNK_DY);
|
||||
float r = length(vec2(xy.x, xy.y + dy) + vec2(0.5, 0.5) - circle.center.xy);
|
||||
float alpha = clamp(0.5 + circle.radius - r, 0.0, 1.0);
|
||||
// TODO: sRGB
|
||||
rgb[i] = mix(rgb[i], fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_Stroke:
|
||||
CmdStroke stroke = Cmd_Stroke_read(cmd_ref);
|
||||
float df = 1e9;
|
||||
float df[CHUNK];
|
||||
for (uint k = 0; k < CHUNK; k++) df[k] = 1e9;
|
||||
SegChunkRef seg_chunk_ref = stroke.seg_ref;
|
||||
do {
|
||||
SegChunk seg_chunk = SegChunk_read(seg_chunk_ref);
|
||||
|
@ -54,52 +64,65 @@ void main() {
|
|||
for (int i = 0; i < seg_chunk.n; i++) {
|
||||
Segment seg = Segment_read(Segment_index(segs, i));
|
||||
vec2 line_vec = seg.end - seg.start;
|
||||
vec2 dpos = xy + vec2(0.5, 0.5) - seg.start;
|
||||
float t = clamp(dot(line_vec, dpos) / dot(line_vec, line_vec), 0.0, 1.0);
|
||||
df = min(df, length(line_vec * t - dpos));
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
vec2 dpos = xy + vec2(0.5, 0.5) - seg.start;
|
||||
dpos.y += float(k * CHUNK_DY);
|
||||
float t = clamp(dot(line_vec, dpos) / dot(line_vec, line_vec), 0.0, 1.0);
|
||||
df[k] = min(df[k], length(line_vec * t - dpos));
|
||||
}
|
||||
}
|
||||
seg_chunk_ref = seg_chunk.next;
|
||||
} while (seg_chunk_ref.offset != 0);
|
||||
fg_rgba = unpackUnorm4x8(stroke.rgba_color).wzyx;
|
||||
alpha = clamp(stroke.half_width + 0.5 - df, 0.0, 1.0);
|
||||
rgb = mix(rgb, fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
float alpha = clamp(stroke.half_width + 0.5 - df[k], 0.0, 1.0);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_Fill:
|
||||
CmdFill fill = Cmd_Fill_read(cmd_ref);
|
||||
// Probably better to store as float, but conversion is no doubt cheap.
|
||||
float area = float(fill.backdrop);
|
||||
float area[CHUNK];
|
||||
for (uint k = 0; k < CHUNK; k++) area[k] = float(fill.backdrop);
|
||||
SegChunkRef fill_seg_chunk_ref = fill.seg_ref;
|
||||
do {
|
||||
SegChunk seg_chunk = SegChunk_read(fill_seg_chunk_ref);
|
||||
SegmentRef segs = seg_chunk.segs;
|
||||
for (int i = 0; i < seg_chunk.n; i++) {
|
||||
Segment seg = Segment_read(Segment_index(segs, i));
|
||||
vec2 start = seg.start - xy;
|
||||
vec2 end = seg.end - xy;
|
||||
vec2 window = clamp(vec2(start.y, end.y), 0.0, 1.0);
|
||||
if (window.x != window.y) {
|
||||
vec2 t = (window - start.y) / (end.y - start.y);
|
||||
vec2 xs = vec2(mix(start.x, end.x, t.x), mix(start.x, end.x, t.y));
|
||||
float xmin = min(min(xs.x, xs.y), 1.0) - 1e-6;
|
||||
float xmax = max(xs.x, xs.y);
|
||||
float b = min(xmax, 1.0);
|
||||
float c = max(b, 0.0);
|
||||
float d = max(xmin, 0.0);
|
||||
float a = (b + 0.5 * (d * d - c * c) - xmin) / (xmax - xmin);
|
||||
area += a * (window.x - window.y);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
vec2 my_xy = vec2(xy.x, xy.y + float(k * CHUNK_DY));
|
||||
vec2 start = seg.start - my_xy;
|
||||
vec2 end = seg.end - my_xy;
|
||||
vec2 window = clamp(vec2(start.y, end.y), 0.0, 1.0);
|
||||
if (window.x != window.y) {
|
||||
vec2 t = (window - start.y) / (end.y - start.y);
|
||||
vec2 xs = vec2(mix(start.x, end.x, t.x), mix(start.x, end.x, t.y));
|
||||
float xmin = min(min(xs.x, xs.y), 1.0) - 1e-6;
|
||||
float xmax = max(xs.x, xs.y);
|
||||
float b = min(xmax, 1.0);
|
||||
float c = max(b, 0.0);
|
||||
float d = max(xmin, 0.0);
|
||||
float a = (b + 0.5 * (d * d - c * c) - xmin) / (xmax - xmin);
|
||||
area[k] += a * (window.x - window.y);
|
||||
}
|
||||
area[k] += sign(end.x - start.x) * clamp(my_xy.y - seg.y_edge + 1.0, 0.0, 1.0);
|
||||
}
|
||||
area += sign(end.x - start.x) * clamp(xy.y - seg.y_edge + 1.0, 0.0, 1.0);
|
||||
}
|
||||
fill_seg_chunk_ref = seg_chunk.next;
|
||||
} while (fill_seg_chunk_ref.offset != 0);
|
||||
fg_rgba = unpackUnorm4x8(fill.rgba_color).wzyx;
|
||||
alpha = min(abs(area), 1.0);
|
||||
rgb = mix(rgb, fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
float alpha = min(abs(area[k]), 1.0);
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, alpha * fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_Solid:
|
||||
CmdSolid solid = Cmd_Solid_read(cmd_ref);
|
||||
fg_rgba = unpackUnorm4x8(solid.rgba_color).wzyx;
|
||||
rgb = mix(rgb, fg_rgba.rgb, fg_rgba.a);
|
||||
for (uint k = 0; k < CHUNK; k++) {
|
||||
rgb[k] = mix(rgb[k], fg_rgba.rgb, fg_rgba.a);
|
||||
}
|
||||
break;
|
||||
case Cmd_Jump:
|
||||
cmd_ref = CmdRef(Cmd_Jump_read(cmd_ref).new_ref);
|
||||
|
@ -108,5 +131,8 @@ void main() {
|
|||
cmd_ref.offset += Cmd_size;
|
||||
}
|
||||
|
||||
imageStore(image, ivec2(xy_uint), vec4(rgb, 1.0));
|
||||
// TODO: sRGB
|
||||
for (uint i = 0; i < CHUNK; i++) {
|
||||
imageStore(image, ivec2(xy_uint.x, xy_uint.y + CHUNK_DY * i), vec4(rgb[i], 1.0));
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in a new issue