Skip to content

Commit

Permalink
t# Это объединение 2 коммитов.
Browse files Browse the repository at this point in the history
feature: emscripten
  • Loading branch information
caiiiycuk committed Jan 26, 2022
1 parent 39a0256 commit ad6d5d9
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 74 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 }}

Expand Down Expand Up @@ -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: |
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions wgpu-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
8 changes: 7 additions & 1 deletion wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 }
Expand All @@ -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" }
Expand Down
16 changes: 16 additions & 0 deletions wgpu-hal/examples/raw-gles.em.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<canvas id="canvas" width="640" height="400"></canvas>
<script>
var Module = {
canvas: document.getElementById("canvas"),
preRun: [function() {ENV.RUST_LOG = "debug"}]
};
</script>
<script src="raw-gles.js"></script>
</body>
</html>
131 changes: 96 additions & 35 deletions wgpu-hal/examples/raw-gles.rs
Original file line number Diff line number Diff line change
@@ -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");

Expand All @@ -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::<std::ffi::c_void>();
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 {
<hal::api::Gles as hal::Api>::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<hal::api::Gles>, width: u32, height: u32) {
use hal::{Adapter as _, CommandEncoder as _, Device as _, Queue as _};

let mut od = unsafe {
exposed
.adapter
Expand Down Expand Up @@ -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,
Expand All @@ -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,
_ => (),
},
_ => (),
}
});
}
Loading

0 comments on commit ad6d5d9

Please sign in to comment.