diff --git a/piet-gpu-types/src/scene.rs b/piet-gpu-types/src/scene.rs index d2cc466..8e4ec3c 100644 --- a/piet-gpu-types/src/scene.rs +++ b/piet-gpu-types/src/scene.rs @@ -1,7 +1,7 @@ use piet_gpu_derive::piet_gpu; pub use self::scene::{ - Bbox, PietFill, PietItem, PietStrokeLine, PietStrokePolyLine, Point, SimpleGroup, + Bbox, PietCircle, PietFill, PietItem, PietStrokeLine, PietStrokePolyLine, Point, SimpleGroup, }; piet_gpu! { @@ -20,6 +20,11 @@ piet_gpu! { items: Ref, bboxes: Ref, } + struct PietCircle { + rgba_color: u32, + center: Point, + radius: f32, + } struct PietStrokeLine { flags: u32, rgba_color: u32, @@ -40,7 +45,7 @@ piet_gpu! { points: Ref, } enum PietItem { - Circle(), + Circle(PietCircle), Line(PietStrokeLine), Fill(PietFill), Poly(PietStrokePolyLine), diff --git a/piet-gpu/shader/build.ninja b/piet-gpu/shader/build.ninja index d0086bc..037540b 100644 --- a/piet-gpu/shader/build.ninja +++ b/piet-gpu/shader/build.ninja @@ -7,4 +7,4 @@ glslang_validator = glslangValidator rule glsl command = $glslang_validator -V -o $out $in -build image.spv: glsl image.comp +build image.spv: glsl image.comp | scene.h diff --git a/piet-gpu/shader/image.comp b/piet-gpu/shader/image.comp index 5487366..6174724 100644 --- a/piet-gpu/shader/image.comp +++ b/piet-gpu/shader/image.comp @@ -26,6 +26,24 @@ void main() { uvec2 xy = gl_GlobalInvocationID.xy; vec2 uv = vec2(xy) * vec2(1.0 / IMAGE_WIDTH, 1.0 / IMAGE_HEIGHT); vec4 rgba = vec4(uv.xyy, 1.0); + + // Render the scene. Right now, every pixel traverses the scene graph, + // which is horribly wasteful, but the goal is to get *some* output and + // then optimize. + + SimpleGroup group = SimpleGroup_read(SimpleGroupRef(0)); + for (uint i = 0; i < group.n_items; i++) { + // Writing this out by hand is illuminating the need for array access + // in piet-gpu-derive. There is some support in the `_index` functions, + // but those are only generated for structs, not for `Ref` or other + // types. + PietItemRef item_ref = PietItemRef(scene[(group.items.offset >> 2) + i]); + uint tag = PietItem_tag(item_ref); + if (tag == PietItem_Circle) { + PietCircle = PietItem_Circle_read(item_ref); + } + } + uvec4 s = uvec4(round(rgba * 255.0)); uint rgba_packed = s.x | (s.y << 8) | (s.z << 16) | (s.w << 24); image[xy.y * IMAGE_WIDTH + xy.x] = rgba_packed; diff --git a/piet-gpu/shader/image.spv b/piet-gpu/shader/image.spv index e05c8c0..5be9f6d 100644 Binary files a/piet-gpu/shader/image.spv and b/piet-gpu/shader/image.spv differ diff --git a/piet-gpu/shader/scene.h b/piet-gpu/shader/scene.h index eb99bd4..440f491 100644 --- a/piet-gpu/shader/scene.h +++ b/piet-gpu/shader/scene.h @@ -12,6 +12,10 @@ struct SimpleGroupRef { uint offset; }; +struct PietCircleRef { + uint offset; +}; + struct PietStrokeLineRef { uint offset; }; @@ -60,6 +64,18 @@ SimpleGroupRef SimpleGroup_index(SimpleGroupRef ref, uint index) { return SimpleGroupRef(ref.offset + index * SimpleGroup_size); } +struct PietCircle { + uint rgba_color; + Point center; + float radius; +}; + +#define PietCircle_size 16 + +PietCircleRef PietCircle_index(PietCircleRef ref, uint index) { + return PietCircleRef(ref.offset + index * PietCircle_size); +} + struct PietStrokeLine { uint flags; uint rgba_color; @@ -140,6 +156,17 @@ SimpleGroup SimpleGroup_read(SimpleGroupRef ref) { return s; } +PietCircle PietCircle_read(PietCircleRef ref) { + uint ix = ref.offset >> 2; + uint raw0 = scene[ix + 0]; + uint raw3 = scene[ix + 3]; + PietCircle s; + s.rgba_color = raw0; + s.center = Point_read(PointRef(ref.offset + 4)); + s.radius = uintBitsToFloat(raw3); + return s; +} + PietStrokeLine PietStrokeLine_read(PietStrokeLineRef ref) { uint ix = ref.offset >> 2; uint raw0 = scene[ix + 0]; @@ -186,6 +213,10 @@ uint PietItem_tag(PietItemRef ref) { return scene[ref.offset >> 2]; } +PietCircle PietItem_Circle_read(PietItemRef ref) { + return PietCircle_read(PietCircleRef(ref.offset + 4)); +} + PietStrokeLine PietItem_Line_read(PietItemRef ref) { return PietStrokeLine_read(PietStrokeLineRef(ref.offset + 4)); }