diff --git a/Cargo.lock b/Cargo.lock index 1a4b364f..664e6068 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "ash" -version = "0.33.3+1.2.191" +version = "0.35.1+1.2.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4f1d82f164f838ae413296d1131aa6fa79b917d25bebaa7033d25620c09219" +checksum = "b7fd04def1c9101b5fb488c131022d2d6f87753ef4b1b11b279e2af404fae6b9" dependencies = [ "libloading", ] @@ -329,8 +329,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "glow" -version = "0.11.1" -source = "git+https://github.com/grovesNL/glow?rev=5851ca6#5851ca65e6b6f4f2c59683245c07de1843c85452" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" dependencies = [ "js-sys", "slotmap", @@ -464,6 +465,7 @@ checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", "libloading", + "pkg-config", ] [[package]] @@ -530,8 +532,7 @@ checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" [[package]] name = "metal" version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" +source = "git+https://github.com/gfx-rs/metal-rs?rev=140c8f4#140c8f4e39001ae154f153ffc767da6c0c9d7f06" dependencies = [ "bitflags", "block", @@ -552,8 +553,8 @@ dependencies = [ [[package]] name = "naga" -version = "0.7.1" -source = "git+https://github.com/gfx-rs/naga?rev=8ffd6ba#8ffd6ba929b4b93c9564f08fe8bb34b23fa72a6f" +version = "0.8.0" +source = "git+https://github.com/gfx-rs/naga?rev=8e2e39e#8e2e39e4d8fa5bbb657c3b170b4f6607d703e284" dependencies = [ "bit-set", "bitflags", @@ -654,6 +655,12 @@ dependencies = [ "indexmap", ] +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + [[package]] name = "png" version = "0.16.8" @@ -956,8 +963,8 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.11.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=ec1d022#ec1d022a75898a3bc4e03589471d0ba7facc066c" +version = "0.12.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=8b66507#8b665073b8c334999626b4c5379a7543840452ae" dependencies = [ "arrayvec", "bitflags", @@ -980,8 +987,8 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "0.11.2" -source = "git+https://github.com/gfx-rs/wgpu?rev=ec1d022#ec1d022a75898a3bc4e03589471d0ba7facc066c" +version = "0.12.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=8b66507#8b665073b8c334999626b4c5379a7543840452ae" dependencies = [ "arrayvec", "ash", @@ -1027,13 +1034,14 @@ dependencies = [ "raw-window-handle", "thiserror", "wgpu-core", + "wgpu-hal", "wgpu-types", ] [[package]] name = "wgpu-types" -version = "0.11.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=ec1d022#ec1d022a75898a3bc4e03589471d0ba7facc066c" +version = "0.12.0" +source = "git+https://github.com/gfx-rs/wgpu?rev=8b66507#8b665073b8c334999626b4c5379a7543840452ae" dependencies = [ "bitflags", "bitflags_serde_shim", diff --git a/Cargo.toml b/Cargo.toml index c910d1dc..0fe53421 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,18 +22,34 @@ default = [] #metal-auto-capture = ["gfx-backend-metal/auto-capture"] #vulkan-portability = ["wgc/gfx-backend-vulkan"] -[dependencies.wgc] +[target.'cfg(not(target_os = "emscripten"))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "ec1d022" +rev = "8b66507" # path = "../wgpu/wgpu-core" #version = "0.11" features = ["raw-window-handle", "trace"] +[target.'cfg(target_os = "emscripten")'.dependencies.wgc] +package = "wgpu-core" +git = "https://github.com/gfx-rs/wgpu" +rev = "8b66507" +# path = "../wgpu/wgpu-core" +#version = "0.11" +features = ["raw-window-handle", "id32"] + +[target.'cfg(target_os = "emscripten")'.dependencies.hal] +package = "wgpu-hal" +git = "https://github.com/gfx-rs/wgpu" +rev = "8b66507" +# path = "../wgpu/wgpu-core" +#version = "0.11" +features = ["emscripten"] + [dependencies.wgt] package = "wgpu-types" git = "https://github.com/gfx-rs/wgpu" -rev = "ec1d022" +rev = "8b66507" # path = "../wgpu/wgpu-types" #version = "0.11" @@ -46,7 +62,7 @@ thiserror = "1" [dependencies.naga] git = "https://github.com/gfx-rs/naga" -rev = "8ffd6ba" +rev = "8e2e39e" features = ["spv-in"] [build-dependencies] diff --git a/Makefile b/Makefile index 3f014172..ba69143e 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,9 @@ lib-native: Cargo.lock Cargo.toml Makefile $(WILDCARD_SOURCE) lib-native-release: Cargo.lock Cargo.toml Makefile $(WILDCARD_SOURCE) cargo build --release $(EXTRA_BUILD_ARGS) +lib-native-emscripten: Cargo.lock Cargo.toml Makefile $(WILDCARD_SOURCE) + EMCC_CFLAGS="-Oz -g -s ERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry -s ASSERTIONS=0" cargo build --target wasm32-unknown-emscripten --release $(EXTRA_BUILD_ARGS) + example-compute: lib-native examples/compute/main.c cd examples/compute && $(CREATE_BUILD_DIR) && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. $(GENERATOR_PLATFORM) && cmake --build . @@ -113,6 +116,9 @@ example-triangle: lib-native examples/triangle/main.c run-example-triangle: example-triangle cd examples/triangle && "$(OUTPUT_DIR)/triangle" +example-triangle-emscripten: lib-native-emscripten examples/triangle/main.c + cd examples/triangle && $(CREATE_BUILD_DIR) && cd build && emcmake cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build . + build-helper: cargo build -p helper diff --git a/examples/compute/shader.wgsl b/examples/compute/shader.wgsl index df541aff..4bcaf40b 100644 --- a/examples/compute/shader.wgsl +++ b/examples/compute/shader.wgsl @@ -1,8 +1,9 @@ struct PrimeIndices { - data: [[stride(4)]] array; + data: @stride(4) array; }; // this is used as both input and output for convenience -[[group(0), binding(0)]] +@group(0) +@binding(0) var v_indices: PrimeIndices; // The Collatz Conjecture states that for any integer n: @@ -34,7 +35,8 @@ fn collatz_iterations(n_base: u32) -> u32{ return i; } -[[stage(compute), workgroup_size(1)]] -fn main([[builtin(global_invocation_id)]] global_id: vec3) { +@stage(compute) +@workgroup_size(1) +fn main(@builtin(global_invocation_id) global_id: vec3) { v_indices.data[global_id.x] = collatz_iterations(v_indices.data[global_id.x]); } diff --git a/examples/triangle/CMakeLists.txt b/examples/triangle/CMakeLists.txt index 298bef23..68aaff9f 100644 --- a/examples/triangle/CMakeLists.txt +++ b/examples/triangle/CMakeLists.txt @@ -6,7 +6,9 @@ set(TARGET_NAME triangle) add_executable(triangle main.c ../framework.c) -if(MSVC) +if(EMSCRIPTEN) + add_definitions(-DWGPU_TARGET=WGPU_TARGET_LINUX_EMSCRIPTEN) +elseif(MSVC) add_definitions(-DWGPU_TARGET=WGPU_TARGET_WINDOWS) target_compile_options(${TARGET_NAME} PRIVATE /W4) set(OS_LIBRARIES "userenv" "ws2_32" "Dwmapi" "dbghelp" "d3dcompiler" "D3D12" "D3D11" "DXGI" "setupapi" "Bcrypt") @@ -23,15 +25,27 @@ endif(USE_WAYLAND) target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra -pedantic) endif(MSVC) -find_package(glfw3 3.3 REQUIRED - HINTS "$ENV{GLFW3_INSTALL_DIR}" -) +if(EMSCRIPTEN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \ + -Oz -g -s USE_GLFW=3") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} \ + -Oz -g -s FULL_ES2=1 \ + -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s MIN_WEBGL_VERSION=2 \ + --preload-file \"${CMAKE_CURRENT_SOURCE_DIR}/shader.wgsl@shader.wgsl\"") + set(WGPU_LIBRARY "wgpu_native") + set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX .html) + target_link_directories(${TARGET_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../target/wasm32-unknown-emscripten/release") +else(EMSCRIPTEN) + find_package(glfw3 3.3 REQUIRED + HINTS "$ENV{GLFW3_INSTALL_DIR}" + ) + find_library(WGPU_LIBRARY wgpu_native + HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug" + ) + target_include_directories(${TARGET_NAME} PUBLIC $ENV{GLFW3_INCLUDE_DIR}) +endif(EMSCRIPTEN) -find_library(WGPU_LIBRARY wgpu_native - HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug" -) - -target_include_directories(${TARGET_NAME} PUBLIC $ENV{GLFW3_INCLUDE_DIR}) target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../ffi) target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../) diff --git a/examples/triangle/main.c b/examples/triangle/main.c index 9ed0233b..133d42be 100644 --- a/examples/triangle/main.c +++ b/examples/triangle/main.c @@ -25,7 +25,9 @@ #elif WGPU_TARGET == WGPU_TARGET_WINDOWS #define GLFW_EXPOSE_NATIVE_WIN32 #endif +#if WGPU_TARGET != WGPU_TARGET_LINUX_EMSCRIPTEN #include +#endif static void handle_device_lost(WGPUDeviceLostReason reason, char const * message, void * userdata) { @@ -45,7 +47,11 @@ int main() { return 1; } +#if WGPU_TARGET == WGPU_TARGET_LINUX_EMSCRIPTEN + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); +#else glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); +#endif GLFWwindow *window = glfwCreateWindow(640, 480, "wgpu with glfw", NULL, NULL); if (!window) { @@ -54,8 +60,16 @@ int main() { } WGPUSurface surface; - -#if WGPU_TARGET == WGPU_TARGET_MACOS +#if WGPU_TARGET == WGPU_TARGET_LINUX_EMSCRIPTEN + { + surface = wgpuInstanceCreateSurface( + NULL, + &(WGPUSurfaceDescriptor){ + .label = NULL, + .nextInChain = NULL, + }); + } +#elif WGPU_TARGET == WGPU_TARGET_MACOS { id metal_layer = NULL; NSWindow *ns_window = glfwGetCocoaWindow(window); @@ -332,6 +346,11 @@ int main() { wgpuSwapChainPresent(swapChain); glfwPollEvents(); + +#if WGPU_TARGET == WGPU_TARGET_LINUX_EMSCRIPTEN + // you must use emscripten_set_main_loop or asyncify + return 0; +#endif } glfwDestroyWindow(window); diff --git a/examples/triangle/shader.wgsl b/examples/triangle/shader.wgsl index 4903d72d..5c95efa7 100644 --- a/examples/triangle/shader.wgsl +++ b/examples/triangle/shader.wgsl @@ -1,11 +1,11 @@ -[[stage(vertex)]] -fn vs_main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4 { +@stage(vertex) +fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { let x = f32(i32(in_vertex_index) - 1); let y = f32(i32(in_vertex_index & 1u) * 2 - 1); return vec4(x, y, 0.0, 1.0); } -[[stage(fragment)]] -fn fs_main() -> [[location(0)]] vec4 { +@stage(fragment) +fn fs_main() -> @location(0) vec4 { return vec4(1.0, 0.0, 0.0, 1.0); } \ No newline at end of file diff --git a/src/conv.rs b/src/conv.rs index b7ce4150..e0c00eca 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -227,7 +227,12 @@ pub fn map_device_descriptor<'a>( } pub fn map_limits(limits: native::WGPULimits) -> wgt::Limits { + #[cfg(target_os = "emscripten")] + let mut wgt_limits = wgt::Limits::downlevel_webgl2_defaults(); + + #[cfg(not(target_os = "emscripten"))] let mut wgt_limits = wgt::Limits::default(); + if limits.maxTextureDimension1D != 0 { wgt_limits.max_texture_dimension_1d = limits.maxTextureDimension1D; } @@ -272,46 +277,42 @@ pub fn map_limits(limits: native::WGPULimits) -> wgt::Limits { if limits.maxStorageBufferBindingSize != 0 { wgt_limits.max_storage_buffer_binding_size = limits.maxStorageBufferBindingSize as u32; } - /* not yet available in wgpu-core if limits.minUniformBufferOffsetAlignment != 0 { - wgt_limits.yyyy = limits.minUniformBufferOffsetAlignment; + wgt_limits.min_uniform_buffer_offset_alignment = limits.minUniformBufferOffsetAlignment; } if limits.minStorageBufferOffsetAlignment != 0 { - wgt_limits.yyyy = limits.minStorageBufferOffsetAlignment; + wgt_limits.min_storage_buffer_offset_alignment = limits.minStorageBufferOffsetAlignment; } - */ if limits.maxVertexBuffers != 0 { wgt_limits.max_vertex_buffers = limits.maxVertexBuffers; } if limits.maxVertexAttributes != 0 { wgt_limits.max_vertex_attributes = limits.maxVertexAttributes; } - /* not yet available in wgpu-core if limits.maxVertexBufferArrayStride != 0 { - wgt_limits.yyyy = limits.maxVertexBufferArrayStride; + wgt_limits.max_vertex_buffer_array_stride = limits.maxVertexBufferArrayStride; } if limits.maxInterStageShaderComponents != 0 { - wgt_limits.yyyy = limits.maxInterStageShaderComponents; + wgt_limits.max_inter_stage_shader_components = limits.maxInterStageShaderComponents; } if limits.maxComputeWorkgroupStorageSize != 0 { - wgt_limits.yyyy = limits.maxComputeWorkgroupStorageSize; + wgt_limits.max_compute_workgroup_storage_size = limits.maxComputeWorkgroupStorageSize; } if limits.maxComputeInvocationsPerWorkgroup != 0 { - wgt_limits.yyyy = limits.maxComputeInvocationsPerWorkgroup; + wgt_limits.max_compute_invocations_per_workgroup = limits.maxComputeInvocationsPerWorkgroup; } if limits.maxComputeWorkgroupSizeX != 0 { - wgt_limits.yyyy = limits.maxComputeWorkgroupSizeX; + wgt_limits.max_compute_workgroup_size_x = limits.maxComputeWorkgroupSizeX; } if limits.maxComputeWorkgroupSizeY != 0 { - wgt_limits.yyyy = limits.maxComputeWorkgroupSizeY; + wgt_limits.max_compute_workgroup_size_y = limits.maxComputeWorkgroupSizeY; } if limits.maxComputeWorkgroupSizeZ != 0 { - wgt_limits.yyyy = limits.maxComputeWorkgroupSizeZ; + wgt_limits.max_compute_workgroup_size_z = limits.maxComputeWorkgroupSizeZ; } if limits.maxComputeWorkgroupsPerDimension != 0 { - wgt_limits.yyyy = limits.maxComputeWorkgroupsPerDimension; + wgt_limits.max_compute_workgroups_per_dimension = limits.maxComputeWorkgroupsPerDimension; } - */ return wgt_limits; } diff --git a/src/lib.rs b/src/lib.rs index 7159ccbf..3bbdf91c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,10 +20,16 @@ pub mod native { type Global = wgc::hub::Global; +#[cfg(not(target_os = "emscripten"))] lazy_static::lazy_static! { static ref GLOBAL: Arc = Arc::new(Global::new("wgpu", wgc::hub::IdentityManagerFactory, wgt::Backends::PRIMARY)); } +#[cfg(target_os = "emscripten")] +lazy_static::lazy_static! { + static ref GLOBAL: Arc = Arc::new(Global::new("wgpu", wgc::hub::IdentityManagerFactory, wgt::Backends::GL)); +} + pub type Label<'a> = Option>; struct OwnedLabel(Option); @@ -276,6 +282,12 @@ unsafe fn map_surface( return wgpu_create_surface(raw_window_handle::RawWindowHandle::AndroidNdk(handle)); } + #[cfg(target_os = "emscripten")] + return wgpu_create_surface(raw_window_handle::RawWindowHandle::Web( + raw_window_handle::WebHandle::empty(), + )); + + #[cfg(not(target_os = "emscripten"))] panic!("Error: Unsupported Surface"); }