Skip to content

Commit 5ba53ca

Browse files
committed
Split PoC smoke and add clang probe
1 parent 87df960 commit 5ba53ca

7 files changed

Lines changed: 755 additions & 379 deletions

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ Why we use a fork:
4747
- Current patch scope is focused on lavapipe build behavior for Emscripten so the driver can be consumed in our wasm flow.
4848
- Non-Emscripten paths remain unchanged.
4949

50+
## Shader toolchain direction
51+
52+
Why not LLVM JIT-in-Wasm right now:
53+
- LLVM maintainer discussion: `https://discourse.llvm.org/t/rfc-building-llvm-for-webassembly/79073`
54+
- In this project setup, a production-grade in-process LLVM JIT path inside the Wasm sandbox is not currently a practical path.
55+
56+
Why not full NIR->Wasm backend today:
57+
- Mesa does not ship a complete NIR->Wasm backend for this use case.
58+
- We built a simple proof-of-concept for a minimal pattern, but a full backend from scratch is a large compiler project and not realistic for a single maintainer effort.
59+
60+
Current strategy:
61+
- Keep `clang_wasm_runtime_smoke` as a clang-in-wasm toolchain proof path.
62+
- Keep Vulkan runtime validation on the current Mesa wasm execution path, while preparing a future direct integration path.
63+
5064
## Default dependency mode
5165

5266
Default configuration uses the latest prebuilt LLVM bundle from this repository:
@@ -103,6 +117,14 @@ It validates:
103117

104118
This gives a realistic loader flow for consumers that use Volk, while keeping dispatch pinned to the wasm ICD path.
105119

120+
`smoke_poc_nir_to_wasm` is kept as an experimental proof-of-concept path and is not the main production direction.
121+
122+
Current shader-path split:
123+
- `lavapipe_runtime_smoke` validates Vulkan compute dispatch in the Mesa wasm driver.
124+
- `clang_wasm_runtime_smoke` validates the clang-in-wasm toolchain path and reports `spirv_probe` status.
125+
- Current `clang/clang` runtime package does not include `llvm-spirv`, so direct clang-in-wasm -> SPIR-V for Vulkan shaders is currently unavailable in this smoke.
126+
- `smoke_poc_nir_to_wasm` is a separate experimental check and is not part of `runtime_smoke`.
127+
106128
## Release channels
107129

108130
- `llvm-wasm-prebuilt-latest` contains only the LLVM prebuilt bundle

tests/BootstrapWasmer.cmake

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
cmake_minimum_required(VERSION 4.2)
2+
3+
if(WIN32)
4+
find_program(_WEBVULKAN_POWERSHELL_EXE NAMES pwsh powershell REQUIRED)
5+
execute_process(
6+
COMMAND "${_WEBVULKAN_POWERSHELL_EXE}" -NoProfile -ExecutionPolicy Bypass -Command "$ProgressPreference='SilentlyContinue'; iwr https://win.wasmer.io -useb | iex"
7+
RESULT_VARIABLE _WEBVULKAN_BOOTSTRAP_RESULT
8+
)
9+
else()
10+
find_program(_WEBVULKAN_SH_EXE NAMES sh REQUIRED)
11+
execute_process(
12+
COMMAND "${_WEBVULKAN_SH_EXE}" -c "curl -sSfL https://get.wasmer.io | sh"
13+
RESULT_VARIABLE _WEBVULKAN_BOOTSTRAP_RESULT
14+
)
15+
endif()
16+
17+
if(NOT _WEBVULKAN_BOOTSTRAP_RESULT EQUAL 0)
18+
message(FATAL_ERROR "Unable to install wasmer")
19+
endif()

tests/CMakeLists.txt

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
44
project(webvulkan_tests LANGUAGES NONE)
55
endif()
66

7+
if(NOT DEFINED WASM_AUTO_FETCH_TOOLS)
8+
set(WASM_AUTO_FETCH_TOOLS ON CACHE BOOL "Auto-download missing tools during configure")
9+
endif()
10+
711
set(WEBVULKAN_TEST_THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../.3rdparty/tests" CACHE PATH "Test-only third-party root directory")
812
set(WEBVULKAN_THIRDPARTY_STATE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.3rdparty/.state" CACHE PATH "State directory for fetched third-party metadata")
913
set(WEBVULKAN_VOLK_GIT_URL "https://github.com/zeux/volk.git" CACHE STRING "volk git repository URL for smoke tests")
@@ -14,6 +18,8 @@ set(WEBVULKAN_TEST_MODE "auto" CACHE STRING "Test mode: auto, in-tree, or packag
1418
set_property(CACHE WEBVULKAN_TEST_MODE PROPERTY STRINGS auto in-tree package)
1519
set(WEBVULKAN_TEST_PACKAGE_PREFIX "" CACHE PATH "Install prefix for WebVulkan package mode")
1620
set(WEBVULKAN_TEST_WASM_BUILD_DIR "${CMAKE_BINARY_DIR}/wasm" CACHE PATH "WASM smoke build directory")
21+
set(WEBVULKAN_TEST_NODE_BIN "" CACHE FILEPATH "Path to node executable used by runtime smoke scripts")
22+
set(WEBVULKAN_WASMER_BIN "" CACHE FILEPATH "Path to wasmer executable used by clang wasm runtime smoke")
1723

1824
if(NOT COMMAND CPMAddPackage)
1925
if(NOT DEFINED WEBVULKAN_CPM_VERSION OR WEBVULKAN_CPM_VERSION STREQUAL "")
@@ -103,6 +109,87 @@ if(NOT SUBBUILD_GENERATOR)
103109
message(FATAL_ERROR "No CMake generator is available for wasm smoke sub-build")
104110
endif()
105111

112+
set(_webvulkan_node_hints)
113+
file(GLOB _webvulkan_node_candidates
114+
"${EMSDK_ROOT}/node/*/bin/node"
115+
"${EMSDK_ROOT}/node/*/bin/node.exe"
116+
)
117+
if(_webvulkan_node_candidates)
118+
list(SORT _webvulkan_node_candidates COMPARE NATURAL ORDER DESCENDING)
119+
list(GET _webvulkan_node_candidates 0 _webvulkan_emsdk_node_exe)
120+
get_filename_component(_webvulkan_emsdk_node_dir "${_webvulkan_emsdk_node_exe}" DIRECTORY)
121+
list(APPEND _webvulkan_node_hints "${_webvulkan_emsdk_node_dir}")
122+
endif()
123+
if(CMAKE_HOST_WIN32)
124+
if(DEFINED ENV{ProgramFiles} AND NOT "$ENV{ProgramFiles}" STREQUAL "")
125+
list(APPEND _webvulkan_node_hints "$ENV{ProgramFiles}/nodejs")
126+
endif()
127+
if(DEFINED ENV{ProgramW6432} AND NOT "$ENV{ProgramW6432}" STREQUAL "")
128+
list(APPEND _webvulkan_node_hints "$ENV{ProgramW6432}/nodejs")
129+
endif()
130+
if(DEFINED ENV{LOCALAPPDATA} AND NOT "$ENV{LOCALAPPDATA}" STREQUAL "")
131+
list(APPEND _webvulkan_node_hints "$ENV{LOCALAPPDATA}/Programs/nodejs")
132+
endif()
133+
endif()
134+
135+
if(NOT WEBVULKAN_TEST_NODE_BIN OR WEBVULKAN_TEST_NODE_BIN MATCHES "-NOTFOUND$")
136+
unset(WEBVULKAN_TEST_NODE_BIN CACHE)
137+
find_program(WEBVULKAN_TEST_NODE_BIN NAMES node node.exe nodejs nodejs.exe HINTS ${_webvulkan_node_hints})
138+
endif()
139+
if(NOT WEBVULKAN_TEST_NODE_BIN OR NOT EXISTS "${WEBVULKAN_TEST_NODE_BIN}")
140+
message(FATAL_ERROR "node executable is required for runtime smoke scripts")
141+
endif()
142+
set(WEBVULKAN_TEST_NODE_BIN "${WEBVULKAN_TEST_NODE_BIN}" CACHE FILEPATH "Path to node executable used by runtime smoke scripts" FORCE)
143+
144+
set(_webvulkan_home_dir "")
145+
if(WIN32 AND DEFINED ENV{USERPROFILE} AND NOT "$ENV{USERPROFILE}" STREQUAL "")
146+
set(_webvulkan_home_dir "$ENV{USERPROFILE}")
147+
elseif(DEFINED ENV{HOME} AND NOT "$ENV{HOME}" STREQUAL "")
148+
set(_webvulkan_home_dir "$ENV{HOME}")
149+
endif()
150+
151+
set(_webvulkan_wasmer_hints)
152+
if(_webvulkan_home_dir)
153+
list(APPEND _webvulkan_wasmer_hints "${_webvulkan_home_dir}/.wasmer/bin")
154+
endif()
155+
if(WIN32)
156+
list(APPEND _webvulkan_wasmer_hints
157+
"C:/Program Files/Wasmer/bin"
158+
"C:/Program Files (x86)/Wasmer/bin"
159+
)
160+
endif()
161+
162+
if(NOT WEBVULKAN_WASMER_BIN OR WEBVULKAN_WASMER_BIN MATCHES "-NOTFOUND$")
163+
unset(WEBVULKAN_WASMER_BIN CACHE)
164+
find_program(WEBVULKAN_WASMER_BIN NAMES wasmer wasmer.exe HINTS ${_webvulkan_wasmer_hints})
165+
endif()
166+
if((NOT WEBVULKAN_WASMER_BIN OR NOT EXISTS "${WEBVULKAN_WASMER_BIN}") AND _webvulkan_home_dir)
167+
if(CMAKE_HOST_WIN32)
168+
set(_webvulkan_wasmer_default "${_webvulkan_home_dir}/.wasmer/bin/wasmer.exe")
169+
else()
170+
set(_webvulkan_wasmer_default "${_webvulkan_home_dir}/.wasmer/bin/wasmer")
171+
endif()
172+
if(EXISTS "${_webvulkan_wasmer_default}")
173+
set(WEBVULKAN_WASMER_BIN "${_webvulkan_wasmer_default}")
174+
endif()
175+
endif()
176+
177+
if((NOT WEBVULKAN_WASMER_BIN OR NOT EXISTS "${WEBVULKAN_WASMER_BIN}") AND WASM_AUTO_FETCH_TOOLS)
178+
execute_process(
179+
COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/BootstrapWasmer.cmake"
180+
RESULT_VARIABLE _webvulkan_bootstrap_wasmer_result
181+
)
182+
if(NOT _webvulkan_bootstrap_wasmer_result EQUAL 0)
183+
message(FATAL_ERROR "Failed to bootstrap wasmer runtime")
184+
endif()
185+
find_program(WEBVULKAN_WASMER_BIN NAMES wasmer wasmer.exe HINTS ${_webvulkan_wasmer_hints})
186+
endif()
187+
188+
if(NOT WEBVULKAN_WASMER_BIN OR NOT EXISTS "${WEBVULKAN_WASMER_BIN}")
189+
message(FATAL_ERROR "wasmer executable is required for clang wasm runtime smoke")
190+
endif()
191+
set(WEBVULKAN_WASMER_BIN "${WEBVULKAN_WASMER_BIN}" CACHE FILEPATH "Path to wasmer executable used by clang wasm runtime smoke" FORCE)
192+
106193
if(NOT COMMAND webvulkan_fetch_git_source)
107194
set(_webvulkan_root_fetch_sources "${CMAKE_CURRENT_LIST_DIR}/../cmake/FetchWebVulkanSources.cmake")
108195
if(EXISTS "${_webvulkan_root_fetch_sources}")
@@ -208,6 +295,7 @@ add_custom_command(
208295
-DSMOKE_INCLUDE_DIRS_SERIALIZED=${_webvulkan_smoke_include_dirs_serialized}
209296
-DSMOKE_SOURCE=${CMAKE_CURRENT_LIST_DIR}/wasm/src/lavapipe_runtime_smoke.c
210297
-DSMOKE_JS_OUT=${WEBVULKAN_LAVAPIPE_SMOKE_JS}
298+
-DSMOKE_EXPORT=_lavapipe_runtime_smoke
211299
-DSMOKE_SCRIPT=${CMAKE_CURRENT_LIST_DIR}/wasm/tools/smoke_runtime.mjs
212300
-DVOLK_INCLUDE_DIR=${_webvulkan_volk_include_dir}
213301
-DVOLK_SOURCE=${_webvulkan_volk_source}
@@ -219,5 +307,53 @@ add_custom_command(
219307
)
220308
add_custom_target(lavapipe_runtime_smoke DEPENDS "${WEBVULKAN_LAVAPIPE_SMOKE_OK}")
221309

310+
set(WEBVULKAN_POC_NIR_TO_WASM_SMOKE_OK "${CMAKE_BINARY_DIR}/poc_nir_to_wasm_smoke.ok")
311+
set(WEBVULKAN_POC_NIR_TO_WASM_SMOKE_JS "${CMAKE_BINARY_DIR}/lavapipe-smoke/poc_nir_to_wasm_smoke.js")
312+
set(_webvulkan_poc_nir_to_wasm_depends
313+
"${CMAKE_CURRENT_LIST_DIR}/RunLavapipeRuntimeSmoke.cmake"
314+
"${CMAKE_CURRENT_LIST_DIR}/wasm/src/poc_nir_to_wasm_smoke.c"
315+
"${CMAKE_CURRENT_LIST_DIR}/wasm/tools/smoke_runtime.mjs"
316+
"${_webvulkan_volk_source}"
317+
"${_webvulkan_volk_header}"
318+
"${_webvulkan_driver_archive}"
319+
)
320+
if(_webvulkan_test_mode STREQUAL "in-tree")
321+
list(APPEND _webvulkan_poc_nir_to_wasm_depends llvmpipe_wasm_spike)
322+
endif()
323+
add_custom_command(
324+
OUTPUT "${WEBVULKAN_POC_NIR_TO_WASM_SMOKE_OK}"
325+
COMMAND
326+
"${CMAKE_COMMAND}"
327+
-DEMSDK_ROOT=${EMSDK_ROOT}
328+
-DDRIVER_ARCHIVE=${_webvulkan_driver_archive}
329+
-DSMOKE_INCLUDE_DIRS_SERIALIZED=${_webvulkan_smoke_include_dirs_serialized}
330+
-DSMOKE_SOURCE=${CMAKE_CURRENT_LIST_DIR}/wasm/src/poc_nir_to_wasm_smoke.c
331+
-DSMOKE_JS_OUT=${WEBVULKAN_POC_NIR_TO_WASM_SMOKE_JS}
332+
-DSMOKE_EXPORT=_poc_nir_to_wasm_smoke
333+
-DSMOKE_SCRIPT=${CMAKE_CURRENT_LIST_DIR}/wasm/tools/smoke_runtime.mjs
334+
-DVOLK_INCLUDE_DIR=${_webvulkan_volk_include_dir}
335+
-DVOLK_SOURCE=${_webvulkan_volk_source}
336+
-P "${CMAKE_CURRENT_LIST_DIR}/RunLavapipeRuntimeSmoke.cmake"
337+
COMMAND "${CMAKE_COMMAND}" -E touch "${WEBVULKAN_POC_NIR_TO_WASM_SMOKE_OK}"
338+
DEPENDS ${_webvulkan_poc_nir_to_wasm_depends}
339+
USES_TERMINAL
340+
VERBATIM
341+
)
342+
add_custom_target(smoke_poc_nir_to_wasm DEPENDS "${WEBVULKAN_POC_NIR_TO_WASM_SMOKE_OK}")
343+
344+
set(WEBVULKAN_CLANG_WASM_SMOKE_OK "${CMAKE_BINARY_DIR}/clang_wasm_runtime_smoke.ok")
345+
add_custom_command(
346+
OUTPUT "${WEBVULKAN_CLANG_WASM_SMOKE_OK}"
347+
COMMAND
348+
"${CMAKE_COMMAND}" -E env
349+
"WEBVULKAN_WASMER_BIN=${WEBVULKAN_WASMER_BIN}"
350+
"${WEBVULKAN_TEST_NODE_BIN}" "${CMAKE_CURRENT_LIST_DIR}/wasm/tools/clang_wasm_runtime_smoke.mjs"
351+
COMMAND "${CMAKE_COMMAND}" -E touch "${WEBVULKAN_CLANG_WASM_SMOKE_OK}"
352+
DEPENDS "${CMAKE_CURRENT_LIST_DIR}/wasm/tools/clang_wasm_runtime_smoke.mjs"
353+
USES_TERMINAL
354+
VERBATIM
355+
)
356+
add_custom_target(clang_wasm_runtime_smoke DEPENDS "${WEBVULKAN_CLANG_WASM_SMOKE_OK}")
357+
222358
add_custom_target(runtime_smoke)
223-
add_dependencies(runtime_smoke wasm_runtime_smoke lavapipe_runtime_smoke)
359+
add_dependencies(runtime_smoke wasm_runtime_smoke lavapipe_runtime_smoke clang_wasm_runtime_smoke)

tests/RunLavapipeRuntimeSmoke.cmake

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ require_var(SMOKE_JS_OUT)
1313
require_var(SMOKE_SCRIPT)
1414
require_var(VOLK_INCLUDE_DIR)
1515
require_var(VOLK_SOURCE)
16+
if(NOT DEFINED SMOKE_EXPORT OR "${SMOKE_EXPORT}" STREQUAL "")
17+
set(SMOKE_EXPORT "_lavapipe_runtime_smoke")
18+
endif()
1619

1720
if(DEFINED SMOKE_INCLUDE_DIRS_SERIALIZED AND NOT "${SMOKE_INCLUDE_DIRS_SERIALIZED}" STREQUAL "")
1821
string(REPLACE "|" ";" SMOKE_INCLUDE_DIRS "${SMOKE_INCLUDE_DIRS_SERIALIZED}")
@@ -73,7 +76,7 @@ append_rsp("-sALLOW_MEMORY_GROWTH=1")
7376
append_rsp("-sMODULARIZE=1")
7477
append_rsp("-sEXPORT_ES6=1")
7578
append_rsp("-sENVIRONMENT=web,worker,node")
76-
append_rsp("-sEXPORTED_FUNCTIONS=['_main','_lavapipe_runtime_smoke']")
79+
append_rsp("-sEXPORTED_FUNCTIONS=['_main','${SMOKE_EXPORT}']")
7780
append_rsp("-sEXPORTED_RUNTIME_METHODS=['ccall']")
7881
append_rsp("-sMAIN_MODULE=2")
7982
append_rsp("-sALLOW_TABLE_GROWTH=1")
@@ -94,7 +97,7 @@ endif()
9497
execute_process(
9598
COMMAND "${CMAKE_COMMAND}" -E env
9699
"SMOKE_MODULE=${SMOKE_JS_OUT}"
97-
"SMOKE_EXPORT=_lavapipe_runtime_smoke"
100+
"SMOKE_EXPORT=${SMOKE_EXPORT}"
98101
"${NODE_EXE}" "${SMOKE_SCRIPT}"
99102
RESULT_VARIABLE SMOKE_RUN_RESULT
100103
)

0 commit comments

Comments
 (0)