mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 20:51:29 +11:00
Progress on wiring up fills
Write the right_edge to the binning output. More work on encoding the fill/stroke distinction and plumbing that through the pipeline. This is a bit unsatisfying because of the code duplication; having an extra fill/stroke bool might be better, but I want to avoid making the structs bigger (this could be solved by better packing in the struct encoding). Fills are plumbed through to the last stage. Backdrop is WIP.
This commit is contained in:
parent
03da52cff8
commit
076e6d600d
|
@ -3,7 +3,14 @@ use piet_gpu_derive::piet_gpu;
|
||||||
piet_gpu! {
|
piet_gpu! {
|
||||||
#[gpu_write]
|
#[gpu_write]
|
||||||
mod annotated {
|
mod annotated {
|
||||||
struct AnnoLineSeg {
|
struct AnnoFillLineSeg {
|
||||||
|
p0: [f32; 2],
|
||||||
|
p1: [f32; 2],
|
||||||
|
// A note: the layout of this struct is shared with
|
||||||
|
// AnnoStrokeLineSeg. In that case, we actually write
|
||||||
|
// [0.0, 0.0] as the stroke field, to minimize divergence.
|
||||||
|
}
|
||||||
|
struct AnnoStrokeLineSeg {
|
||||||
p0: [f32; 2],
|
p0: [f32; 2],
|
||||||
p1: [f32; 2],
|
p1: [f32; 2],
|
||||||
// halfwidth in both x and y for binning
|
// halfwidth in both x and y for binning
|
||||||
|
@ -35,8 +42,8 @@ piet_gpu! {
|
||||||
}
|
}
|
||||||
enum Annotated {
|
enum Annotated {
|
||||||
Nop,
|
Nop,
|
||||||
// The segments need a flag to indicate fill/stroke
|
FillLine(AnnoFillLineSeg),
|
||||||
Line(AnnoLineSeg),
|
StrokeLine(AnnoStrokeLineSeg),
|
||||||
Quad(AnnoQuadSeg),
|
Quad(AnnoQuadSeg),
|
||||||
Cubic(AnnoCubicSeg),
|
Cubic(AnnoCubicSeg),
|
||||||
Stroke(AnnoStroke),
|
Stroke(AnnoStroke),
|
||||||
|
|
|
@ -7,6 +7,9 @@ piet_gpu! {
|
||||||
mod bins {
|
mod bins {
|
||||||
struct BinInstance {
|
struct BinInstance {
|
||||||
element_ix: u32,
|
element_ix: u32,
|
||||||
|
// Right edge of the bounding box of the associated fill
|
||||||
|
// element; used in backdrop computation.
|
||||||
|
right_edge: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BinChunk {
|
struct BinChunk {
|
||||||
|
|
|
@ -85,8 +85,15 @@ piet_gpu! {
|
||||||
}
|
}
|
||||||
enum Element {
|
enum Element {
|
||||||
Nop,
|
Nop,
|
||||||
// The segments need a flag to indicate fill/stroke
|
// Another approach to encoding would be to use a single
|
||||||
Line(LineSeg),
|
// variant but have a bool for fill/stroke. This could be
|
||||||
|
// packed into the tag, so the on-the-wire representation
|
||||||
|
// would be very similar to what's here.
|
||||||
|
StrokeLine(LineSeg),
|
||||||
|
FillLine(LineSeg),
|
||||||
|
|
||||||
|
// Note: we'll need to handle the stroke/fill distinction
|
||||||
|
// for these as well, when we do flattening on the GPU.
|
||||||
Quad(QuadSeg),
|
Quad(QuadSeg),
|
||||||
Cubic(CubicSeg),
|
Cubic(CubicSeg),
|
||||||
Stroke(Stroke),
|
Stroke(Stroke),
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
// Code auto-generated by piet-gpu-derive
|
// Code auto-generated by piet-gpu-derive
|
||||||
|
|
||||||
struct AnnoLineSegRef {
|
struct AnnoFillLineSegRef {
|
||||||
|
uint offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnnoStrokeLineSegRef {
|
||||||
uint offset;
|
uint offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,16 +28,27 @@ struct AnnotatedRef {
|
||||||
uint offset;
|
uint offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnnoLineSeg {
|
struct AnnoFillLineSeg {
|
||||||
|
vec2 p0;
|
||||||
|
vec2 p1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define AnnoFillLineSeg_size 16
|
||||||
|
|
||||||
|
AnnoFillLineSegRef AnnoFillLineSeg_index(AnnoFillLineSegRef ref, uint index) {
|
||||||
|
return AnnoFillLineSegRef(ref.offset + index * AnnoFillLineSeg_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AnnoStrokeLineSeg {
|
||||||
vec2 p0;
|
vec2 p0;
|
||||||
vec2 p1;
|
vec2 p1;
|
||||||
vec2 stroke;
|
vec2 stroke;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AnnoLineSeg_size 24
|
#define AnnoStrokeLineSeg_size 24
|
||||||
|
|
||||||
AnnoLineSegRef AnnoLineSeg_index(AnnoLineSegRef ref, uint index) {
|
AnnoStrokeLineSegRef AnnoStrokeLineSeg_index(AnnoStrokeLineSegRef ref, uint index) {
|
||||||
return AnnoLineSegRef(ref.offset + index * AnnoLineSeg_size);
|
return AnnoStrokeLineSegRef(ref.offset + index * AnnoStrokeLineSeg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnnoQuadSeg {
|
struct AnnoQuadSeg {
|
||||||
|
@ -87,18 +102,39 @@ AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Annotated_Nop 0
|
#define Annotated_Nop 0
|
||||||
#define Annotated_Line 1
|
#define Annotated_FillLine 1
|
||||||
#define Annotated_Quad 2
|
#define Annotated_StrokeLine 2
|
||||||
#define Annotated_Cubic 3
|
#define Annotated_Quad 3
|
||||||
#define Annotated_Stroke 4
|
#define Annotated_Cubic 4
|
||||||
#define Annotated_Fill 5
|
#define Annotated_Stroke 5
|
||||||
|
#define Annotated_Fill 6
|
||||||
#define Annotated_size 44
|
#define Annotated_size 44
|
||||||
|
|
||||||
AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) {
|
AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) {
|
||||||
return AnnotatedRef(ref.offset + index * Annotated_size);
|
return AnnotatedRef(ref.offset + index * Annotated_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) {
|
AnnoFillLineSeg AnnoFillLineSeg_read(AnnoFillLineSegRef ref) {
|
||||||
|
uint ix = ref.offset >> 2;
|
||||||
|
uint raw0 = annotated[ix + 0];
|
||||||
|
uint raw1 = annotated[ix + 1];
|
||||||
|
uint raw2 = annotated[ix + 2];
|
||||||
|
uint raw3 = annotated[ix + 3];
|
||||||
|
AnnoFillLineSeg s;
|
||||||
|
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
|
||||||
|
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnnoFillLineSeg_write(AnnoFillLineSegRef ref, AnnoFillLineSeg s) {
|
||||||
|
uint ix = ref.offset >> 2;
|
||||||
|
annotated[ix + 0] = floatBitsToUint(s.p0.x);
|
||||||
|
annotated[ix + 1] = floatBitsToUint(s.p0.y);
|
||||||
|
annotated[ix + 2] = floatBitsToUint(s.p1.x);
|
||||||
|
annotated[ix + 3] = floatBitsToUint(s.p1.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnoStrokeLineSeg AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef ref) {
|
||||||
uint ix = ref.offset >> 2;
|
uint ix = ref.offset >> 2;
|
||||||
uint raw0 = annotated[ix + 0];
|
uint raw0 = annotated[ix + 0];
|
||||||
uint raw1 = annotated[ix + 1];
|
uint raw1 = annotated[ix + 1];
|
||||||
|
@ -106,14 +142,14 @@ AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) {
|
||||||
uint raw3 = annotated[ix + 3];
|
uint raw3 = annotated[ix + 3];
|
||||||
uint raw4 = annotated[ix + 4];
|
uint raw4 = annotated[ix + 4];
|
||||||
uint raw5 = annotated[ix + 5];
|
uint raw5 = annotated[ix + 5];
|
||||||
AnnoLineSeg s;
|
AnnoStrokeLineSeg s;
|
||||||
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
|
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
|
||||||
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
|
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
|
||||||
s.stroke = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
|
s.stroke = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnnoLineSeg_write(AnnoLineSegRef ref, AnnoLineSeg s) {
|
void AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef ref, AnnoStrokeLineSeg s) {
|
||||||
uint ix = ref.offset >> 2;
|
uint ix = ref.offset >> 2;
|
||||||
annotated[ix + 0] = floatBitsToUint(s.p0.x);
|
annotated[ix + 0] = floatBitsToUint(s.p0.x);
|
||||||
annotated[ix + 1] = floatBitsToUint(s.p0.y);
|
annotated[ix + 1] = floatBitsToUint(s.p0.y);
|
||||||
|
@ -239,8 +275,12 @@ uint Annotated_tag(AnnotatedRef ref) {
|
||||||
return annotated[ref.offset >> 2];
|
return annotated[ref.offset >> 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnoLineSeg Annotated_Line_read(AnnotatedRef ref) {
|
AnnoFillLineSeg Annotated_FillLine_read(AnnotatedRef ref) {
|
||||||
return AnnoLineSeg_read(AnnoLineSegRef(ref.offset + 4));
|
return AnnoFillLineSeg_read(AnnoFillLineSegRef(ref.offset + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnoStrokeLineSeg Annotated_StrokeLine_read(AnnotatedRef ref) {
|
||||||
|
return AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef(ref.offset + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnoQuadSeg Annotated_Quad_read(AnnotatedRef ref) {
|
AnnoQuadSeg Annotated_Quad_read(AnnotatedRef ref) {
|
||||||
|
@ -263,9 +303,14 @@ void Annotated_Nop_write(AnnotatedRef ref) {
|
||||||
annotated[ref.offset >> 2] = Annotated_Nop;
|
annotated[ref.offset >> 2] = Annotated_Nop;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Annotated_Line_write(AnnotatedRef ref, AnnoLineSeg s) {
|
void Annotated_FillLine_write(AnnotatedRef ref, AnnoFillLineSeg s) {
|
||||||
annotated[ref.offset >> 2] = Annotated_Line;
|
annotated[ref.offset >> 2] = Annotated_FillLine;
|
||||||
AnnoLineSeg_write(AnnoLineSegRef(ref.offset + 4), s);
|
AnnoFillLineSeg_write(AnnoFillLineSegRef(ref.offset + 4), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Annotated_StrokeLine_write(AnnotatedRef ref, AnnoStrokeLineSeg s) {
|
||||||
|
annotated[ref.offset >> 2] = Annotated_StrokeLine;
|
||||||
|
AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(ref.offset + 4), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Annotated_Quad_write(AnnotatedRef ref, AnnoQuadSeg s) {
|
void Annotated_Quad_write(AnnotatedRef ref, AnnoQuadSeg s) {
|
||||||
|
|
|
@ -84,8 +84,9 @@ void main() {
|
||||||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
||||||
float my_right_edge = INFINITY;
|
float my_right_edge = INFINITY;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Annotated_Line:
|
case Annotated_FillLine:
|
||||||
AnnoLineSeg line = Annotated_Line_read(ref);
|
case Annotated_StrokeLine:
|
||||||
|
AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref);
|
||||||
x0 = int(floor((min(line.p0.x, line.p1.x) - line.stroke.x) * SX));
|
x0 = int(floor((min(line.p0.x, line.p1.x) - line.stroke.x) * SX));
|
||||||
y0 = int(floor((min(line.p0.y, line.p1.y) - line.stroke.y) * SY));
|
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));
|
x1 = int(ceil((max(line.p0.x, line.p1.x) + line.stroke.x) * SX));
|
||||||
|
@ -107,7 +108,7 @@ void main() {
|
||||||
// If the last element in this partition is a fill edge, then we need to do a
|
// If the last element in this partition is a fill edge, then we need to do a
|
||||||
// look-forward to find the right edge of its corresponding fill. That data is
|
// look-forward to find the right edge of its corresponding fill. That data is
|
||||||
// recorded in aggregates computed in the element processing pass.
|
// recorded in aggregates computed in the element processing pass.
|
||||||
if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_Line) {
|
if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_FillLine) {
|
||||||
uint aggregate_ix = (my_tile + 1) * ELEMENT_BINNING_RATIO;
|
uint aggregate_ix = (my_tile + 1) * ELEMENT_BINNING_RATIO;
|
||||||
// This is sequential but the expectation is that the amount of
|
// This is sequential but the expectation is that the amount of
|
||||||
// look-forward is small (performance may degrade in the case
|
// look-forward is small (performance may degrade in the case
|
||||||
|
@ -165,9 +166,9 @@ void main() {
|
||||||
uint chunk_new_start;
|
uint chunk_new_start;
|
||||||
// Refactor to reduce code duplication?
|
// Refactor to reduce code duplication?
|
||||||
if (chunk_n > 0) {
|
if (chunk_n > 0) {
|
||||||
uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * 4;
|
uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * BinInstance_size;
|
||||||
if (next_chunk + BinChunk_size + min(24, element_count * 4) > wr_limit) {
|
if (next_chunk + BinChunk_size + min(24, element_count * BinInstance_size) > wr_limit) {
|
||||||
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * 4);
|
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * BinInstance_size);
|
||||||
// could try to reduce fragmentation if BIN_ALLOC is only a bit above needed
|
// could try to reduce fragmentation if BIN_ALLOC is only a bit above needed
|
||||||
next_chunk = atomicAdd(alloc, alloc_amount);
|
next_chunk = atomicAdd(alloc, alloc_amount);
|
||||||
wr_limit = next_chunk + alloc_amount;
|
wr_limit = next_chunk + alloc_amount;
|
||||||
|
@ -176,10 +177,10 @@ void main() {
|
||||||
chunk_ref = BinChunkRef(next_chunk);
|
chunk_ref = BinChunkRef(next_chunk);
|
||||||
}
|
}
|
||||||
BinInstanceRef instance_ref = BinInstanceRef(chunk_ref.offset + BinChunk_size);
|
BinInstanceRef instance_ref = BinInstanceRef(chunk_ref.offset + BinChunk_size);
|
||||||
if (instance_ref.offset + element_count * 4 > wr_limit) {
|
if (instance_ref.offset + element_count * BinInstance_size > wr_limit) {
|
||||||
chunk_end = wr_limit;
|
chunk_end = wr_limit;
|
||||||
chunk_n = (wr_limit - instance_ref.offset) / 4;
|
chunk_n = (wr_limit - instance_ref.offset) / BinInstance_size;
|
||||||
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * 4);
|
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * BinInstance_size);
|
||||||
chunk_new_start = atomicAdd(alloc, alloc_amount);
|
chunk_new_start = atomicAdd(alloc, alloc_amount);
|
||||||
wr_limit = chunk_new_start + alloc_amount;
|
wr_limit = chunk_new_start + alloc_amount;
|
||||||
BinChunk_write(chunk_ref, BinChunk(chunk_n, BinChunkRef(chunk_new_start)));
|
BinChunk_write(chunk_ref, BinChunk(chunk_n, BinChunkRef(chunk_new_start)));
|
||||||
|
@ -209,11 +210,11 @@ void main() {
|
||||||
if (my_slice > 0) {
|
if (my_slice > 0) {
|
||||||
idx += count[my_slice - 1][bin_ix];
|
idx += count[my_slice - 1][bin_ix];
|
||||||
}
|
}
|
||||||
uint out_offset = sh_chunk_start[bin_ix] + idx * 4;
|
uint out_offset = sh_chunk_start[bin_ix] + idx * BinInstance_size;
|
||||||
if (out_offset >= sh_chunk_end[bin_ix]) {
|
if (out_offset >= sh_chunk_end[bin_ix]) {
|
||||||
out_offset += sh_chunk_jump[bin_ix];
|
out_offset += sh_chunk_jump[bin_ix];
|
||||||
}
|
}
|
||||||
BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix));
|
BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix, my_right_edge));
|
||||||
}
|
}
|
||||||
x++;
|
x++;
|
||||||
if (x == x1) {
|
if (x == x1) {
|
||||||
|
|
Binary file not shown.
|
@ -10,9 +10,10 @@ struct BinChunkRef {
|
||||||
|
|
||||||
struct BinInstance {
|
struct BinInstance {
|
||||||
uint element_ix;
|
uint element_ix;
|
||||||
|
float right_edge;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BinInstance_size 4
|
#define BinInstance_size 8
|
||||||
|
|
||||||
BinInstanceRef BinInstance_index(BinInstanceRef ref, uint index) {
|
BinInstanceRef BinInstance_index(BinInstanceRef ref, uint index) {
|
||||||
return BinInstanceRef(ref.offset + index * BinInstance_size);
|
return BinInstanceRef(ref.offset + index * BinInstance_size);
|
||||||
|
@ -32,14 +33,17 @@ BinChunkRef BinChunk_index(BinChunkRef ref, uint index) {
|
||||||
BinInstance BinInstance_read(BinInstanceRef ref) {
|
BinInstance BinInstance_read(BinInstanceRef ref) {
|
||||||
uint ix = ref.offset >> 2;
|
uint ix = ref.offset >> 2;
|
||||||
uint raw0 = bins[ix + 0];
|
uint raw0 = bins[ix + 0];
|
||||||
|
uint raw1 = bins[ix + 1];
|
||||||
BinInstance s;
|
BinInstance s;
|
||||||
s.element_ix = raw0;
|
s.element_ix = raw0;
|
||||||
|
s.right_edge = uintBitsToFloat(raw1);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinInstance_write(BinInstanceRef ref, BinInstance s) {
|
void BinInstance_write(BinInstanceRef ref, BinInstance s) {
|
||||||
uint ix = ref.offset >> 2;
|
uint ix = ref.offset >> 2;
|
||||||
bins[ix + 0] = s.element_ix;
|
bins[ix + 0] = s.element_ix;
|
||||||
|
bins[ix + 1] = floatBitsToUint(s.right_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
BinChunk BinChunk_read(BinChunkRef ref) {
|
BinChunk BinChunk_read(BinChunkRef ref) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ layout(set = 0, binding = 3) buffer PtclBuf {
|
||||||
#define N_RINGBUF 512
|
#define N_RINGBUF 512
|
||||||
|
|
||||||
shared uint sh_elements[N_RINGBUF];
|
shared uint sh_elements[N_RINGBUF];
|
||||||
|
shared float sh_right_edge[N_RINGBUF];
|
||||||
shared uint sh_chunk[N_WG];
|
shared uint sh_chunk[N_WG];
|
||||||
shared uint sh_chunk_next[N_WG];
|
shared uint sh_chunk_next[N_WG];
|
||||||
shared uint sh_chunk_n[N_WG];
|
shared uint sh_chunk_n[N_WG];
|
||||||
|
@ -41,6 +42,7 @@ shared uint sh_selected_n;
|
||||||
shared uint sh_elements_ref;
|
shared uint sh_elements_ref;
|
||||||
|
|
||||||
shared uint sh_bitmaps[N_SLICE][N_TILE];
|
shared uint sh_bitmaps[N_SLICE][N_TILE];
|
||||||
|
shared uint sh_backdrop[N_SLICE][N_TILE];
|
||||||
|
|
||||||
// scale factors useful for converting coordinates to tiles
|
// scale factors useful for converting coordinates to tiles
|
||||||
#define SX (1.0 / float(TILE_WIDTH_PX))
|
#define SX (1.0 / float(TILE_WIDTH_PX))
|
||||||
|
@ -113,6 +115,7 @@ void main() {
|
||||||
while (true) {
|
while (true) {
|
||||||
for (uint i = 0; i < N_SLICE; i++) {
|
for (uint i = 0; i < N_SLICE; i++) {
|
||||||
sh_bitmaps[i][th_ix] = 0;
|
sh_bitmaps[i][th_ix] = 0;
|
||||||
|
sh_backdrop[i][th_ix] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (wr_ix - rd_ix <= N_TILE) {
|
while (wr_ix - rd_ix <= N_TILE) {
|
||||||
|
@ -157,8 +160,10 @@ void main() {
|
||||||
}
|
}
|
||||||
BinInstanceRef inst_ref = BinInstanceRef(sh_elements_ref);
|
BinInstanceRef inst_ref = BinInstanceRef(sh_elements_ref);
|
||||||
if (th_ix < chunk_n) {
|
if (th_ix < chunk_n) {
|
||||||
uint el = BinInstance_read(BinInstance_index(inst_ref, th_ix)).element_ix;
|
BinInstance inst = BinInstance_read(BinInstance_index(inst_ref, th_ix));
|
||||||
sh_elements[(wr_ix + th_ix) % N_RINGBUF] = el;
|
uint wr_el_ix = (wr_ix + th_ix) % N_RINGBUF;
|
||||||
|
sh_elements[wr_el_ix] = inst.element_ix;
|
||||||
|
sh_right_edge[wr_el_ix] = inst.right_edge;
|
||||||
}
|
}
|
||||||
wr_ix += chunk_n;
|
wr_ix += chunk_n;
|
||||||
}
|
}
|
||||||
|
@ -180,8 +185,9 @@ void main() {
|
||||||
// Bounding box of element in pixel coordinates.
|
// Bounding box of element in pixel coordinates.
|
||||||
float xmin, xmax, ymin, ymax;
|
float xmin, xmax, ymin, ymax;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Annotated_Line:
|
case Annotated_FillLine:
|
||||||
AnnoLineSeg line = Annotated_Line_read(ref);
|
case Annotated_StrokeLine:
|
||||||
|
AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref);
|
||||||
xmin = min(line.p0.x, line.p1.x) - line.stroke.x;
|
xmin = min(line.p0.x, line.p1.x) - line.stroke.x;
|
||||||
xmax = max(line.p0.x, line.p1.x) + line.stroke.x;
|
xmax = max(line.p0.x, line.p1.x) + line.stroke.x;
|
||||||
ymin = min(line.p0.y, line.p1.y) - line.stroke.y;
|
ymin = min(line.p0.y, line.p1.y) - line.stroke.y;
|
||||||
|
@ -214,7 +220,7 @@ void main() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the coverage area into the bitmaks. This uses an algorithm
|
// Draw the coverage area into the bitmasks. This uses an algorithm
|
||||||
// that computes the coverage of a span for given scanline.
|
// that computes the coverage of a span for given scanline.
|
||||||
|
|
||||||
// Compute bounding box in tiles and clip to this bin.
|
// Compute bounding box in tiles and clip to this bin.
|
||||||
|
@ -263,15 +269,27 @@ void main() {
|
||||||
tag = Annotated_tag(ref);
|
tag = Annotated_tag(ref);
|
||||||
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Annotated_Line:
|
case Annotated_FillLine:
|
||||||
AnnoLineSeg line = Annotated_Line_read(ref);
|
case Annotated_StrokeLine:
|
||||||
|
AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref);
|
||||||
Segment seg = Segment(line.p0, line.p1);
|
Segment seg = Segment(line.p0, line.p1);
|
||||||
alloc_chunk(chunk_n_segs, seg_chunk_ref, first_seg_chunk, seg_limit);
|
alloc_chunk(chunk_n_segs, seg_chunk_ref, first_seg_chunk, seg_limit);
|
||||||
Segment_write(SegmentRef(seg_chunk_ref.offset + SegChunk_size + Segment_size * chunk_n_segs), seg);
|
Segment_write(SegmentRef(seg_chunk_ref.offset + SegChunk_size + Segment_size * chunk_n_segs), seg);
|
||||||
chunk_n_segs++;
|
chunk_n_segs++;
|
||||||
break;
|
break;
|
||||||
case Annotated_Fill:
|
case Annotated_Fill:
|
||||||
chunk_n_segs = 0;
|
if (chunk_n_segs > 0) {
|
||||||
|
AnnoFill fill = Annotated_Fill_read(ref);
|
||||||
|
SegChunk_write(seg_chunk_ref, SegChunk(chunk_n_segs, SegChunkRef(0)));
|
||||||
|
seg_chunk_ref.offset += SegChunk_size + Segment_size * chunk_n_segs;
|
||||||
|
CmdFill cmd_fill;
|
||||||
|
cmd_fill.seg_ref = first_seg_chunk.offset;
|
||||||
|
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;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Annotated_Stroke:
|
case Annotated_Stroke:
|
||||||
if (chunk_n_segs > 0) {
|
if (chunk_n_segs > 0) {
|
||||||
|
|
Binary file not shown.
|
@ -98,8 +98,9 @@ State map_element(ElementRef ref) {
|
||||||
c.linewidth = 1.0; // TODO should be 0.0
|
c.linewidth = 1.0; // TODO should be 0.0
|
||||||
c.flags = 0;
|
c.flags = 0;
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Element_Line:
|
case Element_FillLine:
|
||||||
LineSeg line = Element_Line_read(ref);
|
case Element_StrokeLine:
|
||||||
|
LineSeg line = Element_FillLine_read(ref);
|
||||||
c.bbox.xy = min(line.p0, line.p1);
|
c.bbox.xy = min(line.p0, line.p1);
|
||||||
c.bbox.zw = max(line.p0, line.p1);
|
c.bbox.zw = max(line.p0, line.p1);
|
||||||
break;
|
break;
|
||||||
|
@ -272,13 +273,22 @@ void main() {
|
||||||
AnnotatedRef out_ref = AnnotatedRef((ix + i) * Annotated_size);
|
AnnotatedRef out_ref = AnnotatedRef((ix + i) * Annotated_size);
|
||||||
uint tag = Element_tag(this_ref);
|
uint tag = Element_tag(this_ref);
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Element_Line:
|
case Element_FillLine:
|
||||||
LineSeg line = Element_Line_read(this_ref);
|
case Element_StrokeLine:
|
||||||
AnnoLineSeg anno_line;
|
LineSeg line = Element_StrokeLine_read(this_ref);
|
||||||
|
AnnoStrokeLineSeg anno_line;
|
||||||
anno_line.p0 = st.mat.xz * line.p0.x + st.mat.yw * line.p0.y + st.translate;
|
anno_line.p0 = st.mat.xz * line.p0.x + st.mat.yw * line.p0.y + st.translate;
|
||||||
anno_line.p1 = st.mat.xz * line.p1.x + st.mat.yw * line.p1.y + st.translate;
|
anno_line.p1 = st.mat.xz * line.p1.x + st.mat.yw * line.p1.y + st.translate;
|
||||||
anno_line.stroke = get_linewidth(st);
|
if (tag == Element_StrokeLine) {
|
||||||
Annotated_Line_write(out_ref, anno_line);
|
anno_line.stroke = get_linewidth(st);
|
||||||
|
} else {
|
||||||
|
anno_line.stroke = vec2(0.0);
|
||||||
|
}
|
||||||
|
// We do encoding a bit by hand to minimize divergence. Another approach
|
||||||
|
// would be to have a fill/stroke bool.
|
||||||
|
uint out_tag = tag == Element_FillLine ? Annotated_FillLine : Annotated_StrokeLine;
|
||||||
|
annotated[out_ref.offset >> 2] = out_tag;
|
||||||
|
AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(out_ref.offset + 4), anno_line);
|
||||||
break;
|
break;
|
||||||
case Element_Stroke:
|
case Element_Stroke:
|
||||||
Stroke stroke = Element_Stroke_read(this_ref);
|
Stroke stroke = Element_Stroke_read(this_ref);
|
||||||
|
|
Binary file not shown.
|
@ -238,13 +238,14 @@ TransformRef Transform_index(TransformRef ref, uint index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Element_Nop 0
|
#define Element_Nop 0
|
||||||
#define Element_Line 1
|
#define Element_StrokeLine 1
|
||||||
#define Element_Quad 2
|
#define Element_FillLine 2
|
||||||
#define Element_Cubic 3
|
#define Element_Quad 3
|
||||||
#define Element_Stroke 4
|
#define Element_Cubic 4
|
||||||
#define Element_Fill 5
|
#define Element_Stroke 5
|
||||||
#define Element_SetLineWidth 6
|
#define Element_Fill 6
|
||||||
#define Element_Transform 7
|
#define Element_SetLineWidth 7
|
||||||
|
#define Element_Transform 8
|
||||||
#define Element_size 36
|
#define Element_size 36
|
||||||
|
|
||||||
ElementRef Element_index(ElementRef ref, uint index) {
|
ElementRef Element_index(ElementRef ref, uint index) {
|
||||||
|
@ -446,7 +447,11 @@ uint Element_tag(ElementRef ref) {
|
||||||
return scene[ref.offset >> 2];
|
return scene[ref.offset >> 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
LineSeg Element_Line_read(ElementRef ref) {
|
LineSeg Element_StrokeLine_read(ElementRef ref) {
|
||||||
|
return LineSeg_read(LineSegRef(ref.offset + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
LineSeg Element_FillLine_read(ElementRef ref) {
|
||||||
return LineSeg_read(LineSegRef(ref.offset + 4));
|
return LineSeg_read(LineSegRef(ref.offset + 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ impl PicoSvg {
|
||||||
for item in &self.items {
|
for item in &self.items {
|
||||||
match item {
|
match item {
|
||||||
Item::Fill(fill_item) => {
|
Item::Fill(fill_item) => {
|
||||||
//rc.fill(&fill_item.path, &fill_item.color);
|
rc.fill(&fill_item.path, &fill_item.color);
|
||||||
rc.stroke(&fill_item.path, &fill_item.color, 1.0);
|
//rc.stroke(&fill_item.path, &fill_item.color, 1.0);
|
||||||
}
|
}
|
||||||
Item::Stroke(stroke_item) => {
|
Item::Stroke(stroke_item) => {
|
||||||
rc.stroke(&stroke_item.path, &stroke_item.color, stroke_item.width);
|
rc.stroke(&stroke_item.path, &stroke_item.color, stroke_item.width);
|
||||||
|
|
|
@ -94,7 +94,7 @@ impl RenderContext for PietGpuRenderContext {
|
||||||
}
|
}
|
||||||
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
||||||
let path = shape.to_bez_path(TOLERANCE);
|
let path = shape.to_bez_path(TOLERANCE);
|
||||||
self.encode_path(path);
|
self.encode_path(path, false);
|
||||||
match brush {
|
match brush {
|
||||||
PietGpuBrush::Solid(rgba_color) => {
|
PietGpuBrush::Solid(rgba_color) => {
|
||||||
let stroke = Stroke { rgba_color };
|
let stroke = Stroke { rgba_color };
|
||||||
|
@ -116,7 +116,7 @@ impl RenderContext for PietGpuRenderContext {
|
||||||
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
||||||
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
||||||
let path = shape.to_bez_path(TOLERANCE);
|
let path = shape.to_bez_path(TOLERANCE);
|
||||||
self.encode_path(path);
|
self.encode_path(path, true);
|
||||||
match brush {
|
match brush {
|
||||||
PietGpuBrush::Solid(rgba_color) => {
|
PietGpuBrush::Solid(rgba_color) => {
|
||||||
let fill = Fill { rgba_color };
|
let fill = Fill { rgba_color };
|
||||||
|
@ -198,7 +198,15 @@ impl RenderContext for PietGpuRenderContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PietGpuRenderContext {
|
impl PietGpuRenderContext {
|
||||||
fn encode_path(&mut self, path: impl Iterator<Item = PathEl>) {
|
fn encode_line_seg(&mut self, seg: LineSeg, is_fill: bool) {
|
||||||
|
if is_fill {
|
||||||
|
self.elements.push(Element::FillLine(seg));
|
||||||
|
} else {
|
||||||
|
self.elements.push(Element::StrokeLine(seg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_path(&mut self, path: impl Iterator<Item = PathEl>, is_fill: bool) {
|
||||||
let flatten = true;
|
let flatten = true;
|
||||||
if flatten {
|
if flatten {
|
||||||
let mut start_pt = None;
|
let mut start_pt = None;
|
||||||
|
@ -215,7 +223,7 @@ impl PietGpuRenderContext {
|
||||||
p0: last_pt.unwrap(),
|
p0: last_pt.unwrap(),
|
||||||
p1: scene_pt,
|
p1: scene_pt,
|
||||||
};
|
};
|
||||||
self.elements.push(Element::Line(seg));
|
self.encode_line_seg(seg, is_fill);
|
||||||
last_pt = Some(scene_pt);
|
last_pt = Some(scene_pt);
|
||||||
}
|
}
|
||||||
PathEl::ClosePath => {
|
PathEl::ClosePath => {
|
||||||
|
@ -224,7 +232,7 @@ impl PietGpuRenderContext {
|
||||||
p0: last,
|
p0: last,
|
||||||
p1: start,
|
p1: start,
|
||||||
};
|
};
|
||||||
self.elements.push(Element::Line(seg));
|
self.encode_line_seg(seg, is_fill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -246,7 +254,7 @@ impl PietGpuRenderContext {
|
||||||
p0: last_pt.unwrap(),
|
p0: last_pt.unwrap(),
|
||||||
p1: scene_pt,
|
p1: scene_pt,
|
||||||
};
|
};
|
||||||
self.elements.push(Element::Line(seg));
|
self.encode_line_seg(seg, is_fill);
|
||||||
last_pt = Some(scene_pt);
|
last_pt = Some(scene_pt);
|
||||||
}
|
}
|
||||||
PathEl::QuadTo(p1, p2) => {
|
PathEl::QuadTo(p1, p2) => {
|
||||||
|
@ -279,7 +287,7 @@ impl PietGpuRenderContext {
|
||||||
p0: last,
|
p0: last,
|
||||||
p1: start,
|
p1: start,
|
||||||
};
|
};
|
||||||
self.elements.push(Element::Line(seg));
|
self.encode_line_seg(seg, is_fill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue