GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
test: pin the shared glyph-shader vertex layout at compile time
ImageVertex and GlyphVertex feed the same shader (locations 0..=4) and each
pipeline hardcodes one offset per location, but nothing tied the structs to
those numbers — which is how ImageVertex lost clip_extents and left location 4
undescribed. Assert size and every field offset in both files, so adding,
reordering, or resizing a field fails the build instead of silently feeding
mis-aligned attributes.
Verified by injecting a uv/color reorder: size stays 52 so a size-only check
would pass, but the build fails with
"assertion failed: offset_of!(ImageVertex, uv) == 8".
Co-Authored-By: Claude Fable 5 <[email protected]>
src/vk/image.rs | 13 +++++++++++++
src/vk/text.rs | 11 +++++++++++
2 files changed, 24 insertions(+)
diff --git a/src/vk/image.rs b/src/vk/image.rs
index 08ab1b5..c970497 100644
--- a/src/vk/image.rs
+++ b/src/vk/image.rs
@@ -71,6 +71,19 @@ struct ImageVertex {
clip_extents: [f32; 2],
}
+// The pipeline below hardcodes one offset per shader location. Pin the struct to
+// them so adding, reordering, or resizing a field fails the build instead of
+// silently feeding the shader mis-aligned attributes — the drift that left
+// location 4 undescribed. `text.rs` pins `GlyphVertex` to the same layout.
+const _: () = {
+ assert!(std::mem::size_of::<ImageVertex>() == 52);
+ assert!(std::mem::offset_of!(ImageVertex, position) == 0);
+ assert!(std::mem::offset_of!(ImageVertex, uv) == 8);
+ assert!(std::mem::offset_of!(ImageVertex, color) == 16);
+ assert!(std::mem::offset_of!(ImageVertex, clip_circle) == 32);
+ assert!(std::mem::offset_of!(ImageVertex, clip_extents) == 44);
+};
+
struct GpuImage {
image: vk::Image,
view: vk::ImageView,
diff --git a/src/vk/text.rs b/src/vk/text.rs
index 9dbec40..24af1ca 100644
--- a/src/vk/text.rs
+++ b/src/vk/text.rs
@@ -65,6 +65,17 @@ struct GlyphVertex {
clip_extents: [f32; 2],
}
+// See the matching block in `image.rs`: both pipelines feed the same glyph
+// shader (locations 0..=4), so both vertex structs must hold this exact layout.
+const _: () = {
+ assert!(std::mem::size_of::<GlyphVertex>() == 52);
+ assert!(std::mem::offset_of!(GlyphVertex, position) == 0);
+ assert!(std::mem::offset_of!(GlyphVertex, uv) == 8);
+ assert!(std::mem::offset_of!(GlyphVertex, color) == 16);
+ assert!(std::mem::offset_of!(GlyphVertex, clip_circle) == 32);
+ assert!(std::mem::offset_of!(GlyphVertex, clip_extents) == 44);
+};
+
#[derive(Clone, Copy)]
struct GlyphEntry {
/// Atlas texel rect.