diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index bc7f5d79ea..ea2ad7b2b9 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -22,6 +22,20 @@ pub type PathVertex_ScaledPixels = PathVertex; #[expect(missing_docs)] pub type DrawOrder = u32; +/// A boolean stored as a `u32` so that GPU-facing structs contain no +/// compiler-inserted padding bytes, which would be undefined behavior to +/// reinterpret as `&[u8]` when writing instance buffers. Guaranteed to be +/// `0` or `1` by construction; shaders read it as a `u32`/`uint`. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +#[repr(transparent)] +pub struct PaddedBool32(u32); + +impl From for PaddedBool32 { + fn from(value: bool) -> Self { + PaddedBool32(value as u32) + } +} + #[derive(Default)] #[expect(missing_docs)] pub struct Scene { @@ -511,7 +525,7 @@ pub struct Underline { pub content_mask: ContentMask, pub color: Hsla, pub thickness: ScaledPixels, - pub wavy: u32, + pub wavy: PaddedBool32, } impl From for Primitive { @@ -701,7 +715,7 @@ impl From for Primitive { pub struct PolychromeSprite { pub order: DrawOrder, pub pad: u32, - pub grayscale: bool, + pub grayscale: PaddedBool32, pub opacity: f32, pub bounds: Bounds, pub content_mask: ContentMask, diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 62a8011d4e..7059cf863a 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -3812,7 +3812,7 @@ impl Window { content_mask: self.snapped_content_mask(), color: style.color.unwrap_or_default().opacity(element_opacity), thickness, - wavy: if style.wavy { 1 } else { 0 }, + wavy: style.wavy.into(), }); } @@ -3842,7 +3842,7 @@ impl Window { content_mask: self.snapped_content_mask(), thickness: self.snap_stroke(style.thickness), color: style.color.unwrap_or_default().opacity(opacity), - wavy: 0, + wavy: false.into(), }); } @@ -4002,7 +4002,7 @@ impl Window { self.next_frame.scene.insert_primitive(PolychromeSprite { order: 0, pad: 0, - grayscale: false, + grayscale: false.into(), bounds, corner_radii: Default::default(), content_mask, @@ -4117,7 +4117,7 @@ impl Window { self.next_frame.scene.insert_primitive(PolychromeSprite { order: 0, pad: 0, - grayscale, + grayscale: grayscale.into(), bounds, content_mask, corner_radii, diff --git a/crates/gpui_wgpu/src/shaders.wgsl b/crates/gpui_wgpu/src/shaders.wgsl index 933b88e84d..747a34d81e 100644 --- a/crates/gpui_wgpu/src/shaders.wgsl +++ b/crates/gpui_wgpu/src/shaders.wgsl @@ -1191,7 +1191,7 @@ fn fs_underline(input: UnderlineVarying) -> @location(0) vec4 { } let underline = b_underlines[input.underline_id]; - if ((underline.wavy & 0xFFu) == 0u) + if (underline.wavy == 0u) { return blend_color(input.color, input.color.a); } @@ -1305,7 +1305,7 @@ fn fs_poly_sprite(input: PolySpriteVarying) -> @location(0) vec4 { let distance = quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii); var color = sample; - if ((sprite.grayscale & 0xFFu) != 0u) { + if (sprite.grayscale != 0u) { let grayscale = dot(color.rgb, GRAYSCALE_FACTORS); color = vec4(vec3(grayscale), sample.a); } diff --git a/crates/gpui_windows/src/shaders.hlsl b/crates/gpui_windows/src/shaders.hlsl index 89c12489b2..483f039938 100644 --- a/crates/gpui_windows/src/shaders.hlsl +++ b/crates/gpui_windows/src/shaders.hlsl @@ -1249,7 +1249,7 @@ float4 polychrome_sprite_fragment(PolychromeSpriteFragmentInput input): SV_Targe float distance = quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii); float4 color = sample; - if ((sprite.grayscale & 0xFFu) != 0u) { + if (sprite.grayscale != 0u) { float3 grayscale = dot(color.rgb, GRAYSCALE_FACTORS); color = float4(grayscale, sample.a); }