CMakeLists.txt 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}
  46. -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
  47. )
  48. set(VULKAN_SHADER_GEN_CMAKE_BUILD_ARGS "")
  49. if (CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE MATCHES "Debug|Release|MinSizeRel|RelWithDebInfo")
  50. list(APPEND VULKAN_SHADER_GEN_CMAKE_BUILD_ARGS --config=${CMAKE_BUILD_TYPE})
  51. endif()
  52. # Test all shader extensions
  53. test_shader_extension_support(
  54. "GL_KHR_cooperative_matrix"
  55. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat_support.comp"
  56. "GGML_VULKAN_COOPMAT_GLSLC_SUPPORT"
  57. )
  58. test_shader_extension_support(
  59. "GL_NV_cooperative_matrix2"
  60. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_coopmat2_support.comp"
  61. "GGML_VULKAN_COOPMAT2_GLSLC_SUPPORT"
  62. )
  63. test_shader_extension_support(
  64. "GL_EXT_integer_dot_product"
  65. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_integer_dot_support.comp"
  66. "GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT"
  67. )
  68. test_shader_extension_support(
  69. "GL_EXT_bfloat16"
  70. "${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders/test_bfloat16_support.comp"
  71. "GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT"
  72. )
  73. target_link_libraries(ggml-vulkan PRIVATE Vulkan::Vulkan)
  74. target_include_directories(ggml-vulkan PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
  75. # Workaround to the "can't dereference invalidated vector iterator" bug in clang-cl debug build
  76. # Posssibly relevant: https://stackoverflow.com/questions/74748276/visual-studio-no-displays-the-correct-length-of-stdvector
  77. if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  78. add_compile_definitions(_ITERATOR_DEBUG_LEVEL=0)
  79. endif()
  80. if (GGML_VULKAN_CHECK_RESULTS)
  81. add_compile_definitions(GGML_VULKAN_CHECK_RESULTS)
  82. endif()
  83. if (GGML_VULKAN_DEBUG)
  84. add_compile_definitions(GGML_VULKAN_DEBUG)
  85. endif()
  86. if (GGML_VULKAN_MEMORY_DEBUG)
  87. add_compile_definitions(GGML_VULKAN_MEMORY_DEBUG)
  88. endif()
  89. if (GGML_VULKAN_SHADER_DEBUG_INFO)
  90. add_compile_definitions(GGML_VULKAN_SHADER_DEBUG_INFO)
  91. endif()
  92. if (GGML_VULKAN_VALIDATE)
  93. add_compile_definitions(GGML_VULKAN_VALIDATE)
  94. endif()
  95. if (GGML_VULKAN_RUN_TESTS)
  96. add_compile_definitions(GGML_VULKAN_RUN_TESTS)
  97. endif()
  98. # Set up toolchain for host compilation whether cross-compiling or not
  99. if (CMAKE_CROSSCOMPILING)
  100. if (GGML_VULKAN_SHADERS_GEN_TOOLCHAIN)
  101. set(HOST_CMAKE_TOOLCHAIN_FILE ${GGML_VULKAN_SHADERS_GEN_TOOLCHAIN})
  102. else()
  103. detect_host_compiler()
  104. if (NOT HOST_C_COMPILER OR NOT HOST_CXX_COMPILER)
  105. message(FATAL_ERROR "Host compiler not found")
  106. else()
  107. message(STATUS "Host compiler: ${HOST_C_COMPILER} ${HOST_CXX_COMPILER}")
  108. endif()
  109. configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/host-toolchain.cmake.in ${CMAKE_BINARY_DIR}/host-toolchain.cmake @ONLY)
  110. set(HOST_CMAKE_TOOLCHAIN_FILE ${CMAKE_BINARY_DIR}/host-toolchain.cmake)
  111. endif()
  112. else()
  113. # For non-cross-compiling, use empty toolchain (use host compiler)
  114. set(HOST_CMAKE_TOOLCHAIN_FILE "")
  115. endif()
  116. # Always use ExternalProject_Add approach
  117. include(ExternalProject)
  118. # Add toolchain file if cross-compiling
  119. if (CMAKE_CROSSCOMPILING)
  120. list(APPEND VULKAN_SHADER_GEN_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${HOST_CMAKE_TOOLCHAIN_FILE})
  121. message(STATUS "vulkan-shaders-gen toolchain file: ${HOST_CMAKE_TOOLCHAIN_FILE}")
  122. endif()
  123. # Native build through ExternalProject_Add
  124. ExternalProject_Add(
  125. vulkan-shaders-gen
  126. SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders
  127. CMAKE_ARGS ${VULKAN_SHADER_GEN_CMAKE_ARGS}
  128. BUILD_COMMAND ${CMAKE_COMMAND} --build . ${VULKAN_SHADER_GEN_CMAKE_BUILD_ARGS}
  129. INSTALL_COMMAND ${CMAKE_COMMAND} --install .
  130. INSTALL_DIR ${CMAKE_BINARY_DIR}
  131. )
  132. ExternalProject_Add_StepTargets(vulkan-shaders-gen build install)
  133. set (_ggml_vk_host_suffix $<IF:$<STREQUAL:${CMAKE_HOST_SYSTEM_NAME},Windows>,.exe,>)
  134. set (_ggml_vk_genshaders_cmd ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/vulkan-shaders-gen${_ggml_vk_host_suffix})
  135. set (_ggml_vk_header ${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.hpp)
  136. set (_ggml_vk_source ${CMAKE_CURRENT_BINARY_DIR}/ggml-vulkan-shaders.cpp)
  137. set (_ggml_vk_input_dir ${CMAKE_CURRENT_SOURCE_DIR}/vulkan-shaders)
  138. set (_ggml_vk_output_dir ${CMAKE_CURRENT_BINARY_DIR}/vulkan-shaders.spv)
  139. file(GLOB _ggml_vk_shader_deps "${_ggml_vk_input_dir}/*.comp")
  140. set (_ggml_vk_shader_deps ${_ggml_vk_shader_deps} vulkan-shaders-gen)
  141. # Add build and install dependencies for all builds
  142. set(_ggml_vk_shader_deps ${_ggml_vk_shader_deps} vulkan-shaders-gen-build vulkan-shaders-gen-install)
  143. add_custom_command(
  144. OUTPUT ${_ggml_vk_header}
  145. ${_ggml_vk_source}
  146. COMMAND ${_ggml_vk_genshaders_cmd}
  147. --glslc ${Vulkan_GLSLC_EXECUTABLE}
  148. --input-dir ${_ggml_vk_input_dir}
  149. --output-dir ${_ggml_vk_output_dir}
  150. --target-hpp ${_ggml_vk_header}
  151. --target-cpp ${_ggml_vk_source}
  152. --no-clean
  153. DEPENDS ${_ggml_vk_shader_deps}
  154. COMMENT "Generate vulkan shaders"
  155. )
  156. target_sources(ggml-vulkan PRIVATE ${_ggml_vk_source} ${_ggml_vk_header})
  157. else()
  158. message(WARNING "Vulkan not found")
  159. endif()