将 Rust 编译为 wasm(Web 程序集)时,如何休眠 10 毫秒?

2024-02-08

我的 Rust 程序正在管理 2d html 画布上下文的内存,我试图达到 ~60fps。我可以轻松计算出每帧之间的增量,结果大约约为 5 毫秒。

我不清楚如何让我的 Rust WebAssembly 程序休眠剩余的 11 毫秒。一种选择是让 JavaScript 调用 RustrequestAnimationFrame并使用它作为驱动程序,但如果可能的话,我很好奇将其全部保留在 Rust 中。

我实际上正在寻找 JavaScript 的 Rust 等价物setTimeout(renderNext, 11)当编译到 wasm 目标时。


In your requestAnimationFrame回调,呼叫setTimeout,然后依次进行下一次调用requestAnimationFrame。你可以看看这个的JS版本here https://stackoverflow.com/a/39135659/297468.

基于中的示例wasm-bindgen book https://rustwasm.github.io/docs/wasm-bindgen/examples/request-animation-frame.html#srclibrs,这是我在 Rust 中执行此操作的方法:

fn animate_limited(mut draw_frame: impl FnMut() + 'static, max_fps: i32) {
    // Based on:
    // https://rustwasm.github.io/docs/wasm-bindgen/examples/request-animation-frame.html#srclibrs

    // https://doc.rust-lang.org/book/ch15-05-interior-mutability.html
    let animate_cb = Rc::new(RefCell::new(None));
    let animate_cb2 = animate_cb.clone();

    let timeout_cb = Rc::new(RefCell::new(None));
    let timeout_cb2 = timeout_cb.clone();

    let w = window();
    *timeout_cb2.borrow_mut() = Some(Closure::wrap(Box::new(move || {
        request_animation_frame(&w, animate_cb.borrow().as_ref().unwrap());
    }) as Box<dyn FnMut()>));

    let w2 = window();
    *animate_cb2.borrow_mut() = Some(Closure::wrap(Box::new(move || {
        draw_frame();

        set_timeout(&w2, timeout_cb.borrow().as_ref().unwrap(), 1000 / max_fps);
    }) as Box<dyn FnMut()>));

    request_animation_frame(&window(), animate_cb2.borrow().as_ref().unwrap());
}

fn window() -> web_sys::Window {
    web_sys::window().expect("no global `window` exists")
}

fn request_animation_frame(window: &web_sys::Window, f: &Closure<dyn FnMut()>) -> i32 {
    window
        .request_animation_frame(f.as_ref().unchecked_ref())
        .expect("should register `requestAnimationFrame` OK")
}

fn set_timeout(window: &web_sys::Window, f: &Closure<dyn FnMut()>, timeout_ms: i32) -> i32 {
    window
        .set_timeout_with_callback_and_timeout_and_arguments_0(
            f.as_ref().unchecked_ref(),
            timeout_ms,
        )
        .expect("should register `setTimeout` OK")
}

然后你只需通过animate_limited一个进行绘图的函数(像这样的闭包move || { /* drawing logic here */ }就可以了),以及你想要的最大帧速率。

几乎可以肯定,那里还需要改进。我对 Rust 很陌生,只是花了太长时间来弄清楚如何使其工作。希望这能让其他人在未来更快地完成任务。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 Rust 编译为 wasm(Web 程序集)时,如何休眠 10 毫秒? 的相关文章

随机推荐