bevy
bevy copied to clipboard
wasm: animate_shader example panics with validation error
Bevy version
latest main, 0.7 (different error)
Relevant system information
m1 mac, chrome, firefox
AdapterInfo { name: "ANGLE (Apple, Apple M1 Max, OpenGL 4.1)", vendor: 0, device: 0, device_type: IntegratedGpu, backend: Gl }
What you did
with wasm-server-runner,
cargo run --target wasm32-unknown-unknown --example animate_shader
What went wrong
wasm.js:407 panicked at 'wgpu error: Validation Error
Caused by:
In Device::create_render_pipeline
note: label = `opaque_mesh_pipeline`
Downlevel flags BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED are required but not supported on the device.
This is not an invalid use of WebGPU: the underlying API or device does not support enough features to be a fully compliant implementation. A subset of the features can still be used. If you are running this program on native and not in a browser and wish to work around this issue, call Adapter::downlevel_properties or Device::downlevel_properties to get a listing of the features the current platform supports.
Additional information
I encountered this while working on updating bevy_ecs_tilemap, and was able to manually hack some padding in to work around the issue. But that does not seem ideal.
Similarly, if I hack some padding into this example like this:
diff --git a/assets/shaders/animate_shader.wgsl b/assets/shaders/animate_shader.wgsl
index 947c4a542..ff01630a7 100644
--- a/assets/shaders/animate_shader.wgsl
+++ b/assets/shaders/animate_shader.wgsl
@@ -29,6 +29,9 @@ fn vertex(vertex: Vertex) -> VertexOutput {
struct Time {
time_since_startup: f32,
+ _padding_a: f32,
+ _padding_b: f32,
+ _padding_c: f32
};
@group(2) @binding(0)
var<uniform> time: Time;
diff --git a/examples/shader/animate_shader.rs b/examples/shader/animate_shader.rs
index 6d9832777..fd26dae99 100644
--- a/examples/shader/animate_shader.rs
+++ b/examples/shader/animate_shader.rs
@@ -65,7 +65,7 @@ impl Plugin for CustomMaterialPlugin {
let render_device = app.world.resource::<RenderDevice>();
let buffer = render_device.create_buffer(&BufferDescriptor {
label: Some("time uniform buffer"),
- size: std::mem::size_of::<f32>() as u64,
+ size: std::mem::size_of::<[f32; 4]>() as u64,
usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
mapped_at_creation: false,
});
@@ -163,7 +163,7 @@ fn prepare_time(
render_queue.write_buffer(
&time_meta.buffer,
0,
- bevy::core::cast_slice(&[time.seconds_since_startup]),
+ bevy::core::cast_slice(&[time.seconds_since_startup, 0., 0., 0.]),
);
}
@@ -205,7 +205,7 @@ impl FromWorld for CustomPipeline {
ty: BindingType::Buffer {
ty: BufferBindingType::Uniform,
has_dynamic_offset: false,
- min_binding_size: BufferSize::new(std::mem::size_of::<f32>() as u64),
+ min_binding_size: BufferSize::new(std::mem::size_of::<[f32; 4]>() as u64),
},
count: None,
}],
the example works.
The only relevant wgpu issue I could find is just about the quality of the validation error itself: https://github.com/gfx-rs/wgpu/issues/2832
Bevy 0.7 fails with a different error:
256[.WebGL-0x1141d46c000] GL_INVALID_OPERATION: It is undefined behaviour to use a uniform buffer that is too small.
Some additional discussion/debugging in this discord thread: https://discord.com/channels/691052431525675048/999111134600773693 and here: https://discord.com/channels/691052431525675048/866787577687310356/999311503394086983
Related? https://github.com/gfx-rs/wgpu/issues/4522
This is surprising behavior from wgpu on WASM. Doesn't really relate to Bevy, and I don't think NAGA is the issue - although NAGA could (if wgpu didn't) add padding automatically.
Sorry, I'm a bit new to this. How do I add padding for structs implementing Material2D?
Here's what worked for me.
#[derive(AsBindGroup, TypeUuid, Debug, Default, Clone)]
#[uuid = "721097c0-7368-453f-a95f-0731d6724689"]
pub struct StarfieldMaterial {
#[uniform(0)]
pub pos: Vec2,
#[uniform(0)]
pub _wasm_padding: Vec2,
}
And in the shader:
struct StarfieldMaterial {
pos: vec2<f32>,
_wasm_padding: vec2<f32>,
};
And should I change the way I read the uniforms in my shader somehow?
This now affects anyone using globals in their shaders.