Add TINYUSDZ_WASM_COROUTINE cmake option for C++20 coroutine async loading

- Add CMake option TINYUSDZ_WASM_COROUTINE (default OFF) to enable/disable
  C++20 coroutine-based async loading
- Add TINYUSDZ_USE_COROUTINE compile definition for conditional compilation
- Wrap coroutine helper functions (yieldToEventLoop, reportAsyncPhaseStart)
  with #if defined(TINYUSDZ_USE_COROUTINE)
- Wrap loadFromBinaryAsync method with #if defined(TINYUSDZ_USE_COROUTINE)
- Wrap EMSCRIPTEN_BINDINGS registration with same guard

To enable coroutine support:
  cmake .. -DTINYUSDZ_WASM_COROUTINE=ON

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Syoyo Fujita
2026-01-07 00:32:52 +09:00
parent 9d58ccc7ed
commit c66a71428e
2 changed files with 22 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ option(TINYUSDZ_WASM64 "Use wasm64(memory64). Available only for Chrome and Fire
option(TINYUSDZ_WASM_DEBUG "Enable WASM debug mode with source maps and assertions" OFF)
option(TINYUSDZ_WASM_SIMD "Enable WebAssembly SIMD (128-bit, widely supported since 2021)" ON)
option(TINYUSDZ_WASM_RELAXED_SIMD "Enable WebAssembly Relaxed SIMD (requires recent browsers)" OFF)
option(TINYUSDZ_WASM_COROUTINE "Enable C++20 coroutine-based async loading (allows browser repaint during loading)" OFF)
if (TINYUSDZ_WASM64)
set(BUILD_TARGET "tinyusdz_64")
@@ -117,6 +118,12 @@ if (TINYUSDZ_WITH_EXR)
target_compile_definitions(${BUILD_TARGET} PRIVATE TINYUSDZ_WITH_EXR=1)
endif()
# C++20 coroutine support for async loading
if (TINYUSDZ_WASM_COROUTINE)
message(STATUS "TinyUSDZ WASM: C++20 coroutine async loading enabled")
target_compile_definitions(${BUILD_TARGET} PRIVATE TINYUSDZ_USE_COROUTINE=1)
endif()
# tinyusdz dir
target_include_directories(${BUILD_TARGET}
PRIVATE "${PROJECT_SOURCE_DIR}/../src/")
@@ -203,6 +210,7 @@ endif()
# Export HEAPU8 for zero-copy streaming transfer from JS to WASM
string(APPEND TINYUSDZ_EMCC_LINK_FLAGS " -sEXPORTED_RUNTIME_METHODS=['HEAPU8']")
message(STATUS ${TINYUSDZ_EMCC_LINK_FLAGS})
set_target_properties(${BUILD_TARGET} PROPERTIES LINK_FLAGS "${TINYUSDZ_EMCC_LINK_FLAGS}")

View File

@@ -116,6 +116,11 @@ EM_JS(void, reportTydraComplete, (int meshCount, int materialCount, int textureC
// ============================================================================
// This allows the browser to repaint between processing phases.
// Returns a Promise that resolves on the next animation frame.
//
// Enable with CMake option: -DTINYUSDZ_WASM_COROUTINE=ON (default)
// Disable with: -DTINYUSDZ_WASM_COROUTINE=OFF
#if defined(TINYUSDZ_USE_COROUTINE)
EM_JS(emscripten::EM_VAL, yieldToEventLoop_impl, (), {
// Return a Promise that resolves on next animation frame
@@ -156,6 +161,8 @@ EM_JS(void, reportAsyncPhaseStart, (const char* phase, float progress), {
}
});
#endif // TINYUSDZ_USE_COROUTINE
namespace detail {
std::array<double, 9> toArray(const tinyusdz::value::matrix3d &m) {
@@ -1271,8 +1278,12 @@ class TinyUSDZLoaderNative {
// This method uses C++20 coroutines to yield to the JavaScript event loop
// between processing phases, allowing the browser to repaint during loading.
//
// Enable with CMake option: -DTINYUSDZ_WASM_COROUTINE=ON (default)
// Disable with: -DTINYUSDZ_WASM_COROUTINE=OFF
//
// Returns a Promise that resolves to a JS object: { success: bool, error?: string }
//
#if defined(TINYUSDZ_USE_COROUTINE)
emscripten::val loadFromBinaryAsync(std::string binary, std::string filename) {
// IMPORTANT: Parameters are passed by VALUE (not by reference) to ensure
// data remains valid across co_await suspension points. References would
@@ -1339,6 +1350,7 @@ class TinyUSDZLoaderNative {
result.set("textureCount", static_cast<int>(render_scene_.textures.size()));
co_return result;
}
#endif // TINYUSDZ_USE_COROUTINE
// u8 : Uint8Array object.
bool loadTest(const std::string &filename, const emscripten::val &u8) {
@@ -4493,7 +4505,9 @@ EMSCRIPTEN_BINDINGS(tinyusdz_module) {
#endif
.function("loadAsLayerFromBinary", &TinyUSDZLoaderNative::loadAsLayerFromBinary)
.function("loadFromBinary", &TinyUSDZLoaderNative::loadFromBinary)
#if defined(TINYUSDZ_USE_COROUTINE)
.function("loadFromBinaryAsync", &TinyUSDZLoaderNative::loadFromBinaryAsync) // C++20 coroutine async version
#endif
.function("loadTest", &TinyUSDZLoaderNative::loadTest)
.function("loadFromCachedAsset", &TinyUSDZLoaderNative::loadFromCachedAsset)
.function("loadAsLayerFromCachedAsset", &TinyUSDZLoaderNative::loadAsLayerFromCachedAsset)