add support for element flags to shaders

Commit 9afa9b86b6 added Rust support for
encoding flags into elements. This change adds support to shaders by
introducing variant tag structs:

struct VariantTag {
    uint tag;
    uint flags;
}

and returning them from Variant_tag functions.

It also adds a flags argument to write functions for enum variants that
include TagFlags.

No functionality changes.

Updates #70

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur 2021-03-17 10:51:38 +01:00
parent 903ab1fb59
commit a5b6bda941
19 changed files with 98 additions and 22 deletions

View file

@ -29,6 +29,7 @@ pub fn gen_glsl(module: &LayoutModule) -> String {
(size, LayoutTypeDef::Enum(en)) => { (size, LayoutTypeDef::Enum(en)) => {
gen_enum_def(&mut r, name, en); gen_enum_def(&mut r, name, en);
gen_item_def(&mut r, name, size.size); gen_item_def(&mut r, name, size.size);
gen_tag_def(&mut r, name);
} }
} }
} }
@ -92,6 +93,13 @@ fn gen_item_def(r: &mut String, name: &str, size: usize) {
writeln!(r, "}}\n").unwrap(); writeln!(r, "}}\n").unwrap();
} }
fn gen_tag_def(r: &mut String, name: &str) {
writeln!(r, "struct {}Tag {{", name).unwrap();
writeln!(r, " uint tag;").unwrap();
writeln!(r, " uint flags;").unwrap();
writeln!(r, "}};\n").unwrap();
}
fn gen_struct_read( fn gen_struct_read(
r: &mut String, r: &mut String,
bufname: &str, bufname: &str,
@ -143,12 +151,13 @@ fn gen_enum_read(
variants: &[(String, Vec<(usize, LayoutType)>)], variants: &[(String, Vec<(usize, LayoutType)>)],
) { ) {
if is_mem { if is_mem {
writeln!(r, "uint {}_tag(Alloc a, {}Ref ref) {{", name, name).unwrap(); writeln!(r, "{}Tag {}_tag(Alloc a, {}Ref ref) {{", name, name, name).unwrap();
writeln!(r, " return read_mem(a, ref.offset >> 2);").unwrap(); writeln!(r, " uint tag_and_flags = read_mem(a, ref.offset >> 2);").unwrap();
} else { } else {
writeln!(r, "uint {}_tag({}Ref ref) {{", name, name).unwrap(); writeln!(r, "{}Tag {}_tag({}Ref ref) {{", name, name, name).unwrap();
writeln!(r, " return {}[ref.offset >> 2];", bufname).unwrap(); writeln!(r, " uint tag_and_flags = {}[ref.offset >> 2];", bufname).unwrap();
} }
writeln!(r, " return {}Tag(tag_and_flags & 0xffff, tag_and_flags >> 16);", name).unwrap();
writeln!(r, "}}\n").unwrap(); writeln!(r, "}}\n").unwrap();
for (var_name, payload) in variants { for (var_name, payload) in variants {
let payload_ix = if payload.len() == 1 { let payload_ix = if payload.len() == 1 {
@ -555,6 +564,49 @@ fn gen_enum_write(
} }
writeln!(r, "}}\n").unwrap(); writeln!(r, "}}\n").unwrap();
} }
} else if payload.len() == 2 && matches!(payload[0].1.ty, GpuType::Scalar(GpuScalar::TagFlags)) {
if let GpuType::InlineStruct(structname) = &payload[1].1.ty {
if is_mem {
writeln!(
r,
"void {}_{}_write(Alloc a, {}Ref ref, uint flags, {} s) {{",
name, var_name, name, structname
)
.unwrap();
writeln!(
r,
" write_mem(a, ref.offset >> 2, (flags << 16) | {}_{});",
name, var_name
)
.unwrap();
writeln!(
r,
" {}_write(a, {}Ref(ref.offset + {}), s);",
structname, structname, payload[0].0
)
.unwrap();
} else {
writeln!(
r,
"void {}_{}_write({}Ref ref, uint flags, {} s) {{",
name, var_name, name, structname
)
.unwrap();
writeln!(
r,
" {}[ref.offset >> 2] = (flags << 16) | {}_{};",
bufname, name, var_name
)
.unwrap();
writeln!(
r,
" {}_write({}Ref(ref.offset + {}), s);",
structname, structname, payload[0].0
)
.unwrap();
}
writeln!(r, "}}\n").unwrap();
}
} }
// TODO: support for variants that aren't one struct. // TODO: support for variants that aren't one struct.
} }

View file

@ -79,6 +79,11 @@ AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) {
return AnnotatedRef(ref.offset + index * Annotated_size); return AnnotatedRef(ref.offset + index * Annotated_size);
} }
struct AnnotatedTag {
uint tag;
uint flags;
};
AnnoFill AnnoFill_read(Alloc a, AnnoFillRef ref) { AnnoFill AnnoFill_read(Alloc a, AnnoFillRef ref) {
uint ix = ref.offset >> 2; uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0); uint raw0 = read_mem(a, ix + 0);
@ -170,8 +175,9 @@ void AnnoClip_write(Alloc a, AnnoClipRef ref, AnnoClip s) {
write_mem(a, ix + 3, floatBitsToUint(s.bbox.w)); write_mem(a, ix + 3, floatBitsToUint(s.bbox.w));
} }
uint Annotated_tag(Alloc a, AnnotatedRef ref) { AnnotatedTag Annotated_tag(Alloc a, AnnotatedRef ref) {
return read_mem(a, ref.offset >> 2); uint tag_and_flags = read_mem(a, ref.offset >> 2);
return AnnotatedTag(tag_and_flags & 0xffff, tag_and_flags >> 16);
} }
AnnoStroke Annotated_Stroke_read(Alloc a, AnnotatedRef ref) { AnnoStroke Annotated_Stroke_read(Alloc a, AnnotatedRef ref) {

View file

@ -46,7 +46,7 @@ void main() {
// Work assignment: 1 thread : 1 path element // Work assignment: 1 thread : 1 path element
uint row_count = 0; uint row_count = 0;
if (element_ix < conf.n_elements) { if (element_ix < conf.n_elements) {
uint tag = Annotated_tag(conf.anno_alloc, ref); uint tag = Annotated_tag(conf.anno_alloc, ref).tag;
switch (tag) { switch (tag) {
case Annotated_Fill: case Annotated_Fill:
case Annotated_FillImage: case Annotated_FillImage:

Binary file not shown.

View file

@ -56,7 +56,7 @@ void main() {
AnnotatedRef ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size); AnnotatedRef ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size);
uint tag = Annotated_Nop; uint tag = Annotated_Nop;
if (element_ix < my_n_elements) { if (element_ix < my_n_elements) {
tag = Annotated_tag(conf.anno_alloc, ref); tag = Annotated_tag(conf.anno_alloc, ref).tag;
} }
int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
switch (tag) { switch (tag) {

Binary file not shown.

View file

@ -196,7 +196,7 @@ void main() {
if (th_ix + rd_ix < wr_ix) { if (th_ix + rd_ix < wr_ix) {
element_ix = sh_elements[th_ix]; element_ix = sh_elements[th_ix];
ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size); ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size);
tag = Annotated_tag(conf.anno_alloc, ref); tag = Annotated_tag(conf.anno_alloc, ref).tag;
} }
// Bounding box of element in pixel coordinates. // Bounding box of element in pixel coordinates.
@ -256,7 +256,7 @@ void main() {
} }
} }
AnnotatedRef ref = AnnotatedRef(conf.anno_alloc.offset + sh_elements[el_ix] * Annotated_size); AnnotatedRef ref = AnnotatedRef(conf.anno_alloc.offset + sh_elements[el_ix] * Annotated_size);
uint tag = Annotated_tag(conf.anno_alloc, ref); uint tag = Annotated_tag(conf.anno_alloc, ref).tag;
uint seq_ix = ix - (el_ix > 0 ? sh_tile_count[el_ix - 1] : 0); uint seq_ix = ix - (el_ix > 0 ? sh_tile_count[el_ix - 1] : 0);
uint width = sh_tile_width[el_ix]; uint width = sh_tile_width[el_ix];
uint x = sh_tile_x0[el_ix] + seq_ix % width; uint x = sh_tile_x0[el_ix] + seq_ix % width;
@ -305,7 +305,7 @@ void main() {
// If that turns out to be expensive, maybe we can pack it into // If that turns out to be expensive, maybe we can pack it into
// shared memory (or perhaps just the tag). // shared memory (or perhaps just the tag).
ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size); ref = AnnotatedRef(conf.anno_alloc.offset + element_ix * Annotated_size);
tag = Annotated_tag(conf.anno_alloc, ref); tag = Annotated_tag(conf.anno_alloc, ref).tag;
if (clip_zero_depth == 0) { if (clip_zero_depth == 0) {
switch (tag) { switch (tag) {

Binary file not shown.

View file

@ -99,7 +99,7 @@ State combine_state(State a, State b) {
State map_element(ElementRef ref) { State map_element(ElementRef ref) {
// TODO: it would *probably* be more efficient to make the memory read patterns less // TODO: it would *probably* be more efficient to make the memory read patterns less
// divergent, though it would be more wasted memory. // divergent, though it would be more wasted memory.
uint tag = Element_tag(ref); uint tag = Element_tag(ref).tag;
State c; State c;
c.bbox = vec4(0.0, 0.0, 0.0, 0.0); c.bbox = vec4(0.0, 0.0, 0.0, 0.0);
c.mat = vec4(1.0, 0.0, 0.0, 1.0); c.mat = vec4(1.0, 0.0, 0.0, 1.0);
@ -291,7 +291,7 @@ void main() {
// gains to be had from stashing in shared memory or possibly // gains to be had from stashing in shared memory or possibly
// registers (though register pressure is an issue). // registers (though register pressure is an issue).
ElementRef this_ref = Element_index(ref, i); ElementRef this_ref = Element_index(ref, i);
uint tag = Element_tag(this_ref); uint tag = Element_tag(this_ref).tag;
switch (tag) { switch (tag) {
case Element_FillLine: case Element_FillLine:
case Element_StrokeLine: case Element_StrokeLine:

Binary file not shown.

View file

@ -161,7 +161,7 @@ void main() {
} }
while (true) { while (true) {
uint tag = Cmd_tag(cmd_alloc, cmd_ref); uint tag = Cmd_tag(cmd_alloc, cmd_ref).tag;
if (tag == Cmd_End) { if (tag == Cmd_End) {
break; break;
} }

Binary file not shown.

View file

@ -96,7 +96,7 @@ void main() {
uint tag = PathSeg_Nop; uint tag = PathSeg_Nop;
if (element_ix < conf.n_pathseg) { if (element_ix < conf.n_pathseg) {
tag = PathSeg_tag(conf.pathseg_alloc, ref); tag = PathSeg_tag(conf.pathseg_alloc, ref).tag;
} }
switch (tag) { switch (tag) {
case PathSeg_FillCubic: case PathSeg_FillCubic:

Binary file not shown.

View file

@ -54,6 +54,11 @@ PathSegRef PathSeg_index(PathSegRef ref, uint index) {
return PathSegRef(ref.offset + index * PathSeg_size); return PathSegRef(ref.offset + index * PathSeg_size);
} }
struct PathSegTag {
uint tag;
uint flags;
};
PathFillCubic PathFillCubic_read(Alloc a, PathFillCubicRef ref) { PathFillCubic PathFillCubic_read(Alloc a, PathFillCubicRef ref) {
uint ix = ref.offset >> 2; uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0); uint raw0 = read_mem(a, ix + 0);
@ -131,8 +136,9 @@ void PathStrokeCubic_write(Alloc a, PathStrokeCubicRef ref, PathStrokeCubic s) {
write_mem(a, ix + 11, floatBitsToUint(s.stroke.y)); write_mem(a, ix + 11, floatBitsToUint(s.stroke.y));
} }
uint PathSeg_tag(Alloc a, PathSegRef ref) { PathSegTag PathSeg_tag(Alloc a, PathSegRef ref) {
return read_mem(a, ref.offset >> 2); uint tag_and_flags = read_mem(a, ref.offset >> 2);
return PathSegTag(tag_and_flags & 0xffff, tag_and_flags >> 16);
} }
PathFillCubic PathSeg_FillCubic_read(Alloc a, PathSegRef ref) { PathFillCubic PathSeg_FillCubic_read(Alloc a, PathSegRef ref) {

View file

@ -157,6 +157,11 @@ CmdRef Cmd_index(CmdRef ref, uint index) {
return CmdRef(ref.offset + index * Cmd_size); return CmdRef(ref.offset + index * Cmd_size);
} }
struct CmdTag {
uint tag;
uint flags;
};
CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) { CmdStroke CmdStroke_read(Alloc a, CmdStrokeRef ref) {
uint ix = ref.offset >> 2; uint ix = ref.offset >> 2;
uint raw0 = read_mem(a, ix + 0); uint raw0 = read_mem(a, ix + 0);
@ -301,8 +306,9 @@ void CmdJump_write(Alloc a, CmdJumpRef ref, CmdJump s) {
write_mem(a, ix + 0, s.new_ref); write_mem(a, ix + 0, s.new_ref);
} }
uint Cmd_tag(Alloc a, CmdRef ref) { CmdTag Cmd_tag(Alloc a, CmdRef ref) {
return read_mem(a, ref.offset >> 2); uint tag_and_flags = read_mem(a, ref.offset >> 2);
return CmdTag(tag_and_flags & 0xffff, tag_and_flags >> 16);
} }
CmdFill Cmd_Fill_read(Alloc a, CmdRef ref) { CmdFill Cmd_Fill_read(Alloc a, CmdRef ref) {

View file

@ -160,6 +160,11 @@ ElementRef Element_index(ElementRef ref, uint index) {
return ElementRef(ref.offset + index * Element_size); return ElementRef(ref.offset + index * Element_size);
} }
struct ElementTag {
uint tag;
uint flags;
};
LineSeg LineSeg_read(LineSegRef ref) { LineSeg LineSeg_read(LineSegRef ref) {
uint ix = ref.offset >> 2; uint ix = ref.offset >> 2;
uint raw0 = scene[ix + 0]; uint raw0 = scene[ix + 0];
@ -264,8 +269,9 @@ Clip Clip_read(ClipRef ref) {
return s; return s;
} }
uint Element_tag(ElementRef ref) { ElementTag Element_tag(ElementRef ref) {
return scene[ref.offset >> 2]; uint tag_and_flags = scene[ref.offset >> 2];
return ElementTag(tag_and_flags & 0xffff, tag_and_flags >> 16);
} }
LineSeg Element_StrokeLine_read(ElementRef ref) { LineSeg Element_StrokeLine_read(ElementRef ref) {

View file

@ -39,7 +39,7 @@ void main() {
uint tag = Annotated_Nop; uint tag = Annotated_Nop;
if (element_ix < conf.n_elements) { if (element_ix < conf.n_elements) {
tag = Annotated_tag(conf.anno_alloc, ref); tag = Annotated_tag(conf.anno_alloc, ref).tag;
} }
int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
switch (tag) { switch (tag) {

Binary file not shown.