diff --git a/core/src/render/primitive.rs b/core/src/render/primitive.rs index 052f5bd..8183593 100644 --- a/core/src/render/primitive.rs +++ b/core/src/render/primitive.rs @@ -89,6 +89,8 @@ macro_rules! primitives { } $( + // Each is uploaded as its WGSL counterpart, so its fields have to + // sit at WGSL's offsets -- including an align Rust would not pick. unsafe impl bytemuck::Pod for $ty {} unsafe impl bytemuck::Zeroable for $ty {} impl Primitive for $ty { @@ -263,7 +265,10 @@ impl RectPrimitive { /// `color` is multiplied by the atlas alpha for a mask glyph; a colour glyph /// takes the texel unchanged, which `GlyphEntry::IS_COLORED` selects. -#[repr(C)] +/// +/// `align(8)` because `vec2` aligns `GlyphInfo` to 8, which pads it to +/// 32 bytes. +#[repr(C, align(8))] #[derive(Debug, Copy, Clone)] pub struct GlyphPrimitive { pub uv_min: Vec2, diff --git a/core/src/render/shader.wgsl b/core/src/render/shader.wgsl index e7fc859..248722a 100644 --- a/core/src/render/shader.wgsl +++ b/core/src/render/shader.wgsl @@ -17,13 +17,9 @@ struct Rect { inner_radius: f32, } -// Scalars rather than two vec2: a vec2 member would align the struct to -// 8 and pad it to 32 bytes, which GlyphPrimitive has no field to fill. struct GlyphInfo { - uv_min_x: f32, - uv_min_y: f32, - uv_max_x: f32, - uv_max_y: f32, + uv_min: vec2, + uv_max: vec2, layer: u32, color: u32, flags: u32, @@ -162,9 +158,7 @@ fn draw_texture(region: Region) -> vec4 { } fn draw_glyph(region: Region, g: GlyphInfo) -> vec4 { - let uv_min = vec2(g.uv_min_x, g.uv_min_y); - let uv_max = vec2(g.uv_max_x, g.uv_max_y); - let uv = mix(uv_min, uv_max, region.uv); + let uv = mix(g.uv_min, g.uv_max, region.uv); let texel = textureSample(tex, samp, uv, i32(g.layer)); if (g.flags & 1u) != 0u { return texel;