vello/piet-gpu/shader/tile.h
Elias Naur 07e07c7544 ensure consistent path segment transformation
As described in #62, the non-deterministic scene monoid may result in
slightly different transformations for path segments in an otherwise
closed path.

This change ensures consistent transformation across paths in three steps.

First, absolute transformations computed by the scene monoid is stored
along with path segments and annotated elements.

Second, elements.comp no longer transforms path segments. Instead, each
segment is stored untransformed along with a reference to its absolute
transformation.

Finally, path_coarse performs the transformation of path segments.
Because all segments in a path share a single transformation reference,
the inconsistency in #62 is avoided.

Fixes #62

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-03-19 12:45:23 +01:00

151 lines
3.8 KiB
GLSL

// SPDX-License-Identifier: Apache-2.0 OR MIT OR Unlicense
// Code auto-generated by piet-gpu-derive
struct PathRef {
uint offset;
};
struct TileRef {
uint offset;
};
struct TileSegRef {
uint offset;
};
struct TransformSegRef {
uint offset;
};
struct Path {
uvec4 bbox;
TileRef tiles;
};
#define Path_size 12
PathRef Path_index(PathRef ref, uint index) {
return PathRef(ref.offset + index * Path_size);
}
struct Tile {
TileSegRef tile;
int backdrop;
};
#define Tile_size 8
TileRef Tile_index(TileRef ref, uint index) {
return TileRef(ref.offset + index * Tile_size);
}
struct TileSeg {
vec2 origin;
vec2 vector;
float y_edge;
TileSegRef next;
};
#define TileSeg_size 24
TileSegRef TileSeg_index(TileSegRef ref, uint index) {
return TileSegRef(ref.offset + index * TileSeg_size);
}
struct TransformSeg {
vec4 mat;
vec2 translate;
};
#define TransformSeg_size 24
TransformSegRef TransformSeg_index(TransformSegRef ref, uint index) {
return TransformSegRef(ref.offset + index * TransformSeg_size);
}
Path Path_read(Alloc a, PathRef 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);
Path s;
s.bbox = uvec4(raw0 & 0xffff, raw0 >> 16, raw1 & 0xffff, raw1 >> 16);
s.tiles = TileRef(raw2);
return s;
}
void Path_write(Alloc a, PathRef ref, Path s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, s.bbox.x | (s.bbox.y << 16));
write_mem(a, ix + 1, s.bbox.z | (s.bbox.w << 16));
write_mem(a, ix + 2, s.tiles.offset);
}
Tile Tile_read(Alloc a, TileRef ref) {
uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0);
uint raw1 = read_mem(a, ix + 1);
Tile s;
s.tile = TileSegRef(raw0);
s.backdrop = int(raw1);
return s;
}
void Tile_write(Alloc a, TileRef ref, Tile s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, s.tile.offset);
write_mem(a, ix + 1, uint(s.backdrop));
}
TileSeg TileSeg_read(Alloc a, TileSegRef 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);
uint raw4 = read_mem(a, ix + 4);
uint raw5 = read_mem(a, ix + 5);
TileSeg s;
s.origin = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
s.vector = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.y_edge = uintBitsToFloat(raw4);
s.next = TileSegRef(raw5);
return s;
}
void TileSeg_write(Alloc a, TileSegRef ref, TileSeg s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, floatBitsToUint(s.origin.x));
write_mem(a, ix + 1, floatBitsToUint(s.origin.y));
write_mem(a, ix + 2, floatBitsToUint(s.vector.x));
write_mem(a, ix + 3, floatBitsToUint(s.vector.y));
write_mem(a, ix + 4, floatBitsToUint(s.y_edge));
write_mem(a, ix + 5, s.next.offset);
}
TransformSeg TransformSeg_read(Alloc a, TransformSegRef 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);
uint raw4 = read_mem(a, ix + 4);
uint raw5 = read_mem(a, ix + 5);
TransformSeg s;
s.mat = vec4(uintBitsToFloat(raw0), uintBitsToFloat(raw1), uintBitsToFloat(raw2), uintBitsToFloat(raw3));
s.translate = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
return s;
}
void TransformSeg_write(Alloc a, TransformSegRef ref, TransformSeg s) {
uint ix = ref.offset >> 2;
write_mem(a, ix + 0, floatBitsToUint(s.mat.x));
write_mem(a, ix + 1, floatBitsToUint(s.mat.y));
write_mem(a, ix + 2, floatBitsToUint(s.mat.z));
write_mem(a, ix + 3, floatBitsToUint(s.mat.w));
write_mem(a, ix + 4, floatBitsToUint(s.translate.x));
write_mem(a, ix + 5, floatBitsToUint(s.translate.y));
}