This is an automated email from the ASF dual-hosted git repository. tqchen pushed a commit to branch manylinux-ci-836 in repository https://gitbox.apache.org/repos/asf/tvm-tirx.git
commit 3e62b585894ae6fdc9c6ab80104c3093857dc8a7 Author: Tianqi Chen <[email protected]> AuthorDate: Sun Oct 25 19:21:34 2026 +0000 [FEAT] Enable SPIR-V code generation independently of Vulkan runtime --- CMakeLists.txt | 5 +- cmake/modules/SPIRV.cmake | 87 +++++++++++++++++++++++ cmake/modules/Vulkan.cmake | 23 +----- cmake/utils/FindVulkan.cmake | 28 +------- src/backend/vulkan/codegen/spirv_utils.cc | 2 +- tests/python/backend/vulkan/test_module_export.py | 8 +-- 6 files changed, 97 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 22b608d0b..b2ad29af9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ tvm_tirx_option(TVM_TIRX_USE_OPENCL_EXTN_QCOM BOOL OFF "Enable Qualcomm OpenCL e # Vulkan tvm_tirx_option(TVM_TIRX_USE_VULKAN STRING OFF "Build with Vulkan (OFF, ON, or SDK path)") -tvm_tirx_option(TVM_TIRX_USE_KHRONOS_SPIRV STRING OFF "Use Khronos SPIR-V tools (OFF or install path)") +tvm_tirx_option(TVM_TIRX_USE_KHRONOS_SPIRV STRING OFF "SPIR-V tools installation prefix (OFF for automatic discovery)") tvm_tirx_option(TVM_TIRX_USE_SPIRV_KHR_INTEGER_DOT_PRODUCT BOOL OFF "Enable SPIR-V integer dot product") # ROCm @@ -219,6 +219,7 @@ include(cmake/modules/OpenMP.cmake) # contributions are collected before the compiler object target is created. include(cmake/modules/CUDA.cmake) include(cmake/modules/OpenCL.cmake) +include(cmake/modules/SPIRV.cmake) include(cmake/modules/Vulkan.cmake) include(cmake/modules/Metal.cmake) include(cmake/modules/ROCM.cmake) @@ -228,7 +229,7 @@ include(cmake/modules/Git.cmake) # ######### Target: `tvm_tirx_compiler` ########## add_library(tvm_tirx_compiler_objs OBJECT ${COMPILER_SRCS}) -target_link_libraries(tvm_tirx_compiler_objs PUBLIC tvm_tirx_header) +target_link_libraries(tvm_tirx_compiler_objs PUBLIC tvm_tirx_header PRIVATE tvm_spirv_header) if(TARGET tvm_llvm_header) target_link_libraries(tvm_tirx_compiler_objs PRIVATE tvm_llvm_header) endif() diff --git a/cmake/modules/SPIRV.cmake b/cmake/modules/SPIRV.cmake new file mode 100644 index 000000000..0d90c4df4 --- /dev/null +++ b/cmake/modules/SPIRV.cmake @@ -0,0 +1,87 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# SPIR-V code generation needs headers and SPIRV-Tools, but no Vulkan loader. +include(FetchContent) +FetchContent_Declare(tvm_spirv_headers + URL https://github.com/KhronosGroup/SPIRV-Headers/archive/09913f088a1197aba4aefd300a876b2ebbaa3391.tar.gz + URL_HASH SHA256=6d4aad5a86d7d5af144747aee1d616f624897d64d842f282aca7777f84244318 + SOURCE_SUBDIR headers-only) +find_path(TVM_SPIRV_HEADERS_DIR spirv.hpp + HINTS "${TVM_TIRX_USE_KHRONOS_SPIRV}" ENV VULKAN_SDK + PATH_SUFFIXES include/spirv/unified1 include/SPIRV) +if(NOT TVM_SPIRV_HEADERS_DIR) + FetchContent_MakeAvailable(tvm_spirv_headers) + set(TVM_SPIRV_HEADERS_DIR "${tvm_spirv_headers_SOURCE_DIR}/include/spirv/unified1") +endif() +find_path(TVM_VULKAN_HEADERS_DIR vulkan/vulkan_core.h + HINTS "${TVM_TIRX_USE_VULKAN}" ENV VULKAN_SDK PATH_SUFFIXES include) +if(NOT TVM_VULKAN_HEADERS_DIR) + FetchContent_Declare(tvm_vulkan_headers + URL https://github.com/KhronosGroup/Vulkan-Headers/archive/952f776f6573aafbb62ea717d871cd1d6816c387.tar.gz + URL_HASH SHA256=4c744e80c908bcc65c2057482f44e57d7e3d748f6eae4cd759fd593018f4ce35 + SOURCE_SUBDIR headers-only) + FetchContent_MakeAvailable(tvm_vulkan_headers) + set(TVM_VULKAN_HEADERS_DIR "${tvm_vulkan_headers_SOURCE_DIR}/include") +endif() + +find_package(SPIRV-Tools CONFIG QUIET + HINTS "${TVM_TIRX_USE_KHRONOS_SPIRV}" ENV VULKAN_SDK) +if(NOT TARGET SPIRV-Tools-static AND NOT TARGET SPIRV-Tools) + # Keep the matching SDK 1.4.309 headers beside the source build. Only the + # validation/disassembly library is linked; tools and tests are not built. + if(NOT tvm_spirv_headers_SOURCE_DIR) + FetchContent_MakeAvailable(tvm_spirv_headers) + endif() + set(SPIRV-Headers_SOURCE_DIR "${tvm_spirv_headers_SOURCE_DIR}") + set(TVM_SPIRV_HEADERS_DIR "${tvm_spirv_headers_SOURCE_DIR}/include/spirv/unified1") + set(SPIRV_SKIP_EXECUTABLES ON) + set(SPIRV_SKIP_TESTS ON) + set(SPIRV_TOOLS_BUILD_STATIC ON) + set(SKIP_SPIRV_TOOLS_INSTALL ON) + FetchContent_Declare(tvm_spirv_tools + URL https://github.com/KhronosGroup/SPIRV-Tools/archive/f289d047f49fb60488301ec62bafab85573668cc.tar.gz + URL_HASH SHA256=5fbd56baf226a04435656bae408287365102b69a24fa73bab8353c5f44b55615 + SOURCE_SUBDIR library-only) + FetchContent_MakeAvailable(tvm_spirv_tools) + add_subdirectory("${tvm_spirv_tools_SOURCE_DIR}" "${tvm_spirv_tools_BINARY_DIR}" EXCLUDE_FROM_ALL) + install(FILES "${tvm_spirv_tools_SOURCE_DIR}/LICENSE" DESTINATION licenses + RENAME LICENSE-SPIRV-Tools.txt COMPONENT tvm_tirx) +endif() +if(TARGET SPIRV-Tools-static) + set(TVM_SPIRV_TOOLS_LIBRARY SPIRV-Tools-static) +else() + set(TVM_SPIRV_TOOLS_LIBRARY SPIRV-Tools) +endif() + +add_library(tvm_spirv_header INTERFACE) +target_include_directories(tvm_spirv_header SYSTEM INTERFACE + "${TVM_SPIRV_HEADERS_DIR}" "${TVM_VULKAN_HEADERS_DIR}") +target_link_libraries(tvm_spirv_header INTERFACE ${TVM_SPIRV_TOOLS_LIBRARY}) +target_compile_definitions(tvm_spirv_header INTERFACE TVM_ENABLE_SPIRV=1) +if(TVM_TIRX_USE_SPIRV_KHR_INTEGER_DOT_PRODUCT) + target_compile_definitions(tvm_spirv_header INTERFACE TVM_SPIRV_KHR_INTEGER_DOT_PRODUCT=1) +endif() +file(GLOB COMPILER_SPIRV_SRCS CONFIGURE_DEPENDS + src/backend/vulkan/codegen/build_vulkan.cc + src/backend/vulkan/codegen/codegen_spirv.cc + src/backend/vulkan/codegen/intrin_rule_spirv.cc + src/backend/vulkan/codegen/ir_builder.cc + src/backend/vulkan/codegen/spirv_support.cc + src/backend/vulkan/codegen/spirv_utils.cc) +list(APPEND COMPILER_SRCS ${COMPILER_SPIRV_SRCS}) +list(APPEND TVM_LINKER_LIBS ${TVM_SPIRV_TOOLS_LIBRARY}) diff --git a/cmake/modules/Vulkan.cmake b/cmake/modules/Vulkan.cmake index 88025bf03..5fb61cacb 100644 --- a/cmake/modules/Vulkan.cmake +++ b/cmake/modules/Vulkan.cmake @@ -15,38 +15,19 @@ # specific language governing permissions and limitations # under the License. -# Be compatible with older version of CMake -find_vulkan(${TVM_TIRX_USE_VULKAN} ${TVM_TIRX_USE_KHRONOS_SPIRV}) +find_vulkan(${TVM_TIRX_USE_VULKAN}) if(TVM_TIRX_USE_VULKAN) if(NOT Vulkan_FOUND) message(FATAL_ERROR "Cannot find Vulkan, TVM_TIRX_USE_VULKAN=" ${TVM_TIRX_USE_VULKAN}) endif() - if(TVM_TIRX_USE_SPIRV_KHR_INTEGER_DOT_PRODUCT) - add_definitions(-DTVM_SPIRV_KHR_INTEGER_DOT_PRODUCT=1) - message(STATUS "Enable SPIRV_KHR_INTEGER_DOT_PRODUCT") - endif() - include_directories(SYSTEM ${Vulkan_INCLUDE_DIRS}) - message(STATUS "Build with Vulkan support") - file(GLOB COMPILER_VULKAN_SRCS CONFIGURE_DEPENDS src/backend/vulkan/codegen/build_vulkan.cc - src/backend/vulkan/codegen/codegen_spirv.cc - src/backend/vulkan/codegen/intrin_rule_spirv.cc - src/backend/vulkan/codegen/ir_builder.cc - src/backend/vulkan/codegen/spirv_support.cc - src/backend/vulkan/codegen/spirv_utils.cc - ) - list(APPEND COMPILER_SRCS ${COMPILER_VULKAN_SRCS}) - list(APPEND TVM_LINKER_LIBS ${Vulkan_SPIRV_TOOLS_LIBRARY}) - add_definitions(-DTVM_ENABLE_SPIRV=1) -endif(TVM_TIRX_USE_VULKAN) - -if(TVM_TIRX_USE_VULKAN) message(STATUS "Build vulkan device runtime") file(GLOB RUNTIME_VULKAN_SRCS CONFIGURE_DEPENDS src/backend/vulkan/runtime/*.cc) add_library(tvm_runtime_vulkan_objs OBJECT ${RUNTIME_VULKAN_SRCS}) target_link_libraries(tvm_runtime_vulkan_objs PUBLIC tvm_tirx_header) + target_include_directories(tvm_runtime_vulkan_objs SYSTEM PRIVATE ${Vulkan_INCLUDE_DIRS}) set_target_properties(tvm_runtime_vulkan_objs PROPERTIES POSITION_INDEPENDENT_CODE ON) add_library(tvm_runtime_vulkan SHARED $<TARGET_OBJECTS:tvm_runtime_vulkan_objs>) install(TARGETS tvm_runtime_vulkan DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT tvm_tirx) diff --git a/cmake/utils/FindVulkan.cmake b/cmake/utils/FindVulkan.cmake index 032ff1dff..a5d7a0799 100644 --- a/cmake/utils/FindVulkan.cmake +++ b/cmake/utils/FindVulkan.cmake @@ -29,10 +29,9 @@ # - Vulkan_FOUND # - Vulkan_INCLUDE_DIRS # - Vulkan_LIBRARY -# - Vulkan_SPIRV_TOOLS_LIBRARY # -macro(find_vulkan use_vulkan use_khronos_spirv) +macro(find_vulkan use_vulkan) set(__use_vulkan ${use_vulkan}) if(IS_DIRECTORY ${__use_vulkan}) set(__vulkan_sdk ${__use_vulkan}) @@ -44,13 +43,6 @@ macro(find_vulkan use_vulkan use_khronos_spirv) endif() - if(IS_DIRECTORY ${use_khronos_spirv}) - set(__use_khronos_spirv ${use_khronos_spirv}) - message(STATUS "Custom khronos spirv PATH=" ${__use_khronos_spirv}) - else() - set(__use_khronos_spirv "") - endif() - if(CMAKE_SYSTEM_NAME STREQUAL "Android") set(VULKAN_NDK_SRC ${CMAKE_ANDROID_NDK}/sources/third_party/vulkan/src) set(Vulkan_INCLUDE_DIRS ${VULKAN_NDK_SRC}/include) @@ -76,23 +68,7 @@ macro(find_vulkan use_vulkan use_khronos_spirv) endif() if(Vulkan_FOUND) - get_filename_component(VULKAN_LIBRARY_PATH ${Vulkan_LIBRARY} DIRECTORY) - if (WIN32) - find_library(Vulkan_SPIRV_TOOLS_LIBRARY SPIRV-Tools - HINTS ${__use_khronos_spirv}/spirv-tools/lib ${VULKAN_LIBRARY_PATH} ${VULKAN_LIBRARY_PATH}/spirv-tools ${VULKAN_SDK}/lib) - find_path(_libspirv libspirv.h HINTS ${__use_khronos_spirv}/spirv-tools/include ${Vulkan_INCLUDE_DIRS} PATH_SUFFIXES vulkan spirv-tools) - find_path(_spirv spirv.hpp HINTS ${__use_khronos_spirv}/SPIRV-Headers/include ${Vulkan_INCLUDE_DIRS} PATH_SUFFIXES vulkan SPIRV spirv/unified1 spirv-headers) - else() - find_library(Vulkan_SPIRV_TOOLS_LIBRARY SPIRV-Tools - HINTS ${__use_khronos_spirv}/lib ${VULKAN_LIBRARY_PATH} ${VULKAN_LIBRARY_PATH}/spirv-tools ${VULKAN_SDK}/lib) - find_path(_libspirv libspirv.h HINTS ${__use_khronos_spirv}/include ${Vulkan_INCLUDE_DIRS} PATH_SUFFIXES vulkan spirv-tools) - find_path(_spirv spirv.hpp HINTS ${__use_khronos_spirv}/include ${Vulkan_INCLUDE_DIRS} PATH_SUFFIXES vulkan SPIRV spirv/unified1 spirv-headers) - endif() - - find_path(_glsl_std GLSL.std.450.h HINTS ${Vulkan_INCLUDE_DIRS} PATH_SUFFIXES vulkan SPIRV spirv/unified1 spirv-headers) - list(APPEND Vulkan_INCLUDE_DIRS ${_libspirv} ${_spirv} ${_glsl_std}) message(STATUS "Vulkan_INCLUDE_DIRS=" ${Vulkan_INCLUDE_DIRS}) message(STATUS "Vulkan_LIBRARY=" ${Vulkan_LIBRARY}) - message(STATUS "Vulkan_SPIRV_TOOLS_LIBRARY=" ${Vulkan_SPIRV_TOOLS_LIBRARY}) - endif(Vulkan_FOUND) + endif() endmacro(find_vulkan) diff --git a/src/backend/vulkan/codegen/spirv_utils.cc b/src/backend/vulkan/codegen/spirv_utils.cc index c2e9946a8..659d3a2af 100644 --- a/src/backend/vulkan/codegen/spirv_utils.cc +++ b/src/backend/vulkan/codegen/spirv_utils.cc @@ -28,7 +28,7 @@ #include <tvm/support/env.h> #if TVM_ENABLE_SPIRV -#include <libspirv.h> +#include <spirv-tools/libspirv.h> #include "codegen_spirv.h" #endif diff --git a/tests/python/backend/vulkan/test_module_export.py b/tests/python/backend/vulkan/test_module_export.py index 4e9e7fbe5..981df5d2e 100644 --- a/tests/python/backend/vulkan/test_module_export.py +++ b/tests/python/backend/vulkan/test_module_export.py @@ -15,19 +15,14 @@ # specific language governing permissions and limitations # under the License. -import pytest - import tvm_tirx import tvm_tirx.testing from tvm_tirx.script import ir as I from tvm_tirx.script import tirx as T -from tvm_tirx.testing import env [email protected] [email protected](not env.has_vulkan(), reason="need vulkan") def test_export_load_with_fallback(monkeypatch, tmp_path): - """Force the codegen wrapper into the fallback branch, then export.""" + """Compile and export SPIR-V without requiring a Vulkan device or runtime.""" n = 1024 @I.ir_module @@ -42,6 +37,7 @@ def test_export_load_with_fallback(monkeypatch, tmp_path): monkeypatch.setenv("TVM_TIRX_COMPILE_FORCE_FALLBACK", "1") host_lib = tvm_tirx.tirx.compile(Module, target="vulkan") monkeypatch.delenv("TVM_TIRX_COMPILE_FORCE_FALLBACK") + assert "OpEntryPoint GLCompute" in host_lib.mod.imports[0].inspect_source() lib_path = str(tmp_path / "lib.so") host_lib.export_library(lib_path)
