From ad6d5d9c312bb698b253c3931f89883b7a201411 Mon Sep 17 00:00:00 2001 From: Alexander Guryanov Date: Tue, 25 Jan 2022 17:35:45 +0700 Subject: [PATCH] =?UTF-8?q?t#=20=D0=AD=D1=82=D0=BE=20=D0=BE=D0=B1=D1=8A?= =?UTF-8?q?=D0=B5=D0=B4=D0=B8=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=202=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC=D0=BC=D0=B8=D1=82=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feature: emscripten --- .github/workflows/ci.yml | 16 ++++ Cargo.lock | 1 + wgpu-core/Cargo.toml | 3 + wgpu-hal/Cargo.toml | 8 +- wgpu-hal/examples/raw-gles.em.html | 16 ++++ wgpu-hal/examples/raw-gles.rs | 131 +++++++++++++++++++++-------- wgpu-hal/src/gles/egl.rs | 54 +++++++++--- wgpu-hal/src/gles/mod.rs | 8 +- wgpu-hal/src/gles/queue.rs | 4 +- wgpu/Cargo.toml | 3 +- wgpu/src/backend/direct.rs | 20 ++--- wgpu/src/lib.rs | 16 ++-- 12 files changed, 206 insertions(+), 74 deletions(-) create mode 100644 wgpu-hal/examples/raw-gles.em.html diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 744276fb0a1..a9af986914c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,7 @@ env: # - local: build for the same target as we compile on, and do local tests # - other: build without testing, e.g. cross-build # - web: build for the Web +# - em: build for the Emscripten jobs: build: @@ -94,6 +95,12 @@ jobs: tool: clippy kind: web + - name: Emscripten + os: ubuntu-20.04 + target: wasm32-unknown-emscripten + tool: clippy + kind: em + name: Check ${{ matrix.name }} runs-on: ${{ matrix.os }} @@ -168,6 +175,15 @@ jobs: # build docs cargo doc --target ${{ matrix.target }} -p wgpu --no-deps + - name: check em + if: matrix.kind == 'em' + run: | + # build for Emscripten/WebGL + cargo ${{matrix.tool}} --target ${{ matrix.target }} -p wgpu -p wgpu-hal --features webgl,emscripten + + # build raw-gles example + cargo ${{matrix.tool}} --target ${{ matrix.target }} --example raw-gles --features webgl,emscripten + - name: check native if: matrix.kind == 'local' || matrix.kind == 'other' run: | diff --git a/Cargo.lock b/Cargo.lock index b46a6bfbaad..807a7fafade 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -900,6 +900,7 @@ checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", "libloading", + "pkg-config", ] [[package]] diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index fecdbec031e..53ec9ef4e3d 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -65,5 +65,8 @@ hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = [target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies] hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = ["vulkan", "dx12", "renderdoc"] } +[target.'cfg(target_os = "emscripten")'.dependencies] +hal = { path = "../wgpu-hal", package = "wgpu-hal", version = "0.12", features = ["emscripten"] } + [build-dependencies] cfg_aliases = "0.1" diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 79b1a39175e..5bd4823112d 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -18,6 +18,7 @@ vulkan = ["naga/spv-out", "ash", "gpu-alloc", "gpu-descriptor", "libloading", "i gles = ["naga/glsl-out", "glow", "egl", "libloading"] dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6"] renderdoc = ["libloading", "renderdoc-sys"] +emscripten = ["gles"] [[example]] name = "halmark" @@ -66,6 +67,11 @@ egl = { package = "khronos-egl", version = "4.1", features = ["dynamic"], option #Note: it's only unused on Apple platforms libloading = { version = "0.7", optional = true } +[target.'cfg(target_os = "emscripten")'.dependencies] +egl = { package = "khronos-egl", version = "4.1", features = ["static", "no-pkg-config"] } +#Note: it's unused by emscripten, but we keep it to have single code base in egl.rs +libloading = { version = "0.7", optional = true } + [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["libloaderapi", "windef", "winuser"] } native = { package = "d3d12", version = "0.4.1", features = ["libloading"], optional = true } @@ -75,7 +81,7 @@ mtl = { package = "metal", git = "https://github.com/gfx-rs/metal-rs", rev = "14 objc = "0.2.5" core-graphics-types = "0.1" -[target.'cfg(target_arch = "wasm32")'.dependencies] +[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] wasm-bindgen = { version = "0.2" } web-sys = { version = "0.3", features = ["Window", "HtmlCanvasElement", "WebGl2RenderingContext"] } js-sys = { version = "0.3" } diff --git a/wgpu-hal/examples/raw-gles.em.html b/wgpu-hal/examples/raw-gles.em.html new file mode 100644 index 00000000000..f3587e85751 --- /dev/null +++ b/wgpu-hal/examples/raw-gles.em.html @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/wgpu-hal/examples/raw-gles.rs b/wgpu-hal/examples/raw-gles.rs index 23cb6df4314..815f4c18299 100644 --- a/wgpu-hal/examples/raw-gles.rs +++ b/wgpu-hal/examples/raw-gles.rs @@ -1,15 +1,16 @@ //! This example shows interop with raw GLES contexts - //! the ability to hook up wgpu-hal to an existing context and draw into it. +//! +//! Emscripten build: +//! 1. install emsdk +//! 2. build this example with cargo: +//! EMMAKEN_CFLAGS="-g -s ERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry -s FULL_ES3=1" cargo build --example raw-gles --target wasm32-unknown-emscripten --features emscripten,webgl +//! 3. copy raw-gles.em.html into target/wasm32-unknown-emscripten/debug/examples/ and open it in browser extern crate wgpu_hal as hal; -#[cfg(target_arch = "wasm32")] -fn main() {} - #[cfg(not(target_arch = "wasm32"))] fn main() { - use hal::{Adapter as _, CommandEncoder as _, Device as _, Queue as _}; - env_logger::init(); println!("Initializing external GL context"); @@ -32,6 +33,94 @@ fn main() { }) } .expect("GL adapter can't be initialized"); + + fill_screen(&exposed, inner_size.width, inner_size.height); + + println!("Showing the window"); + gl_context.swap_buffers().unwrap(); + + event_loop.run(move |event, _, control_flow| { + use glutin::{ + event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event_loop::ControlFlow, + }; + *control_flow = ControlFlow::Wait; + + match event { + Event::LoopDestroyed => return, + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested + | WindowEvent::KeyboardInput { + input: + KeyboardInput { + virtual_keycode: Some(VirtualKeyCode::Escape), + .. + }, + .. + } => *control_flow = ControlFlow::Exit, + _ => (), + }, + _ => (), + } + }); +} + +#[cfg(feature = "emscripten")] +fn main() { + env_logger::init(); + + println!("Initializing external GL context"); + let egl = egl::Instance::new(egl::Static); + let display = egl.get_display(egl::DEFAULT_DISPLAY).unwrap(); + egl.initialize(display) + .expect("unable to initialize display"); + + let attributes = [ + egl::RED_SIZE, + 8, + egl::GREEN_SIZE, + 8, + egl::BLUE_SIZE, + 8, + egl::NONE, + ]; + + let config = egl + .choose_first_config(display, &attributes) + .unwrap() + .expect("unable to choose config"); + let surface = unsafe { + let window = std::ptr::null_mut::(); + egl.create_window_surface(display, config, window, None) + } + .expect("unable to create surface"); + + let context_attributes = [egl::CONTEXT_CLIENT_VERSION, 3, egl::NONE]; + + let gl_context = egl + .create_context(display, config, None, &context_attributes) + .expect("unable to create context"); + egl.make_current(display, Some(surface), Some(surface), Some(gl_context)) + .expect("can't make context current"); + + println!("Hooking up to wgpu-hal"); + let exposed = unsafe { + ::Adapter::new_external(|name| { + egl.get_proc_address(name) + .map_or(std::ptr::null(), |p| p as *const _) + }) + } + .expect("GL adapter can't be initialized"); + + fill_screen(&exposed, 640, 400); +} + +#[cfg(all(target_arch = "wasm32", not(feature = "emscripten")))] +fn main() {} + +fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height: u32) { + use hal::{Adapter as _, CommandEncoder as _, Device as _, Queue as _}; + let mut od = unsafe { exposed .adapter @@ -68,8 +157,8 @@ fn main() { let rp_desc = hal::RenderPassDescriptor { label: None, extent: wgt::Extent3d { - width: inner_size.width, - height: inner_size.height, + width, + height, depth_or_array_layers: 1, }, sample_count: 1, @@ -92,32 +181,4 @@ fn main() { let cmd_buf = encoder.end_encoding().unwrap(); od.queue.submit(&[&cmd_buf], None).unwrap(); } - - println!("Showing the window"); - gl_context.swap_buffers().unwrap(); - - event_loop.run(move |event, _, control_flow| { - use glutin::{ - event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent}, - event_loop::ControlFlow, - }; - *control_flow = ControlFlow::Wait; - - match event { - Event::LoopDestroyed => return, - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested - | WindowEvent::KeyboardInput { - input: - KeyboardInput { - virtual_keycode: Some(VirtualKeyCode::Escape), - .. - }, - .. - } => *control_flow = ControlFlow::Exit, - _ => (), - }, - _ => (), - } - }); } diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs index ea49dfb3e6b..08a94560090 100644 --- a/wgpu-hal/src/gles/egl.rs +++ b/wgpu-hal/src/gles/egl.rs @@ -26,6 +26,12 @@ type WlDisplayConnectFun = type WlDisplayDisconnectFun = unsafe extern "system" fn(display: *const raw::c_void); +#[cfg(not(feature = "emscripten"))] +type EglInstance = egl::DynamicInstance; + +#[cfg(feature = "emscripten")] +type EglInstance = egl::Instance; + type WlEglWindowCreateFun = unsafe extern "system" fn( surface: *const raw::c_void, width: raw::c_int, @@ -154,7 +160,7 @@ enum SrgbFrameBufferKind { /// Choose GLES framebuffer configuration. fn choose_config( - egl: &egl::DynamicInstance, + egl: &EglInstance, display: egl::Display, srgb_kind: SrgbFrameBufferKind, ) -> Result<(egl::Config, bool), crate::InstanceError> { @@ -263,7 +269,7 @@ fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, m #[derive(Clone, Debug)] struct EglContext { - instance: Arc>, + instance: Arc, display: egl::Display, raw: egl::Context, pbuffer: Option, @@ -307,7 +313,7 @@ impl AdapterContext { } struct EglContextLock<'a> { - instance: &'a Arc>, + instance: &'a Arc, display: egl::Display, } @@ -385,6 +391,7 @@ struct Inner { version: (i32, i32), supports_native_window: bool, config: egl::Config, + #[cfg_attr(feature = "emscripten", allow(dead_code))] wl_display: Option<*mut raw::c_void>, /// Method by which the framebuffer should support srgb srgb_kind: SrgbFrameBufferKind, @@ -393,7 +400,7 @@ struct Inner { impl Inner { fn create( flags: crate::InstanceFlags, - egl: Arc>, + egl: Arc, display: egl::Display, ) -> Result { let version = egl.initialize(display).map_err(|_| crate::InstanceError)?; @@ -563,7 +570,12 @@ unsafe impl Send for Instance {} unsafe impl Sync for Instance {} impl crate::Instance for Instance { + #[cfg_attr(feature = "emscripten", allow(unused_variables))] unsafe fn init(desc: &crate::InstanceDescriptor) -> Result { + #[cfg(feature = "emscripten")] + let egl_result: Result = Ok(egl::Instance::new(egl::Static)); + + #[cfg(not(feature = "emscripten"))] let egl_result = if cfg!(windows) { egl::DynamicInstance::::load_required_from_filename("libEGL.dll") } else if cfg!(any(target_os = "macos", target_os = "ios")) { @@ -606,8 +618,14 @@ impl crate::Instance for Instance { None }; + #[cfg(not(feature = "emscripten"))] + let egl1_5 = egl.upcast::(); + + #[cfg(feature = "emscripten")] + let egl1_5: Option<&Arc> = Some(&egl); + let (display, wsi_library, wsi_kind) = if let (Some(library), Some(egl)) = - (wayland_library, egl.upcast::()) + (wayland_library, egl1_5) { log::info!("Using Wayland platform"); let display_attributes = [egl::ATTRIB_NONE]; @@ -619,18 +637,14 @@ impl crate::Instance for Instance { ) .unwrap(); (display, Some(Arc::new(library)), WindowKind::Wayland) - } else if let (Some((display, library)), Some(egl)) = - (x11_display_library, egl.upcast::()) - { + } else if let (Some((display, library)), Some(egl)) = (x11_display_library, egl1_5) { log::info!("Using X11 platform"); let display_attributes = [egl::ATTRIB_NONE]; let display = egl .get_platform_display(EGL_PLATFORM_X11_KHR, display.as_ptr(), &display_attributes) .unwrap(); (display, Some(Arc::new(library)), WindowKind::X11) - } else if let (Some((display, library)), Some(egl)) = - (angle_x11_display_library, egl.upcast::()) - { + } else if let (Some((display, library)), Some(egl)) = (angle_x11_display_library, egl1_5) { log::info!("Using Angle platform with X11"); let display_attributes = [ EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE as egl::Attrib, @@ -657,6 +671,9 @@ impl crate::Instance for Instance { (display, None, WindowKind::Unknown) }; + #[cfg(feature = "emscripten")] + let display = egl.get_display(egl::DEFAULT_DISPLAY).unwrap(); + if desc.flags.contains(crate::InstanceFlags::VALIDATION) && client_ext_str.contains(&"EGL_KHR_debug") { @@ -698,7 +715,7 @@ impl crate::Instance for Instance { let raw_window_handle = has_handle.raw_window_handle(); - #[cfg_attr(target_os = "android", allow(unused_mut))] + #[cfg_attr(any(target_os = "android", feature = "emscripten"), allow(unused_mut))] let mut inner = self.inner.lock(); match raw_window_handle { @@ -721,6 +738,7 @@ impl crate::Instance for Instance { return Err(crate::InstanceError); } } + #[cfg(not(feature = "emscripten"))] Rwh::Wayland(handle) => { /* Wayland displays are not sharable between surfaces so if the * surface we receive from this handle is from a different @@ -757,6 +775,8 @@ impl crate::Instance for Instance { drop(old_inner); } } + #[cfg(feature = "emscripten")] + Rwh::Web(_) => {} other => { log::error!("Unsupported window: {:?}", other); return Err(crate::InstanceError); @@ -975,6 +995,8 @@ impl crate::Surface for Surface { wl_window = Some(window); window } + #[cfg(feature = "emscripten")] + (WindowKind::Unknown, Rwh::Web(handle)) => handle.id as *mut std::ffi::c_void, (WindowKind::Unknown, Rwh::Win32(handle)) => handle.hwnd, (WindowKind::Unknown, Rwh::AppKit(handle)) => handle.ns_view, _ => { @@ -1014,8 +1036,14 @@ impl crate::Surface for Surface { } attributes.push(egl::ATTRIB_NONE as i32); + #[cfg(not(feature = "emscripten"))] + let egl1_5 = self.egl.instance.upcast::(); + + #[cfg(feature = "emscripten")] + let egl1_5: Option<&Arc> = Some(&self.egl.instance); + // Careful, we can still be in 1.4 version even if `upcast` succeeds - let raw_result = match self.egl.instance.upcast::() { + let raw_result = match egl1_5 { Some(egl) if self.wsi.kind != WindowKind::Unknown => { let attributes_usize = attributes .into_iter() diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 7a89b2bbedb..c48225f6d6d 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -56,9 +56,9 @@ To address this, we invalidate the vertex buffers based on: */ -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] mod egl; -#[cfg(target_arch = "wasm32")] +#[cfg(all(target_arch = "wasm32", not(feature = "emscripten")))] mod web; mod adapter; @@ -67,10 +67,10 @@ mod conv; mod device; mod queue; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] use self::egl::{AdapterContext, Instance, Surface}; -#[cfg(target_arch = "wasm32")] +#[cfg(all(target_arch = "wasm32", not(feature = "emscripten")))] use self::web::{AdapterContext, Instance, Surface}; use arrayvec::ArrayVec; diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index 731ff99185b..e6f9f549f6b 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -1176,10 +1176,10 @@ impl crate::Queue for super::Queue { surface: &mut super::Surface, texture: super::Texture, ) -> Result<(), crate::SurfaceError> { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] let gl = &self.shared.context.get_without_egl_lock(); - #[cfg(target_arch = "wasm32")] + #[cfg(all(target_arch = "wasm32", not(feature = "emscripten")))] let gl = &self.shared.context.glow_context; surface.present(texture, gl) diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index fe69c549614..f7564e4a4b2 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -83,6 +83,7 @@ trace = ["serde", "wgc/trace"] replay = ["serde", "wgc/replay"] angle = ["wgc/angle"] webgl = ["wgc"] +emscripten = ["webgl"] [target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgc] package = "wgpu-core" @@ -102,7 +103,7 @@ package = "wgpu-types" path = "../wgpu-types" version = "0.12" -[target.'cfg(not(target_arch = "wasm32"))'.dependencies.hal] +[target.'cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))'.dependencies.hal] package = "wgpu-hal" path = "../wgpu-hal" version = "0.12" diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index aa1c990d1d7..f7a16e1237b 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -38,7 +38,7 @@ impl fmt::Debug for Context { } impl Context { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn from_hal_instance(hal_instance: A::Instance) -> Self { Self(wgc::hub::Global::from_hal_instance::( "wgpu", @@ -51,7 +51,7 @@ impl Context { &self.0 } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub fn enumerate_adapters(&self, backends: wgt::Backends) -> Vec { self.0 .enumerate_adapters(wgc::instance::AdapterInputs::Mask(backends, |_| { @@ -59,7 +59,7 @@ impl Context { })) } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_adapter_from_hal( &self, hal_adapter: hal::ExposedAdapter, @@ -67,7 +67,7 @@ impl Context { self.0.create_adapter_from_hal(hal_adapter, PhantomData) } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_device_from_hal( &self, adapter: &wgc::id::AdapterId, @@ -94,7 +94,7 @@ impl Context { Ok((device, device_id)) } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_texture_from_hal( &self, hal_texture: A::Texture, @@ -123,7 +123,7 @@ impl Context { } } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn device_as_hal) -> R, R>( &self, device: &Device, @@ -133,7 +133,7 @@ impl Context { .device_as_hal::(device.id, hal_device_callback) } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn texture_as_hal)>( &self, texture: &Texture, @@ -143,7 +143,7 @@ impl Context { .texture_as_hal::(texture.id, hal_texture_callback) } - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub fn generate_report(&self) -> wgc::hub::GlobalReport { self.0.generate_report() } @@ -1528,7 +1528,7 @@ impl crate::Context for Context { #[cfg_attr(target_arch = "wasm32", allow(unused))] fn device_drop(&self, device: &Self::DeviceId) { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] { let global = &self.0; match wgc::gfx_select!(device.id => global.device_poll(device.id, true)) { @@ -1537,7 +1537,7 @@ impl crate::Context for Context { } } //TODO: make this work in general - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] #[cfg(feature = "metal-auto-capture")] { let global = &self.0; diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 76de67b980a..414a68c6c58 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -1431,7 +1431,7 @@ impl Instance { /// # Safety /// /// Refer to the creation of wgpu-hal Instance for every backend. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn from_hal(hal_instance: A::Instance) -> Self { Self { context: Arc::new(C::from_hal_instance::(hal_instance)), @@ -1443,7 +1443,7 @@ impl Instance { /// # Arguments /// /// - `backends` - Backends from which to enumerate adapters. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub fn enumerate_adapters(&self, backends: Backends) -> impl Iterator { let context = Arc::clone(&self.context); self.context @@ -1474,7 +1474,7 @@ impl Instance { /// # Safety /// /// `hal_adapter` must be created from this instance internal handle. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_adapter_from_hal( &self, hal_adapter: hal::ExposedAdapter, @@ -1555,7 +1555,7 @@ impl Instance { } /// Generates memory report. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub fn generate_report(&self) -> wgc::hub::GlobalReport { self.context.generate_report() } @@ -1607,7 +1607,7 @@ impl Adapter { /// /// - `hal_device` must be created from this adapter internal handle. /// - `desc.features` must be a subset of `hal_device` features. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_device_from_hal( &self, hal_device: hal::OpenDevice, @@ -1846,7 +1846,7 @@ impl Device { /// - `hal_texture` must be created from this device internal handle /// - `hal_texture` must be created respecting `desc` /// - `hal_texture` must be initialized - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn create_texture_from_hal( &self, hal_texture: A::Texture, @@ -1910,7 +1910,7 @@ impl Device { /// # Safety /// /// - The raw handle obtained from the hal Device must not be manually destroyed - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn as_hal) -> R, R>( &self, hal_device_callback: F, @@ -2203,7 +2203,7 @@ impl Texture { /// # Safety /// /// - The raw handle obtained from the hal Texture must not be manually destroyed - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub unsafe fn as_hal)>( &self, hal_texture_callback: F,