CMakeLists.txt 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. cmake_minimum_required(VERSION 3.19)
  2. cmake_policy(SET CMP0114 NEW)
  3. find_package(Vulkan COMPONENTS glslc REQUIRED)
  4. function(detect_host_compiler)
  5. if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
  6. find_program(HOST_C_COMPILER NAMES cl gcc clang NO_CMAKE_FIND_ROOT_PATH)
  7. find_program(HOST_CXX_COMPILER NAMES cl g++ clang++ NO_CMAKE_FIND_ROOT_PATH)
  8. else()
  9. find_program(HOST_C_COMPILER NAMES gcc clang NO_CMAKE_FIND_ROOT_PATH)
  10. find_program(HOST_CXX_COMPILER NAMES g++ clang++ NO_CMAKE_FIND_ROOT_PATH)
  11. endif()
  12. set(HOST_C_COMPILER "${HOST_C_COMPILER}" PARENT_SCOPE)
  13. set(HOST_CXX_COMPILER "${HOST_CXX_COMPILER}" PARENT_SCOPE)
  14. endfunction()
  15. # Function to test shader extension support
  16. # Parameters:
  17. # EXTENSION_NAME - Name of the extension to test (e.g., "GL_EXT_integer_dot_product")
  18. # TEST_SHADER_FILE - Path to the test shader file
  19. # RESULT_VARIABLE - Name of the variable to set (ON/OFF) based on test result
  20. function(test_shader_extension_support EXTENSION_NAME TEST_SHADER_FILE RESULT_VARIABLE)
  21. execute_process(
  22. COMMAND ${Vulkan_GLSLC_EXECUTABLE} -o - -fshader-stage=compute --target-env=vulkan1.3 "${TEST_SHADER_FILE}"
  23. OUTPUT_VARIABLE glslc_output
  24. ERROR_VARIABLE glslc_error
  25. )
  26. if (${glslc_error} MATCHES ".*extension not supported: ${EXTENSION_NAME}.*")
  27. message(STATUS "${EXTENSION_NAME} not supported by glslc")
  28. set(${RESULT_VARIABLE} OFF PARENT_SCOPE)
  29. else()
  30. message(STATUS "${EXTENSION_NAME} supported by glslc")
  31. set(${RESULT_VARIABLE} ON PARENT_SCOPE)
  32. add_compile_definitions(${RESULT_VARIABLE})
  33. # Ensure the extension support is forwarded to vulkan-shaders-gen
  34. list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -D${RESULT_VARIABLE}=ON)
  35. set(VULKAN_SHADER_GEN_CMAKE_ARGS "${VULKAN_SHADER_GEN_CMAKE_ARGS}" PARENT_SCOPE)
  36. endif()
  37. endfunction()
  38. if (Vulkan_FOUND)
  39. message(STATUS "Vulkan found")
  40. ggml_add_backend_library(ggml-vulkan
  41. ggml-vulkan.cpp
  42. ../../include/ggml-vulkan.h
  43. )
  44. set(VULKAN_SHADER_GEN_CMAKE_ARGS "")
  45. # Test all shader extensions
  46. test_shader_extension_support(
  47. "GL_KHR_cooperative_matrix"
  48. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat_support.comp"
  49. "GGML_VULKAN_COOPMAT_GLSLC_SUPPORT"
  50. )
  51. test_shader_extension_support(
  52. "GL_NV_cooperative_matrix2"
  53. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat2_support.comp"
  54. "GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT"
  55. )
  56. test_shader_extension_support(
  57. "GL_EXT_integer_dot_product"
  58. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_integer_dot_support.comp"
  59. "GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT"
  60. )
  61. test_shader_extension_support(
  62. "GL_EXT_bfloat16"
  63. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_bfloat16_support.comp"
  64. "GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT"
  65. )
  66. target_link_libraries(ggml-vulkan PRIVATE Vulkan::Vulkan)
  67. target_include_directories(ggml-vulkan PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
  68. # Workaround to the "can't dereference invalidated vector iterator" bug in clang-cl debug build
  69. # Posssibly relevant: https://stackoverflow.com/questions/74748276/visual-studio-no-displays-the-correct-length-of-stdvector
  70. if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  71. add_compile_definitions(_ITERATOR_DEBUG_LEVEL=0)
  72. endif()
  73. if (GGML_VULKAN_CHECK_RESULTS)
  74. add_compile_definitions(GGML_VULKAN_CHECK_RESULTS)
  75. endif()
  76. if (GGML_VULKAN_DEBUG)
  77. add_compile_definitions(GGML_VULKAN_DEBUG)
  78. endif()
  79. if (GGML_VULKAN_MEMORY_DEBUG)
  80. add_compile_definitions(GGML_VULKAN_MEMORY_DEBUG)
  81. endif()
  82. if (GGML_VULKAN_SHADER_DEBUG_INFO)
  83. add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO)
  84. list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DGGML_VULKAN_SHADER_DEBUG_INFO=ON)
  85. endif()
  86. if (GGML_VULKAN_VALIDATE)
  87. add_compile_definitions(GGML_VULKAN_VALIDATE)
  88. endif()
  89. if (GGML_VULKAN_RUN_TESTS)
  90. add_compile_definitions(GGML_VULKAN_RUN_TESTS)
  91. endif()
  92. # Set up toolchain for host compilation whether cross-compiling or not
  93. if (CMAKE_CROSSCOMPILING)
  94. if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN)
  95. set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN})
  96. else()
  97. detect_host_compiler()
  98. if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER)
  99. message(FATAL_ERROR "Host compiler not found")
  100. else()
  101. message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}")
  102. endif()
  103. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY)
  104. set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake)
  105. endif()
  106. else()
  107. # For non-cross-compiling, use empty toolchain (use host compiler)
  108. set(HOST_CMAKE_TOOLCHAIN_FILE "")
  109. endif()
  110. include(ExternalProject)
  111. if (CMAKE_CROSSCOMPILING)
  112. list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE})
  113. message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}")
  114. endif()
  115. ExternalProject_Add(
  116. vulkan-shaders-gen
  117. SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders
  118. CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/$<CONFIG>
  119. -DCMAKE_INSTALL_BINDIR=.
  120. -DCMAKE_BUILD_TYPE=$<CONFIG>
  121. ${VULKAN_SHADER_GEN_CMAKE_ARGS}
  122. BUILD_COMMAND ${CMAKE_COMMAND} --build . --config $<CONFIG>
  123. BUILD_ALWAYS TRUE
  124. # NOTE: When DESTDIR is set using Makefile generators and
  125. # "make install" triggers the build step, vulkan-shaders-gen
  126. # would be installed into the DESTDIR prefix, so it is unset
  127. # to ensure that does not happen.
  128. INSTALL_COMMAND ${CMAKE_COMMAND} -E env --unset=DESTDIR
  129. ${CMAKE_COMMAND} --install . --config $<CONFIG>
  130. )
  131. set (_ggml_vk_host_suffix $<IF:$<STREQUAL:${CMAKE_HOST_SYSTEM_NAME},Windows>,.exe,>)
  132. set (_ggml_vk_genshaders_dir "${CMAKE_BINARY_DIR}/$<CONFIG>")
  133. set (_ggml_vk_genshaders_cmd "${_ggml_vk_genshaders_dir}/vulkan-shaders-gen${_ggml_vk_host_suffix}")
  134. set (_ggml_vk_header "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp")
  135. set (_ggml_vk_source "${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.cpp")
  136. set (_ggml_vk_input_dir "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders")
  137. set (_ggml_vk_output_dir "${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv")
  138. file(GLOB _ggml_vk_shader_files CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.comp")
  139. # Because external projects do not provide source-level tracking,
  140. # the vulkan-shaders-gen sources need to be explicitly added to
  141. # ensure that changes will cascade into shader re-generation.
  142. file(GLOB _ggml_vk_shaders_gen_sources
  143. CONFIGURE_DEPENDS "${_ggml_vk_input_dir}/*.cpp"
  144. "${_ggml_vk_input_dir}/*.h")
  145. add_custom_command(
  146. OUTPUT ${_ggml_vk_header}
  147. ${_ggml_vk_source}
  148. COMMAND ${_ggml_vk_genshaders_cmd}
  149. --glslc ${Vulkan_GLSLC_EXECUTABLE}
  150. --input-dir ${_ggml_vk_input_dir}
  151. --output-dir ${_ggml_vk_output_dir}
  152. --target-hpp ${_ggml_vk_header}
  153. --target-cpp ${_ggml_vk_source}
  154. --no-clean
  155. DEPENDS ${_ggml_vk_shader_files}
  156. ${_ggml_vk_shaders_gen_sources}
  157. vulkan-shaders-gen
  158. COMMENT "Generate vulkan shaders"
  159. )
  160. target_sources(ggml-vulkan PRIVATE ${_ggml_vk_source} ${_ggml_vk_header})
  161. else()
  162. message(WARNING "Vulkan not found")
  163. endif()