mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Fix wgpu padding (#8448)
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: <https://github.com/viridia/quill/pull/14> The biggest change I made was in `egui-wgpu` to `r_tex_nearest_filtering` Shader (`egui.wgsl`) ```wgsl // Old @group(1) @binding(2) var<uniform> r_tex_nearest_filtering: u32; // New @group(1) @binding(2) var<uniform> r_tex_nearest_filtering: vec4<u32>; ``` 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 <https://github.com/emilk/egui/issues/8446> * Fixes <https://github.com/emilk/egui/issues/8446> * [X] I have followed the instructions in the PR template --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,7 @@ fn vs_main(
|
|||||||
@group(1) @binding(0) var r_tex_color: texture_2d<f32>;
|
@group(1) @binding(0) var r_tex_color: texture_2d<f32>;
|
||||||
@group(1) @binding(1) var r_tex_sampler: sampler;
|
@group(1) @binding(1) var r_tex_sampler: sampler;
|
||||||
|
|
||||||
|
|
||||||
/// Set in bit 0 of `r_tex_flags` if the sampler uses nearest filtering.
|
/// Set in bit 0 of `r_tex_flags` if the sampler uses nearest filtering.
|
||||||
///
|
///
|
||||||
/// Must match `TEX_FLAG_NEAREST` in `renderer.rs`.
|
/// Must match `TEX_FLAG_NEAREST` in `renderer.rs`.
|
||||||
@@ -114,11 +115,11 @@ const WRAP_MODE_MIRRORED_REPEAT: u32 = 2u;
|
|||||||
///
|
///
|
||||||
/// Bit 0: `TEX_FLAG_NEAREST`.
|
/// Bit 0: `TEX_FLAG_NEAREST`.
|
||||||
/// Bits 1+: one of the `WRAP_MODE_*` constants.
|
/// Bits 1+: one of the `WRAP_MODE_*` constants.
|
||||||
@group(1) @binding(2) var<uniform> r_tex_flags: u32;
|
@group(1) @binding(2) var<uniform> r_tex_flags: vec4<u32>;
|
||||||
|
|
||||||
/// Map a texel coordinate to a valid texel according to the texture's wrap mode.
|
/// Map a texel coordinate to a valid texel according to the texture's wrap mode.
|
||||||
fn wrap_texel_coord(coord: vec2<i32>, texture_size: vec2<i32>) -> vec2<i32> {
|
fn wrap_texel_coord(coord: vec2<i32>, texture_size: vec2<i32>) -> vec2<i32> {
|
||||||
let wrap_mode = r_tex_flags >> 1u;
|
let wrap_mode = r_tex_flags[0] >> 1u;
|
||||||
if wrap_mode == WRAP_MODE_REPEAT {
|
if wrap_mode == WRAP_MODE_REPEAT {
|
||||||
return ((coord % texture_size) + texture_size) % texture_size;
|
return ((coord % texture_size) + texture_size) % texture_size;
|
||||||
} else if wrap_mode == WRAP_MODE_MIRRORED_REPEAT {
|
} else if wrap_mode == WRAP_MODE_MIRRORED_REPEAT {
|
||||||
@@ -131,6 +132,7 @@ fn wrap_texel_coord(coord: vec2<i32>, texture_size: vec2<i32>) -> vec2<i32> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn sample_texture(in: VertexOutput) -> vec4<f32> {
|
fn sample_texture(in: VertexOutput) -> vec4<f32> {
|
||||||
if r_locals.predictable_texture_filtering == 0 {
|
if r_locals.predictable_texture_filtering == 0 {
|
||||||
// Hardware filtering: fast, but varies across GPUs and drivers.
|
// Hardware filtering: fast, but varies across GPUs and drivers.
|
||||||
@@ -139,7 +141,7 @@ fn sample_texture(in: VertexOutput) -> vec4<f32> {
|
|||||||
let texture_size = vec2<i32>(textureDimensions(r_tex_color, 0));
|
let texture_size = vec2<i32>(textureDimensions(r_tex_color, 0));
|
||||||
let texture_size_f = vec2<f32>(texture_size);
|
let texture_size_f = vec2<f32>(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.
|
// Nearest filtering: load the texel under the sample position.
|
||||||
let texel = wrap_texel_coord(vec2<i32>(floor(in.tex_coord * texture_size_f)), texture_size);
|
let texel = wrap_texel_coord(vec2<i32>(floor(in.tex_coord * texture_size_f)), texture_size);
|
||||||
return textureLoad(r_tex_color, texel, 0);
|
return textureLoad(r_tex_color, texel, 0);
|
||||||
|
|||||||
@@ -357,7 +357,9 @@ impl Renderer {
|
|||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
ty: wgpu::BindingType::Buffer {
|
ty: wgpu::BindingType::Buffer {
|
||||||
has_dynamic_offset: false,
|
has_dynamic_offset: false,
|
||||||
min_binding_size: NonZeroU64::new(core::mem::size_of::<u32>() as _),
|
min_binding_size: NonZeroU64::new(
|
||||||
|
(core::mem::size_of::<u32>() * 4) as _,
|
||||||
|
),
|
||||||
ty: wgpu::BufferBindingType::Uniform,
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
@@ -370,7 +372,7 @@ impl Renderer {
|
|||||||
let flag = flag as u32;
|
let flag = flag as u32;
|
||||||
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||||
label: Some(&format!("egui_texture_flags_{flag}")),
|
label: Some(&format!("egui_texture_flags_{flag}")),
|
||||||
contents: bytemuck::bytes_of(&flag),
|
contents: bytemuck::bytes_of(&[flag, 0, 0, 0]),
|
||||||
usage: wgpu::BufferUsages::UNIFORM,
|
usage: wgpu::BufferUsages::UNIFORM,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user