From af5f4d20f4821e9cde185a31680d824f50731d4a Mon Sep 17 00:00:00 2001 From: Red Artist Date: Wed, 22 Feb 2023 11:46:14 +0530 Subject: [PATCH] enable debug extension on emscripten (#3519) * enable debug extension on emscripten * update changelog * extract emscripten stuff into a separate module * use unmasked queries on w-u-u, and only enable extension on emscripten * fix docs --- CHANGELOG.md | 1 + wgpu-hal/src/gles/adapter.rs | 11 +++++++++++ wgpu-hal/src/gles/emscripten.rs | 26 ++++++++++++++++++++++++++ wgpu-hal/src/gles/mod.rs | 2 ++ 4 files changed, 40 insertions(+) create mode 100644 wgpu-hal/src/gles/emscripten.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 843903cddc..356bc2d80c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,7 @@ By @teoxoy in [#3436](https://github.com/gfx-rs/wgpu/pull/3436) #### GLES - [gles] fix: Set FORCE_POINT_SIZE if it is vertex shader with mesh consist of point list. By @REASY in [3440](https://github.com/gfx-rs/wgpu/pull/3440) +- [gles] fix: enable `WEBGL_debug_renderer_info` before querying unmasked vendor/renderer to avoid crashing on emscripten in [#3519](https://github.com/gfx-rs/wgpu/pull/3519) #### General diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 669e9a5499..15436d68f8 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -186,10 +186,21 @@ impl super::Adapter { let extensions = gl.supported_extensions(); let (vendor_const, renderer_const) = if extensions.contains("WEBGL_debug_renderer_info") { + // emscripten doesn't enable "WEBGL_debug_renderer_info" extension by default. so, we do it manually. + // See https://github.com/gfx-rs/wgpu/issues/3245 for context + #[cfg(target_os = "emscripten")] + if unsafe { super::emscripten::enable_extension("WEBGL_debug_renderer_info\0") } { + (GL_UNMASKED_VENDOR_WEBGL, GL_UNMASKED_RENDERER_WEBGL) + } else { + (glow::VENDOR, glow::RENDERER) + } + // glow already enables WEBGL_debug_renderer_info on wasm32-unknown-unknown target by default. + #[cfg(not(target_os = "emscripten"))] (GL_UNMASKED_VENDOR_WEBGL, GL_UNMASKED_RENDERER_WEBGL) } else { (glow::VENDOR, glow::RENDERER) }; + let (vendor, renderer) = { let vendor = unsafe { gl.get_parameter_string(vendor_const) }; let renderer = unsafe { gl.get_parameter_string(renderer_const) }; diff --git a/wgpu-hal/src/gles/emscripten.rs b/wgpu-hal/src/gles/emscripten.rs new file mode 100644 index 0000000000..7372dbd369 --- /dev/null +++ b/wgpu-hal/src/gles/emscripten.rs @@ -0,0 +1,26 @@ +extern "C" { + /// returns 1 if success. 0 if failure. extension name must be null terminated + fn emscripten_webgl_enable_extension( + context: std::ffi::c_int, + extension: *const std::ffi::c_char, + ) -> std::ffi::c_int; + fn emscripten_webgl_get_current_context() -> std::ffi::c_int; +} +/// Webgl requires extensions to be enabled before using them. +/// This function can be used to enable webgl extension on emscripten target. +/// +/// returns true on success +/// +/// # Safety: +/// +/// - opengl context MUST BE current +/// - extension_name_null_terminated argument must be a valid string with null terminator. +/// - extension must be present. check `glow_context.supported_extensions()` +pub unsafe fn enable_extension(extension_name_null_terminated: &str) -> bool { + unsafe { + emscripten_webgl_enable_extension( + emscripten_webgl_get_current_context(), + extension_name_null_terminated.as_ptr() as _, + ) == 1 + } +} diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 278b707dc7..d196b8bc46 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -59,6 +59,8 @@ To address this, we invalidate the vertex buffers based on: ///cbindgen:ignore #[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))] mod egl; +#[cfg(target_os = "emscripten")] +mod emscripten; #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] mod web;