bevy icon indicating copy to clipboard operation
bevy copied to clipboard

wasm: animate_shader example panics with validation error

Open rparrett opened this issue 3 years ago • 5 comments

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

rparrett avatar Jul 20 '22 14:07 rparrett

Related? https://github.com/gfx-rs/wgpu/issues/4522

rparrett avatar Jul 30 '22 18:07 rparrett

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.

simbleau avatar Jul 31 '22 23:07 simbleau

Sorry, I'm a bit new to this. How do I add padding for structs implementing Material2D?

Pietrek14 avatar Sep 07 '22 20:09 Pietrek14

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>,
};

rparrett avatar Sep 07 '22 21:09 rparrett

And should I change the way I read the uniforms in my shader somehow?

Pietrek14 avatar Sep 08 '22 14:09 Pietrek14

This now affects anyone using globals in their shaders.

rparrett avatar Nov 03 '22 21:11 rparrett