[emscripten] Compile emdawnwebgpu port with -sSHARED_MEMORY
When linking using -sSHARED_MEMORY (which means the heap is a
SharedArrayBuffer - it's implied by -pthread or other flags),
emdawnwebgpu's webgpu.cpp also needs to be compiled with that flag.
Asides:
- Switch webgpu.cpp to C++20.
- Remove the underscore from lib_emdawnwebgpu -> libemdawnwebgpu, to
make it more consistent with typical library names.
No-Try: true
Fixed: 420406098
Change-Id: I1668295212da03f145bdef5db85c8cf013969df3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/244075
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Auto-Submit: Kai Ninomiya <kainino@chromium.org>
diff --git a/src/emdawnwebgpu/pkg/README.md b/src/emdawnwebgpu/pkg/README.md
index d344c64..0a7af93 100644
--- a/src/emdawnwebgpu/pkg/README.md
+++ b/src/emdawnwebgpu/pkg/README.md
@@ -17,7 +17,7 @@
First, start with either:
-- A "remote" port file `emdawnwebgpu-v*.port.py` (requires Emscripten 4.0.10+).
+- A "remote" port file `emdawnwebgpu-v*.remoteport.py` (requires Emscripten 4.0.10+).
- An `emdawnwebgpu_pkg` containing a local port file `emdawnwebgpu.port.py`.
(Either from a pre-built zip release, or from a Dawn build output directory.)
@@ -26,7 +26,7 @@
Pass the following flag to `emcc`, during both compile and link, to set the
include paths and link the implementation:
- --use-port=path/to/emdawnwebgpu*.port.py
+ --use-port=path/to/emdawnwebgpu_port_or_remoteport_file.py
If (and only if) using Emscripten before 4.0.7, also pass this flag during link:
@@ -37,7 +37,9 @@
Options can be set by appending `:key1=value:key2=value` to `--use-port`.
For information about port options, run:
- emcc --use-port=path/to/emdawnwebgpu*.port.py:help
+ emcc --use-port=emdawnwebgpu:help
+ emcc --use-port=path/to/emdawnwebgpu.port.py:help
+ emcc --use-port=path/to/emdawnwebgpu-*.remoteport.py:help
### C++ bindings
@@ -46,12 +48,14 @@
for any reason (you have custom bindings, you're using a pinned snapshot of
`webgpu_cpp.h`, etc.), you can set the option `cpp_bindings=false`:
- --use-port=path/to/emdawnwebgpu*.port.py:cpp_bindings=false
+ --use-port=emdawnwebgpu:cpp_bindings=false
+ --use-port=path/to/emdawnwebgpu.port.py:cpp_bindings=false
+ --use-port=path/to/emdawnwebgpu-*.remoteport.py:cpp_bindings=false
## Embuilder
If your build process needs a separate step to build the port before linking,
-use Emscripten's `embuilder` (with `opt_level` set explicitly):
+use Emscripten's `embuilder`.
- embuilder build path/to/emdawnwebgpu*.port.py:opt_level=0
- embuilder build path/to/emdawnwebgpu*.port.py:opt_level=2
+Under `embuilder`, some options cannot be set automatically, so they must be
+set manually. See `OPTIONS` in `emdawnwebgpu.port.py` for details.
diff --git a/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py b/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py
index 3af52aa..b80ee18 100644
--- a/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py
+++ b/src/emdawnwebgpu/pkg/emdawnwebgpu.port.py
@@ -36,20 +36,31 @@
LICENSE = "Some files: BSD 3-Clause License. Other files: Emscripten's license (available under both MIT License and University of Illinois/NCSA Open Source License)"
-# User options, e.g. --use-port=path/to/emdawnwebgpu.port.py:cpp_bindings=false
+# User options. (See README.md for how to use these.)
OPTIONS = {
'cpp_bindings':
"Add the include path for Dawn-like <webgpu/webgpu_cpp.h> C++ bindings. Default: true.",
+
+ # The following options are generally not needed, as they are automatically
+ # derived from the linker flags. However, if using embuilder, these must be
+ # used as they are the only way to control these options
+ # (https://github.com/emscripten-core/emscripten/issues/24421). For example:
+ #
+ # embuilder build path/to/port/file.py:opt_level=2:shared_memory=true
'opt_level':
"Optimization (-O) level for the bindings' Wasm layer. Default: choose based on -sASSERTIONS.",
+ 'shared_memory':
+ "Enable -sSHARED_MEMORY. Default: choose based on whether linker has -sSHARED_MEMORY enabled.",
}
_VALID_OPTION_VALUES = {
'cpp_bindings': ['true', 'false'],
'opt_level': ['auto', '0', '2'],
+ 'shared_memory': ['auto', 'true', 'false'],
}
-_opts: Dict[str, Union[Optional[str], bool]] = {
- 'cpp_bindings': True,
+_opts: Dict[str, Optional[str]] = {
+ 'cpp_bindings': 'true',
'opt_level': 'auto',
+ 'shared_memory': 'auto',
}
@@ -91,8 +102,6 @@
error_handler(
f'[{option}] can be {list(_VALID_OPTION_VALUES[option])}, got [{value}]'
)
- if isinstance(_opts[option], bool):
- value = value == 'true'
return value
@@ -106,34 +115,44 @@
# It's important that these take precedent over Emscripten's builtin
# system/include/, which also currently has webgpu headers.
args = ['-isystem', _c_include_dir]
- if _opts['cpp_bindings']:
+ if _opts['cpp_bindings'] == 'true':
args += ['-isystem', _cpp_include_dir]
return args
# Hooks that affect linker invocations
-
-# If not explicitly set, use -O0 when linking with -sASSERTIONS builds, and -O2
-# otherwise. (ASSERTIONS implicitly affects library_webgpu.js, so it makes sense
-# for it to control this too - debuggability is most useful with assertions.)
-# Emscripten automatically handles necessary compile flags (LTO, PIC, wasm64).
-def _compute_opt_level_flag(settings):
- value = _opts['opt_level']
- if value == 'auto':
- value = '0' if settings.ASSERTIONS else '2'
- return f'-O{value}'
-
-
-# Compute the library compile flags, either `-O0` or `-O2 -DNDEBUG` (see above).
-# NDEBUG affects <assert.h> and is used in `webgpu.cpp`.
def _compute_library_compile_flags(settings):
- opt_level_flag = _compute_opt_level_flag(settings)
- flags = [opt_level_flag]
+ # Emscripten automatically handles many necessary compile flags (LTO, PIC,
+ # wasm64). The ones it does not handle are handled below.
+ lib_name_suffix = ''
+ flags = []
+
+ # If not explicitly set, use -O0 when linking with -sASSERTIONS builds, and
+ # -O2 otherwise. (ASSERTIONS implicitly affects library_webgpu.js, so it
+ # makes sense for it to control this too - debuggability is most useful with
+ # assertions.)
+ opt_level = _opts['opt_level']
+ if opt_level == 'auto':
+ opt_level = '0' if settings.ASSERTIONS else '2'
+ lib_name_suffix += f'-O{opt_level}'
+ flags.append(f'-O{opt_level}')
# Set NDEBUG if -O0 (similar to emcc's defaulting of -sASSERTIONS from -O).
- if opt_level_flag != '-O0':
+ if opt_level != '0':
flags.append('-DNDEBUG')
- return flags
+
+ # If not explicitly set, inherit -sSHARED_MEMORY from the linker invocation.
+ # This affects how std::atomic<> is compiled. (It may be fine to link a
+ # -sSHARED_MEMORY=1 object into a -sSHARED_MEMORY=0 executable, but it still
+ # emits unnecessary atomic operations, so we prefer not to do that.)
+ shared_memory = _opts['shared_memory']
+ if shared_memory == 'auto':
+ shared_memory = 'true' if settings.SHARED_MEMORY else 'false'
+ if shared_memory == 'true':
+ lib_name_suffix += '-shared_memory'
+ flags.append('-sSHARED_MEMORY')
+
+ return (lib_name_suffix, flags)
# Create a unique lib name for this version of the port and compile flags.
@@ -149,8 +168,8 @@
for filename in _files_affecting_port_build:
add(open(filename, 'rb').read())
- opt_level_flag = _compute_opt_level_flag(settings)
- return f'lib_emdawnwebgpu-{hash_value:08x}{opt_level_flag}.a'
+ (lib_name_suffix, _) = _compute_library_compile_flags(settings)
+ return f'libemdawnwebgpu-{hash_value:08x}{lib_name_suffix}.a'
def linker_setup(ports, settings):
@@ -184,8 +203,8 @@
# compiled webgpu.cpp (which also includes webgpu/webgpu.h).
includes = [_c_include_dir]
# Always use -g. The linker can remove debug symbols in release builds.
- flags = ['-g', '-std=c++17', '-fno-exceptions']
- flags += _compute_library_compile_flags(settings)
+ (_, flags) = _compute_library_compile_flags(settings)
+ flags += ['-g', '-std=c++20', '-fno-exceptions']
# IMPORTANT: Keep `_files_affecting_port_build` in sync with this.
ports.build_port(_src_dir,