From caea233a47870d5477383949057cc9fdc0f7fbca Mon Sep 17 00:00:00 2001 From: Juanperias <136520331+Juanperias@users.noreply.github.com> Date: Wed, 26 Aug 2026 02:09:32 -0400 Subject: [PATCH] Fix wgpu padding (#8448) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Egui web example was throwing an error in WGPU. In this case, the error was ``` panicked at /home/runner/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wgpu-30.0.0/src/backend/wgpu_core.rs:1414:26: wgpu error: Validation Error Caused by: In Device::create_render_pipeline, label = ‘egui_pipeline’ In the provided shader, the type given for group 1 binding 2 has a size of 4. Since the device does not support DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED`, the type must have a size that is a multiple of 16 bytes ``` One reference I used was the following Pull Request: The biggest change I made was in `egui-wgpu` to `r_tex_nearest_filtering` Shader (`egui.wgsl`) ```wgsl // Old @group(1) @binding(2) var r_tex_nearest_filtering: u32; // New @group(1) @binding(2) var r_tex_nearest_filtering: vec4; ``` And with the corresponding changes in `renderer.rs`, I ran it locally and it worked perfectly in Firefox 149 and Chromium 151 (Both fail when attempting to access https://www.egui.rs/#demo, returning the error described above) * Closes * Fixes * [X] I have followed the instructions in the PR template --------- Co-authored-by: Emil Ernerfeldt Co-authored-by: Claude Fable 5 --- crates/egui-wgpu/src/egui.wgsl | 8 +++++--- crates/egui-wgpu/src/renderer.rs | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/egui-wgpu/src/egui.wgsl b/crates/egui-wgpu/src/egui.wgsl index bd3b5313e..9567b0d3e 100644 --- a/crates/egui-wgpu/src/egui.wgsl +++ b/crates/egui-wgpu/src/egui.wgsl @@ -98,6 +98,7 @@ fn vs_main( @group(1) @binding(0) var r_tex_color: texture_2d; @group(1) @binding(1) var r_tex_sampler: sampler; + /// Set in bit 0 of `r_tex_flags` if the sampler uses nearest filtering. /// /// Must match `TEX_FLAG_NEAREST` in `renderer.rs`. @@ -114,11 +115,11 @@ const WRAP_MODE_MIRRORED_REPEAT: u32 = 2u; /// /// Bit 0: `TEX_FLAG_NEAREST`. /// Bits 1+: one of the `WRAP_MODE_*` constants. -@group(1) @binding(2) var r_tex_flags: u32; +@group(1) @binding(2) var r_tex_flags: vec4; /// Map a texel coordinate to a valid texel according to the texture's wrap mode. fn wrap_texel_coord(coord: vec2, texture_size: vec2) -> vec2 { - let wrap_mode = r_tex_flags >> 1u; + let wrap_mode = r_tex_flags[0] >> 1u; if wrap_mode == WRAP_MODE_REPEAT { return ((coord % texture_size) + texture_size) % texture_size; } else if wrap_mode == WRAP_MODE_MIRRORED_REPEAT { @@ -131,6 +132,7 @@ fn wrap_texel_coord(coord: vec2, texture_size: vec2) -> vec2 { } } + fn sample_texture(in: VertexOutput) -> vec4 { if r_locals.predictable_texture_filtering == 0 { // Hardware filtering: fast, but varies across GPUs and drivers. @@ -139,7 +141,7 @@ fn sample_texture(in: VertexOutput) -> vec4 { let texture_size = vec2(textureDimensions(r_tex_color, 0)); let texture_size_f = vec2(texture_size); - if (r_tex_flags & TEX_FLAG_NEAREST) != 0u { + if (r_tex_flags[0] & TEX_FLAG_NEAREST) != 0u { // Nearest filtering: load the texel under the sample position. let texel = wrap_texel_coord(vec2(floor(in.tex_coord * texture_size_f)), texture_size); return textureLoad(r_tex_color, texel, 0); diff --git a/crates/egui-wgpu/src/renderer.rs b/crates/egui-wgpu/src/renderer.rs index cb9f40f18..d5130d5c0 100644 --- a/crates/egui-wgpu/src/renderer.rs +++ b/crates/egui-wgpu/src/renderer.rs @@ -357,7 +357,9 @@ impl Renderer { visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Buffer { has_dynamic_offset: false, - min_binding_size: NonZeroU64::new(core::mem::size_of::() as _), + min_binding_size: NonZeroU64::new( + (core::mem::size_of::() * 4) as _, + ), ty: wgpu::BufferBindingType::Uniform, }, count: None, @@ -370,7 +372,7 @@ impl Renderer { let flag = flag as u32; device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some(&format!("egui_texture_flags_{flag}")), - contents: bytemuck::bytes_of(&flag), + contents: bytemuck::bytes_of(&[flag, 0, 0, 0]), usage: wgpu::BufferUsages::UNIFORM, }) });