gfx-rs / wgpu

A cross-platform, safe, pure-Rust graphics API.
https://wgpu.rs
Apache License 2.0
12.57k stars 919 forks source link

Strange random behavior when creating an adapter (running in web only with webgl as fallback) #5881

Closed MrFastDie closed 4 months ago

MrFastDie commented 4 months ago

Description So it's a strange behavior that I cannot always reproduce. Sometimes when I reload my browser I get the error, that I cannot crate an adapter. Sometimes it strangely works, its a question of how much I am willing to refresh the page.

Repro steps Just remove the macros from below, they just do some console.log stuff for me.

You will see three behaviors:

  1. The page is running (you see a black cube)
  2. The Canvas is empty (thats when it could not create the adapter, sometimes you might also get a BorrowMutex error I think thats a platform dependend bug from winit - happens most on mac with safari)
  3. Sometimes the Shader dont appear to be working and you see a black page.
use std::borrow::Cow;
use std::mem;
use std::panic;
use std::sync::Arc;

use bytemuck::Pod;
use bytemuck::Zeroable;
use glam::Mat4;
use macros::debug;
use macros::error;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;
use wasm_bindgen_futures::JsFuture;
use web_sys::js_sys::Function;
use web_sys::js_sys::Promise;
use wgpu::util::DeviceExt;
use wgpu::Backends;
use wgpu::Device;
use wgpu::Instance;
use wgpu::InstanceDescriptor;
use wgpu::StoreOp;
use wgpu::Surface;
use winit::application::ApplicationHandler;
use winit::dpi::PhysicalPosition;
use winit::event::WindowEvent;
use winit::event_loop::ActiveEventLoop;
use winit::event_loop::ControlFlow;
use winit::event_loop::EventLoop;
use winit::event_loop::EventLoopProxy;
use winit::platform::web::EventLoopExtWebSys;
use winit::platform::web::WindowAttributesExtWebSys;
use winit::window::Window;
use winit::window::WindowId;

mod macros;

#[wasm_bindgen]
#[allow(dead_code)]
struct State {
    proxy: EventLoopProxy<UserEvent>,
}

#[derive(Debug)]
pub enum UserEvent {
    WakeUp,
    Initialized(InitializedApp),
}

pub async fn sleep_impl(dur: web_time::Duration) {
    let mut cb = |resolve: Function, _reject: Function| {
        if let Some(window) = web_sys::window() {
            if let Err(err) = window.set_timeout_with_callback_and_timeout_and_arguments_0(
                &resolve,
                dur.as_secs() as i32,
            ) {
                console_error!("failed to call window.set_timeout: {err:?}");
            }
        }
    };
    if let Err(err) = JsFuture::from(Promise::new(&mut cb)).await {
        console_error!("failed to create sleep future: {err:?}");
    }
}

#[wasm_bindgen]
impl State {
    #[wasm_bindgen(constructor)]
    pub async fn new(canvas: web_sys::HtmlCanvasElement) -> Result<State, JsValue> {
        panic::set_hook(Box::new(console_error_panic_hook::hook));

        let event_loop = EventLoop::<UserEvent>::with_user_event()
            .build()
            .expect("Failed to create event loop");
        event_loop.set_control_flow(ControlFlow::Wait);

        let event_loop_proxy = event_loop.create_proxy();

        let app = App::create::<UserEvent>(canvas, event_loop_proxy.clone()).await;

        event_loop.spawn_app(app);

        Ok(State {
            proxy: event_loop_proxy,
        })
    }
}

#[derive(Debug)]
pub struct InitializedApp {
    window: Arc<Window>,
    surface: Surface<'static>,
    device: Device,
    queue: wgpu::Queue,
    config: wgpu::SurfaceConfiguration,

    vertex_buf: wgpu::Buffer,
    index_buf: wgpu::Buffer,
    index_count: usize,
    bind_group: wgpu::BindGroup,
    uniform_buf: wgpu::Buffer,
    pipeline: wgpu::RenderPipeline,
}

impl InitializedApp {
    fn generate_matrix(aspect_ratio: f32) -> glam::Mat4 {
        // let projection = glam::Mat4::perspective_rh(consts::FRAC_PI_4, aspect_ratio, 1.0, 10.0);
        // let view = glam::Mat4::look_at_rh(
        //     glam::Vec3::new(1.5f32, -5.0, 3.0),
        //     glam::Vec3::ZERO,
        //     glam::Vec3::Z,
        // );
        // projection * view

        let projection = glam::Mat4::perspective_rh_gl(45 as f32, aspect_ratio, 0.1, 100.0);
        let view = glam::Mat4::look_at_rh(
            glam::Vec3::new(2.0, 2.0, 2.0), // Make sure this is positioned to see the cube
            glam::Vec3::new(0.0, 0.0, 0.0),
            glam::Vec3::Y,
        );
        projection * view
    }
}

struct App {
    initialized_app: Option<InitializedApp>,
    canvas: web_sys::HtmlCanvasElement,
    event_loop_proxy: EventLoopProxy<UserEvent>,
}

impl App {
    pub async fn create<T>(
        canvas: web_sys::HtmlCanvasElement,
        proxy: EventLoopProxy<UserEvent>,
    ) -> Self {
        App {
            canvas,
            initialized_app: None,
            event_loop_proxy: proxy,
        }
    }
}

async fn init(w: Arc<Window>) -> InitializedApp {
    let instance = Instance::new(InstanceDescriptor {
        backends: Backends::BROWSER_WEBGPU,
        flags: Default::default(),
        dx12_shader_compiler: Default::default(),
        gles_minor_version: Default::default(),
    });
    let surface = instance
        .create_surface(w.clone())
        .map_err(|e| console_error!("CreateSurfaceError: {:?}", e))
        .unwrap();

    let adapter = instance
        .request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::default(),
            force_fallback_adapter: false,
            compatible_surface: Some(&surface),
        })
        .await
        .expect("Failed to find an appropriate adapter");

    // Create the logical device and command queue
    let (device, queue) = adapter
        .request_device(
            &wgpu::DeviceDescriptor {
                label: None,
                required_features: adapter.features(),
                // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain.
                required_limits: wgpu::Limits::downlevel_webgl2_defaults()
                    .using_resolution(adapter.limits()),
            },
            None,
        )
        .await
        .expect("Failed to create device");

    let config = surface
        .get_default_config(&adapter, w.inner_size().width, w.inner_size().height)
        .unwrap();

    surface.configure(&device, &config);

    w.request_redraw();

    // Create the vertex and index buffers
    let vertex_size = mem::size_of::<Vertex>();
    let vertex_data = VERTICES;
    let index_data = INDICES;

    let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
        label: Some("Vertex Buffer"),
        contents: bytemuck::cast_slice(&vertex_data),
        usage: wgpu::BufferUsages::VERTEX,
    });

    let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
        label: Some("Index Buffer"),
        contents: bytemuck::cast_slice(&index_data),
        usage: wgpu::BufferUsages::INDEX,
    });

    // Create pipeline layout
    let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
        label: None,
        entries: &[wgpu::BindGroupLayoutEntry {
            binding: 0,
            visibility: wgpu::ShaderStages::VERTEX,
            ty: wgpu::BindingType::Buffer {
                ty: wgpu::BufferBindingType::Uniform,
                has_dynamic_offset: false,
                min_binding_size: wgpu::BufferSize::new(64),
            },
            count: None,
        }],
    });
    let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
        label: None,
        bind_group_layouts: &[&bind_group_layout],
        push_constant_ranges: &[],
    });

    // Create other resources
    let mx_total = InitializedApp::generate_matrix(config.width as f32 / config.height as f32);
    let mx_ref: &[f32; 16] = mx_total.as_ref();
    let uniform_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
        label: Some("Uniform Buffer"),
        contents: bytemuck::cast_slice(mx_ref),
        usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
    });

    // Create bind group
    let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
        layout: &bind_group_layout,
        entries: &[wgpu::BindGroupEntry {
            binding: 0,
            resource: uniform_buf.as_entire_binding(),
        }],
        label: None,
    });

    let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
        label: None,
        source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
    });

    let vertex_buffers = [wgpu::VertexBufferLayout {
        array_stride: vertex_size as wgpu::BufferAddress,
        step_mode: wgpu::VertexStepMode::Vertex,
        attributes: &[
            // Position
            wgpu::VertexAttribute {
                format: wgpu::VertexFormat::Float32x4,
                offset: 0,
                shader_location: 0,
            },
            // Color
            wgpu::VertexAttribute {
                format: wgpu::VertexFormat::Float32x4,
                offset: 4 * 4,
                shader_location: 1,
            },
            // Edge
            wgpu::VertexAttribute {
                format: wgpu::VertexFormat::Float32,
                offset: 8 * 4,
                shader_location: 2,
            },
        ],
    }];

    let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
        label: None,
        layout: Some(&pipeline_layout),
        vertex: wgpu::VertexState {
            module: &shader,
            entry_point: "vs_main",
            compilation_options: Default::default(),
            buffers: &vertex_buffers,
        },
        fragment: Some(wgpu::FragmentState {
            module: &shader,
            entry_point: "fs_main",
            compilation_options: Default::default(),
            targets: &[Some(config.format.into())],
        }),
        primitive: wgpu::PrimitiveState {
            cull_mode: Some(wgpu::Face::Back),
            ..Default::default()
        },
        depth_stencil: None,
        multisample: wgpu::MultisampleState::default(),
        multiview: None,
    });

    InitializedApp {
        window: w,
        surface,
        device,
        queue,
        config,

        vertex_buf,
        index_buf,
        index_count: index_data.len(),
        bind_group,
        uniform_buf,
        pipeline,
    }
}

impl ApplicationHandler<UserEvent> for App {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        console_debug!("Resumed");

        if self.initialized_app.is_some() {
            return;
        }

        let window_attributes = WindowAttributesExtWebSys::with_canvas(
            Window::default_attributes(),
            Some(self.canvas.clone()),
        )
        .with_append(true);

        let window = Arc::new(event_loop.create_window(window_attributes.clone()).unwrap());
        let proxy_clone = self.event_loop_proxy.clone();

        wasm_bindgen_futures::spawn_local(async move {
            let x = init(window).await;
            proxy_clone
                .send_event(UserEvent::Initialized(x))
                .expect("Initialized web");
        });
    }
    fn user_event(&mut self, _event_loop: &ActiveEventLoop, event: UserEvent) {
        console_debug!("User event received");

        match event {
            UserEvent::WakeUp => {
                console_debug!("WakeUp");
            }
            UserEvent::Initialized(initialized) => {
                self.initialized_app = Some(initialized);

                console_debug!("Initialized");
            }
        }
    }

    fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
        if !self.initialized_app.is_some() {
            console_error!("App is not initialized, exiting");

            return;
        }

        let initialized = self.initialized_app.as_mut().unwrap();

        console_debug!("Event Received");
        match event {
            WindowEvent::CloseRequested => {
                event_loop.exit();
            }
            WindowEvent::CursorMoved {
                position: PhysicalPosition { x, y },
                device_id: _,
            } => {
                if let Some(app) = &mut self.initialized_app {
                    console_debug!("Rotating app to x: {} y: {}", x, y);
                    let width = app.config.width as f32;
                    let height = app.config.height as f32;

                    // Normalize cursor coordinates to range [-1, 1]
                    let x_norm = x as f32 / width * 2.0 - 1.0;
                    let y_norm = y as f32 / height * 2.0 - 1.0;

                    // Update view matrix with new angles
                    let rotation_x = Mat4::from_rotation_x(x_norm);
                    let rotation_y = Mat4::from_rotation_x(y_norm);

                    // Combine rotations with the existing projection
                    let aspect_ratio = width / height;

                    let projection = glam::Mat4::perspective_rh_gl(45.0, aspect_ratio, 0.1, 100.0);
                    let view = glam::Mat4::look_at_rh(
                        glam::Vec3::new(2.0, 2.0, 2.0), // Make sure this is positioned to see the cube
                        glam::Vec3::new(0.0, 0.0, 0.0),
                        glam::Vec3::Y,
                    );
                    let mx_total = projection * view * rotation_x * rotation_y;

                    let mx_ref: &[f32; 16] = mx_total.as_ref();
                    app.queue
                        .write_buffer(&app.uniform_buf, 0, bytemuck::cast_slice(mx_ref));

                    // Request redraw to update the scene with new rotation
                    app.window.request_redraw();
                }
            }
            WindowEvent::Resized(new_size) => {
                console_debug!("Resizing");

                let mx_total =
                    InitializedApp::generate_matrix(new_size.width as f32 / new_size.height as f32);
                let mx_ref: &[f32; 16] = mx_total.as_ref();
                initialized.queue.write_buffer(
                    &initialized.uniform_buf,
                    0,
                    bytemuck::cast_slice(mx_ref),
                );

                // let mut config = initialized.config.clone();
                // config.width = new_size.width.max(1);
                // config.height = new_size.height.max(1);
                //
                // initialized.surface.configure(&initialized.device, &config);
                //
                // initialized.config = config;
                //
                // // On macos the window needs to be redrawn manually after resizing
                initialized.window.request_redraw();
            }
            WindowEvent::RedrawRequested => {
                console_debug!("Redraw Requested");
                let frame = initialized
                    .surface
                    .get_current_texture()
                    .expect("Failed to acquire next swap chain texture");

                let view = frame
                    .texture
                    .create_view(&wgpu::TextureViewDescriptor::default());

                let mut encoder = initialized
                    .device
                    .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });

                {
                    let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
                        label: None,
                        color_attachments: &[Some(wgpu::RenderPassColorAttachment {
                            view: &view,
                            resolve_target: None,
                            ops: wgpu::Operations {
                                load: wgpu::LoadOp::Clear(wgpu::Color {
                                    r: 0.1,
                                    g: 0.2,
                                    b: 0.3,
                                    a: 1.0,
                                }),
                                store: StoreOp::Store,
                            },
                        })],
                        depth_stencil_attachment: None,
                        timestamp_writes: None,
                        occlusion_query_set: None,
                    });
                    rpass.set_pipeline(&initialized.pipeline);
                    rpass.set_bind_group(0, &initialized.bind_group, &[]);
                    rpass.set_index_buffer(
                        initialized.index_buf.slice(..),
                        wgpu::IndexFormat::Uint16,
                    );
                    rpass.set_vertex_buffer(0, initialized.vertex_buf.slice(..));
                    rpass.draw_indexed(0..initialized.index_count as u32, 0, 0..1);
                }

                initialized.queue.submit(Some(encoder.finish()));
                frame.present();
            }
            _ => (),
        }
    }
}

#[repr(C)]
#[derive(Copy, Clone)]
struct Vertex {
    _pos: [f32; 4],
    _color: [f32; 4],
    _edge: f32,
}

unsafe impl Zeroable for Vertex {}
unsafe impl Pod for Vertex {}

const VERTICES: &[Vertex] = &[
    Vertex {
        _pos: [-1.0, 1.0, -1.0, 1.0],
        _color: [1.0, 0.0, 0.0, 1.0],
        _edge: 1.0,
    },
    Vertex {
        _pos: [1.0, 1.0, -1.0, 1.0],
        _color: [1.0, 0.0, 0.0, 1.0],
        _edge: 1.0,
    },
    Vertex {
        _pos: [1.0, -1.0, -1.0, 1.0],
        _color: [1.0, 0.0, 0.0, 1.0],
        _edge: 1.0,
    },
    Vertex {
        _pos: [1.0, -1.0, -1.0, 1.0],
        _color: [1.0, 0.0, 0.0, 1.0],
        _edge: 1.0,
    },
    // back
    Vertex {
        _pos: [-1.0, 1.0, 1.0, 1.0],
        _color: [0.0, 0.0, 1.0, 1.0],
        _edge: 1.0,
    },
    Vertex {
        _pos: [1.0, 1.0, 1.0, 1.0],
        _color: [0.0, 0.0, 1.0, 1.0],
        _edge: 1.0,
    },
    Vertex {
        _pos: [-1.0, -1.0, 1.0, 1.0],
        _color: [0.0, 0.0, 1.0, 1.0],
        _edge: 1.0,
    },
    Vertex {
        _pos: [1.0, -1.0, 1.0, 1.0],
        _color: [0.0, 0.0, 1.0, 1.0],
        _edge: 1.0,
    },
];

// Indices for each triangle in a cube
const INDICES: [u16; 36] = [
    2, 0, 1, 1, 3, 2, // bottom
    6, 7, 5, 5, 4, 6, // top
    0, 4, 5, 5, 1, 0, // back
    2, 3, 7, 7, 6, 2, // front
    3, 1, 5, 5, 7, 3, // right
    2, 6, 4, 4, 0, 2, // left
];

cargo.toml (For some reason enabling WebGL features forcing me to include getrandom)

[package]
name = "rusty_cube_wasm"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4.42"
wgpu = { version = "0.20.1", features = ["webgpu", "webgl"] }
bytemuck = "1.16.1"
console_error_panic_hook = "0.1.7"
web-time = "1.1.0"
rusty_cube_geometry = { path = "../geometry" }
getrandom = { version = "0.2.15", features = ["js"] }
glam = "0.28.0"

[lib]
crate-type = ["cdylib"]

[dependencies.web-sys]
version = "0.3"
features = [
    "Window",
    "Document",
    "HtmlCanvasElement",
    "console",
]

[dependencies.winit]
version = "0.30.3"
features = ["default"]

[features]
default = []
web_platform = []
winit_platform = ["web_platform"]

.cargo/config.toml:

[build]
rustflags = ["--cfg", "web_platform"]
target = "wasm32-unknown-unknown"

Expected vs observed behavior My expected behavior is that my cube should draw every time I refresh the page

Platform Right now I'm running Arch with a AMD gpu and the vulkan-amdgpu-pro driver but I get the same behavior on my Macbook with Chrome and Safari. Strangly I can't get WebGPU running on Chrome on arch at all - but that seems more like a chrome bug. Chromium on Arch is the same as Firefox for me.

Wumpf commented 4 months ago

are there any errors on the browser's console on the failure cases Did you experience any issues with this on native?

MrFastDie commented 4 months ago

Ah yes sorry, wenn the BorrowMutexErr occurs:

panicked at /home/daniel/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-bindgen-futures-0.4.42/src/lib.rs:136:39:
already borrowed: BorrowMutError

Stack:

__wbg_get_imports/imports.wbg.__wbg_new_abda76e883ba8a5f@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:387:21
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[4123]:0x27f99d
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1780]:0x1cca39
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3059]:0x26fa0d
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2648]:0x24315b
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1692]:0x1c52ba
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2740]:0x2455ca
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2368:37
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3718]:0x278f0e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1097]:0x16df07
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2170]:0x1f77d8
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[607]:0x81f06
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2053]:0x1e9df0
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1692]:0x1c52af
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2740]:0x2455ca
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2368:37
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3718]:0x278f0e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1097]:0x16df07
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2025]:0x1e5d52
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[607]:0x81b6c
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2555]:0x24106d
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[713]:0xe3ef4
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2555]:0x24106d

[rusty_cube_wasm.js:403:20](http://localhost:5173/src/wasm/rusty_cube_wasm.js)
Uncaught (in promise) RuntimeError: unreachable executed
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566 rusty_cube_wasm.js:2368
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566 rusty_cube_wasm.js:2368
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4

Adapter creation

    panicked at wasm/src/lib.rs:162:10:
Failed to find an appropriate adapter

Stack:

__wbg_get_imports/imports.wbg.__wbg_new_abda76e883ba8a5f@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:387:21
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[4123]:0x27f99d
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1780]:0x1cca39
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3059]:0x26fa0d
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2849]:0x24b152
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3327]:0x273be1
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[607]:0x81cf3
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2053]:0x1e9df0
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1692]:0x1c52af
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2740]:0x2455ca
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2368:37
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3718]:0x278f0e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1097]:0x16df07
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2170]:0x1f77d8
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[607]:0x81f06
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2053]:0x1e9df0
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1692]:0x1c52af
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2740]:0x2455ca
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2368:37
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3718]:0x278f0e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1097]:0x16df07
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2025]:0x1e5d52
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[607]:0x81b6c
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2555]:0x24106d
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[713]:0xe3ef4
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1237]:0x18b33e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3619]:0x277afd
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[3618]:0x277aef
__wbg_adapter_58@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:240:10
real@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:209:20
VoidFunction*__wbg_get_imports/imports.wbg.__wbg_queueMicrotask_481971b0d87f3dd4@http://localhost:5173/src/wasm/rusty_cube_wasm.js?t=1719383020861:2245:23
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[1890]:0x1d840e
@http://localhost:5173/src/wasm/rusty_cube_wasm_bg.wasm:wasm-function[2555]:0x24106d

rusty_cube_wasm.js:403:20
Uncaught RuntimeError: unreachable executed
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566 rusty_cube_wasm.js:2368
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566 rusty_cube_wasm.js:2368
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
rusty_cube_wasm_bg.wasm:1886815:1

and

Uncaught (in promise) Error: closure invoked recursively or after being dropped
    __wbindgen_throw rusty_cube_wasm.js:2430
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    promise callback*__wbg_get_imports/imports.wbg.__wbg_then_a73caa9a87991566 rusty_cube_wasm.js:2368
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_58 rusty_cube_wasm.js:240
    real rusty_cube_wasm.js:209
    __wbg_queueMicrotask_481971b0d87f3dd4 rusty_cube_wasm.js:2245
    __wbg_adapter_1106 rusty_cube_wasm.js:284
    cb0 rusty_cube_wasm.js:2344
    __wbg_new_81740750da40724f rusty_cube_wasm.js:2349
    State rusty_cube_wasm.js:317
    initializeWasm wasm.tsx:12
    WasmComponent wasm.tsx:18
    commitHookEffectListMount chunk-52HAZHR6.js:24343
    invokePassiveEffectMountInDEV chunk-52HAZHR6.js:25759
    invokeEffectsInDev chunk-52HAZHR6.js:27136
    commitDoubleInvokeEffectsInDEV chunk-52HAZHR6.js:27121
    flushPassiveEffectsImpl chunk-52HAZHR6.js:26938
    flushPassiveEffects chunk-52HAZHR6.js:26882
    commitRootImpl chunk-52HAZHR6.js:26763
    workLoop chunk-52HAZHR6.js:485
    flushWork chunk-52HAZHR6.js:464
    performWorkUntilDeadline chunk-52HAZHR6.js:672
    js chunk-52HAZHR6.js:693
    js chunk-52HAZHR6.js:741
    __require chunk-OP2PB36O.js:18
    js chunk-52HAZHR6.js:756
    __require chunk-OP2PB36O.js:18
    js chunk-52HAZHR6.js:7920
    js chunk-52HAZHR6.js:28995
    __require chunk-OP2PB36O.js:18
    js chunk-52HAZHR6.js:29024
    __require chunk-OP2PB36O.js:18
    js react-dom_client.js:26
    __require chunk-OP2PB36O.js:18
    <anonymous> react-dom_client.js:52
rusty_cube_wasm.js:2430:14
MrFastDie commented 4 months ago

are there any errors on the browser's console on the failure cases Did you experience any issues with this on native?

With on native you mean with no features enabled? It's the same but the errors seem to occur less but that at this point could just be the stars align different for me.

Wumpf commented 4 months ago

I meant when running this not as a web application but the same code for a native application. Nevermind if that's too much trouble setting up for you right now.

Thanks for those logs. Without more symbols they aren't unfortunately very useful. I was hoping that there's some useful callstack or that wgpu logged some more errors before this happens - there's nothing there? That would first require some setup like https://github.com/gfx-rs/wgpu/blob/trunk/examples/src/framework.rs#L55

As-is, the only thing to go about this bug boils down essentially to debugging the application code you posted, a bit much as a starting point :/

teoxoy commented 4 months ago

I don't think this is an issue on our side, please reopen if further debugging shows otherwise.

lexi-the-cute commented 2 days ago

I'm also getting already borrowed: BorrowMutError when I upgrade wgpu from 0.20.1 to 22.0 on Firefox. something about grabbing an adapter failed. will have to look into this more

Edit: yep. it's a consistent bug for me both for Firefox and Chromium. This is my config where I reverted back to a version of WGPU where it works in the browser. https://github.com/lexi-the-cute/catgirl-engine/commit/0f83bba143dda4c4e18bd56b32fe3553d89c118f#diff-d65079572c3a43b4c213b69ff6258e5c7dde09a43ec9905135062c52b3fc1654R111

Screenshot_20241101_232547