Skip to content

Commit 6c8a4d1

Browse files
committed
Integrate volk runtime smoke path
1 parent 4f4427e commit 6c8a4d1

4 files changed

Lines changed: 100 additions & 17 deletions

File tree

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ add_executable(my_app src/main.c)
7878
target_link_libraries(my_app PRIVATE webvulkan::llvmpipe_wasm)
7979
```
8080

81+
## Volk smoke path
82+
83+
`runtime_smoke` includes a dedicated Volk-based runtime check.
84+
85+
It validates:
86+
- `volkInitializeCustom` is used with `vk_icdGetInstanceProcAddr` from the linked wasm driver archive
87+
- Vulkan instance creation and physical device enumeration succeed
88+
- Required ICD entrypoints are resolved through that same dispatch path
89+
90+
This gives a realistic loader flow for consumers that use Volk, while keeping dispatch pinned to the wasm ICD path.
91+
8192
## Release channels
8293

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

tests/CMakeLists.txt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,37 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
44
project(webvulkan_tests LANGUAGES NONE)
55
endif()
66

7+
set(WEBVULKAN_TEST_THIRDPARTY_DIR "${CMAKE_CURRENT_LIST_DIR}/../.3rdparty/tests" CACHE PATH "Test-only third-party root directory")
8+
set(WEBVULKAN_VOLK_GIT_URL "https://github.com/zeux/volk.git" CACHE STRING "volk git repository URL for smoke tests")
9+
set(WEBVULKAN_VOLK_GIT_REF "1.4.304" CACHE STRING "Pinned volk git ref for smoke tests")
10+
711
set(WEBVULKAN_TEST_MODE "auto" CACHE STRING "Test mode: auto, in-tree, or package")
812
set_property(CACHE WEBVULKAN_TEST_MODE PROPERTY STRINGS auto in-tree package)
913
set(WEBVULKAN_TEST_PACKAGE_PREFIX "" CACHE PATH "Install prefix for WebVulkan package mode")
1014
set(WEBVULKAN_TEST_WASM_BUILD_DIR "${CMAKE_BINARY_DIR}/wasm" CACHE PATH "WASM smoke build directory")
1115

16+
if(NOT COMMAND CPMAddPackage)
17+
if(NOT DEFINED WEBVULKAN_CPM_VERSION OR WEBVULKAN_CPM_VERSION STREQUAL "")
18+
set(WEBVULKAN_CPM_VERSION "0.40.2" CACHE STRING "CPM.cmake release version for tests")
19+
endif()
20+
if(NOT DEFINED WEBVULKAN_CPM_DIR OR WEBVULKAN_CPM_DIR STREQUAL "")
21+
set(WEBVULKAN_CPM_DIR "${WEBVULKAN_TEST_THIRDPARTY_DIR}/cpm" CACHE PATH "Directory where CPM.cmake is stored for tests")
22+
endif()
23+
if(NOT DEFINED CPM_SOURCE_CACHE OR CPM_SOURCE_CACHE STREQUAL "")
24+
set(CPM_SOURCE_CACHE "${WEBVULKAN_TEST_THIRDPARTY_DIR}/cpm-cache" CACHE PATH "CPM source cache path for tests")
25+
endif()
26+
if(NOT DEFINED WEBVULKAN_ALLOW_DEP_UPDATES)
27+
set(WEBVULKAN_ALLOW_DEP_UPDATES OFF CACHE BOOL "Allow dependency git update during configure")
28+
endif()
29+
if(WEBVULKAN_ALLOW_DEP_UPDATES)
30+
set(CPM_UPDATE_DISCONNECTED OFF CACHE BOOL "CPM update disconnected mode" FORCE)
31+
else()
32+
set(CPM_UPDATE_DISCONNECTED ON CACHE BOOL "CPM update disconnected mode" FORCE)
33+
endif()
34+
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/BootstrapCpm.cmake")
35+
webvulkan_bootstrap_cpm()
36+
endif()
37+
1238
set(_webvulkan_test_mode "${WEBVULKAN_TEST_MODE}")
1339
if(_webvulkan_test_mode STREQUAL "auto")
1440
if(TARGET llvmpipe_wasm_spike)
@@ -51,6 +77,20 @@ if(NOT SUBBUILD_GENERATOR)
5177
message(FATAL_ERROR "No CMake generator is available for wasm smoke sub-build")
5278
endif()
5379

80+
CPMAddPackage(
81+
NAME webvulkan_volk
82+
GIT_REPOSITORY "${WEBVULKAN_VOLK_GIT_URL}"
83+
GIT_TAG "${WEBVULKAN_VOLK_GIT_REF}"
84+
GIT_SHALLOW TRUE
85+
DOWNLOAD_ONLY YES
86+
)
87+
set(_webvulkan_volk_include_dir "${webvulkan_volk_SOURCE_DIR}")
88+
set(_webvulkan_volk_source "${webvulkan_volk_SOURCE_DIR}/volk.c")
89+
set(_webvulkan_volk_header "${webvulkan_volk_SOURCE_DIR}/volk.h")
90+
if(NOT EXISTS "${_webvulkan_volk_source}" OR NOT EXISTS "${_webvulkan_volk_header}")
91+
message(FATAL_ERROR "volk sources are missing under ${webvulkan_volk_SOURCE_DIR}")
92+
endif()
93+
5494
if(_webvulkan_test_mode STREQUAL "in-tree")
5595
if(NOT TARGET llvmpipe_wasm_spike)
5696
message(FATAL_ERROR "in-tree test mode requires llvmpipe_wasm_spike target")
@@ -106,6 +146,8 @@ set(_webvulkan_lavapipe_depends
106146
"${CMAKE_CURRENT_LIST_DIR}/RunLavapipeRuntimeSmoke.cmake"
107147
"${CMAKE_CURRENT_LIST_DIR}/wasm/src/lavapipe_runtime_smoke.c"
108148
"${CMAKE_CURRENT_LIST_DIR}/wasm/tools/smoke_runtime.mjs"
149+
"${_webvulkan_volk_source}"
150+
"${_webvulkan_volk_header}"
109151
"${_webvulkan_driver_archive}"
110152
)
111153
if(_webvulkan_test_mode STREQUAL "in-tree")
@@ -122,6 +164,8 @@ add_custom_command(
122164
-DSMOKE_SOURCE=${CMAKE_CURRENT_LIST_DIR}/wasm/src/lavapipe_runtime_smoke.c
123165
-DSMOKE_JS_OUT=${WEBVULKAN_LAVAPIPE_SMOKE_JS}
124166
-DSMOKE_SCRIPT=${CMAKE_CURRENT_LIST_DIR}/wasm/tools/smoke_runtime.mjs
167+
-DVOLK_INCLUDE_DIR=${_webvulkan_volk_include_dir}
168+
-DVOLK_SOURCE=${_webvulkan_volk_source}
125169
-P "${CMAKE_CURRENT_LIST_DIR}/RunLavapipeRuntimeSmoke.cmake"
126170
COMMAND "${CMAKE_COMMAND}" -E touch "${WEBVULKAN_LAVAPIPE_SMOKE_OK}"
127171
DEPENDS ${_webvulkan_lavapipe_depends}

tests/RunLavapipeRuntimeSmoke.cmake

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ require_var(SMOKE_INCLUDE_DIRS)
1212
require_var(SMOKE_SOURCE)
1313
require_var(SMOKE_JS_OUT)
1414
require_var(SMOKE_SCRIPT)
15+
require_var(VOLK_INCLUDE_DIR)
16+
require_var(VOLK_SOURCE)
1517

1618
if(CMAKE_HOST_WIN32)
1719
set(EMCC_BIN "${EMSDK_ROOT}/upstream/emscripten/emcc.bat")
@@ -34,6 +36,12 @@ list(GET NODE_CANDIDATES 0 NODE_EXE)
3436
if(NOT EXISTS "${DRIVER_ARCHIVE}")
3537
message(FATAL_ERROR "Missing driver archive ${DRIVER_ARCHIVE}")
3638
endif()
39+
if(NOT EXISTS "${VOLK_SOURCE}")
40+
message(FATAL_ERROR "Missing volk source ${VOLK_SOURCE}")
41+
endif()
42+
if(NOT EXISTS "${VOLK_INCLUDE_DIR}/volk.h")
43+
message(FATAL_ERROR "Missing volk include directory ${VOLK_INCLUDE_DIR}")
44+
endif()
3745

3846
get_filename_component(SMOKE_OUT_DIR "${SMOKE_JS_OUT}" DIRECTORY)
3947
file(MAKE_DIRECTORY "${SMOKE_OUT_DIR}")
@@ -46,9 +54,11 @@ function(append_rsp ARG_VALUE)
4654
endfunction()
4755

4856
append_rsp("${SMOKE_SOURCE}")
57+
append_rsp("${VOLK_SOURCE}")
4958
append_rsp("-o")
5059
append_rsp("${SMOKE_JS_OUT}")
5160
append_rsp("-std=c11")
61+
append_rsp("-I${VOLK_INCLUDE_DIR}")
5262
foreach(SMOKE_INCLUDE_DIR IN LISTS SMOKE_INCLUDE_DIRS)
5363
if(NOT EXISTS "${SMOKE_INCLUDE_DIR}")
5464
message(FATAL_ERROR "Missing include directory ${SMOKE_INCLUDE_DIR}")

tests/wasm/src/lavapipe_runtime_smoke.c

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
#include <emscripten/emscripten.h>
2+
#include <volk.h>
23
#include <stdio.h>
34
#include <string.h>
4-
#include <vulkan/vulkan.h>
55

66
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName);
77

88
EMSCRIPTEN_KEEPALIVE int lavapipe_runtime_smoke(void) {
9-
PFN_vkCreateInstance createInstance = (PFN_vkCreateInstance)vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance");
10-
PFN_vkEnumerateInstanceVersion enumerateVersion = (PFN_vkEnumerateInstanceVersion)vk_icdGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion");
11-
12-
if (!createInstance || !enumerateVersion) {
9+
volkInitializeCustom((PFN_vkGetInstanceProcAddr)vk_icdGetInstanceProcAddr);
10+
if (!vkCreateInstance || !vkEnumerateInstanceVersion) {
1311
return 21;
1412
}
1513

1614
uint32_t apiVersion = 0u;
17-
VkResult rc = enumerateVersion(&apiVersion);
15+
VkResult rc = vkEnumerateInstanceVersion(&apiVersion);
1816
if (rc != VK_SUCCESS) {
1917
return 22;
2018
}
@@ -34,27 +32,44 @@ EMSCRIPTEN_KEEPALIVE int lavapipe_runtime_smoke(void) {
3432
createInfo.pApplicationInfo = &appInfo;
3533

3634
VkInstance instance = VK_NULL_HANDLE;
37-
rc = createInstance(&createInfo, 0, &instance);
35+
rc = vkCreateInstance(&createInfo, 0, &instance);
3836
if (rc != VK_SUCCESS || instance == VK_NULL_HANDLE) {
3937
return 23;
4038
}
4139

42-
PFN_vkEnumeratePhysicalDevices enumeratePhysicalDevices =
43-
(PFN_vkEnumeratePhysicalDevices)vk_icdGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices");
44-
PFN_vkDestroyInstance destroyInstance =
45-
(PFN_vkDestroyInstance)vk_icdGetInstanceProcAddr(instance, "vkDestroyInstance");
46-
47-
if (!enumeratePhysicalDevices || !destroyInstance) {
40+
volkLoadInstance(instance);
41+
if (!vkEnumeratePhysicalDevices || !vkDestroyInstance || !vkGetDeviceProcAddr) {
42+
vkDestroyInstance(instance, 0);
4843
return 24;
4944
}
5045

5146
uint32_t physicalDeviceCount = 0u;
52-
rc = enumeratePhysicalDevices(instance, &physicalDeviceCount, 0);
47+
rc = vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, 0);
5348
if (rc != VK_SUCCESS || physicalDeviceCount == 0u) {
54-
destroyInstance(instance, 0);
49+
vkDestroyInstance(instance, 0);
5550
return 25;
5651
}
5752

53+
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
54+
uint32_t one = 1u;
55+
rc = vkEnumeratePhysicalDevices(instance, &one, &physicalDevice);
56+
if (rc != VK_SUCCESS || one == 0u || physicalDevice == VK_NULL_HANDLE) {
57+
vkDestroyInstance(instance, 0);
58+
return 26;
59+
}
60+
61+
PFN_vkVoidFunction fpEnumeratePhysicalDevices =
62+
vk_icdGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices");
63+
PFN_vkVoidFunction fpGetPhysicalDeviceProperties =
64+
vk_icdGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties");
65+
PFN_vkVoidFunction fpGetPhysicalDeviceProperties2 =
66+
vk_icdGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2");
67+
68+
if (!fpEnumeratePhysicalDevices || !fpGetPhysicalDeviceProperties || !fpGetPhysicalDeviceProperties2) {
69+
vkDestroyInstance(instance, 0);
70+
return 27;
71+
}
72+
5873
printf("lavapipe runtime smoke ok\n");
5974
printf(" backend=mesa lavapipe (swrast)\n");
6075
printf(" instance.api=%u.%u.%u (%u)\n",
@@ -65,8 +80,11 @@ EMSCRIPTEN_KEEPALIVE int lavapipe_runtime_smoke(void) {
6580
printf(" vkCreateInstance=ok\n");
6681
printf(" vkEnumeratePhysicalDevices=ok\n");
6782
printf(" physical_devices=%u\n", physicalDeviceCount);
68-
printf(" vk_icd.entrypoint=vk_icdGetInstanceProcAddr\n");
69-
destroyInstance(instance, 0);
83+
printf(" vk_icdGetInstanceProcAddr(vkEnumeratePhysicalDevices)=present\n");
84+
printf(" vk_icdGetInstanceProcAddr(vkGetPhysicalDeviceProperties)=present\n");
85+
printf(" vk_icdGetInstanceProcAddr(vkGetPhysicalDeviceProperties2)=present\n");
86+
printf(" vulkan_loader=volk (custom vk_icdGetInstanceProcAddr)\n");
87+
vkDestroyInstance(instance, 0);
7088
return 0;
7189
}
7290

0 commit comments

Comments
 (0)