1## Copyright 2020 Intel Corporation 2## SPDX-License-Identifier: BSD-3-Clause 3 4############################################################################### 5## Generic ISPC macros/options ################################################ 6############################################################################### 7 8option(BUILD_GPU "Build GPU code paths?" ON) 9 10set(ISPC_INCLUDE_DIR "") 11macro (include_directories_ispc) 12 list(APPEND ISPC_INCLUDE_DIR ${ARGN}) 13endmacro () 14 15set(ISPC_DEFINITIONS "") 16macro (add_definitions_ispc) 17 list(APPEND ISPC_DEFINITIONS ${ARGN}) 18endmacro () 19 20############################################################################### 21## CPU specific macros/options ################################################ 22############################################################################### 23 24## Find ISPC ## 25find_program(ISPC_EXECUTABLE ispc HINTS ${ISPC_DIR_HINT} DOC "Path to the ISPC executable.") 26if (NOT ISPC_EXECUTABLE) 27 message(FATAL_ERROR "Could not find ISPC. Exiting.") 28else() 29 message(STATUS "Found Intel(r) Implicit SPMD Compiler (Intel(r) ISPC): ${ISPC_EXECUTABLE}") 30endif() 31 32## ISPC config options ## 33 34option(ISPC_FAST_MATH "enable ISPC fast-math optimizations" OFF) 35mark_as_advanced(ISPC_FAST_MATH) 36 37set(ISPC_ADDRESSING 32 CACHE STRING "32 vs 64 bit addressing in ispc") 38set_property(CACHE ISPC_ADDRESSING PROPERTY STRINGS 32 64) 39mark_as_advanced(ISPC_ADDRESSING) 40 41macro(define_ispc_isa_options ISA_NAME) 42 set(ISPC_TARGET_${ISA_NAME} ${ARGV1} CACHE STRING "ispc target used for ${ISA_NAME} ISA") 43 set_property(CACHE ISPC_TARGET_${ISA_NAME} PROPERTY STRINGS ${ARGN} NONE) 44 #mark_as_advanced(ISPC_TARGET_${ISA_NAME}) 45endmacro() 46 47# TODO: query ISPC for available targets to be added here 48define_ispc_isa_options(SSE4 sse4-i32x4 sse4-i32x8 sse4-i16x8 sse4-i8x16) 49define_ispc_isa_options(AVX avx1-i32x8 avx1-i32x4 avx1-i32x16 avx1-i64x4) 50define_ispc_isa_options(AVX2 avx2-i32x8 avx2-i32x4 avx2-i32x16 avx2-i64x4) 51define_ispc_isa_options(AVX512KNL avx512knl-i32x16) 52define_ispc_isa_options(AVX512SKX avx512skx-i32x16 avx512skx-i32x8) 53 54macro(append_ispc_target_list ISA_NAME) 55 set(_TARGET_NAME ISPC_TARGET_${ISA_NAME}) 56 if (NOT ${_TARGET_NAME} STREQUAL "NONE") 57 list(APPEND ISPC_TARGET_LIST ${${_TARGET_NAME}}) 58 endif() 59 unset(_TARGET_NAME) 60endmacro() 61 62unset(ISPC_TARGET_LIST) 63append_ispc_target_list(SSE4) 64append_ispc_target_list(AVX) 65append_ispc_target_list(AVX2) 66append_ispc_target_list(AVX512KNL) 67append_ispc_target_list(AVX512SKX) 68 69## Macros ## 70 71macro (ispc_compile) 72 set(ISPC_ADDITIONAL_ARGS "") 73 # Check if CPU target is passed externally 74 if (NOT ISPC_TARGET_CPU) 75 set(ISPC_TARGETS ${ISPC_TARGET_LIST}) 76 else() 77 set(ISPC_TARGETS ${ISPC_TARGET_CPU}) 78 endif() 79 80 set(ISPC_TARGET_EXT ${CMAKE_CXX_OUTPUT_EXTENSION}) 81 string(REPLACE ";" "," ISPC_TARGET_ARGS "${ISPC_TARGETS}") 82 83 set(ISPC_ARCHITECTURE "x86-64") 84 85 set(ISPC_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR}) 86 include_directories(${ISPC_TARGET_DIR}) 87 88 if(ISPC_INCLUDE_DIR) 89 string(REPLACE ";" ";-I;" ISPC_INCLUDE_DIR_PARMS "${ISPC_INCLUDE_DIR}") 90 set(ISPC_INCLUDE_DIR_PARMS "-I" ${ISPC_INCLUDE_DIR_PARMS}) 91 endif() 92 93 #CAUTION: -O0/1 -g with ispc seg faults 94 set(ISPC_FLAGS_DEBUG "-g" CACHE STRING "ISPC Debug flags") 95 mark_as_advanced(ISPC_FLAGS_DEBUG) 96 set(ISPC_FLAGS_RELEASE "-O3" CACHE STRING "ISPC Release flags") 97 mark_as_advanced(ISPC_FLAGS_RELEASE) 98 set(ISPC_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "ISPC Release with Debug symbols flags") 99 mark_as_advanced(ISPC_FLAGS_RELWITHDEBINFO) 100 if (WIN32 OR "${CMAKE_BUILD_TYPE}" STREQUAL "Release") 101 set(ISPC_OPT_FLAGS ${ISPC_FLAGS_RELEASE}) 102 elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 103 set(ISPC_OPT_FLAGS ${ISPC_FLAGS_DEBUG}) 104 else() 105 set(ISPC_OPT_FLAGS ${ISPC_FLAGS_RELWITHDEBINFO}) 106 endif() 107 108 # turn space sparated list into ';' separated list 109 string(REPLACE " " ";" ISPC_OPT_FLAGS "${ISPC_OPT_FLAGS}") 110 111 if (NOT WIN32) 112 list(APPEND ISPC_ADDITIONAL_ARGS --pic) 113 endif() 114 115 if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 116 list(APPEND ISPC_ADDITIONAL_ARGS --opt=disable-assertions) 117 endif() 118 119 if (ISPC_FAST_MATH) 120 list(APPEND ISPC_ADDITIONAL_ARGS --opt=fast-math) 121 endif() 122 123 set(ISPC_OBJECTS "") 124 125 foreach(src ${ARGN}) 126 get_filename_component(fname ${src} NAME_WE) 127 128 set(outdir "${ISPC_TARGET_DIR}/local_ispc") 129 set(input ${CMAKE_CURRENT_SOURCE_DIR}/${src}) 130 131 set(deps "") 132 if (EXISTS ${outdir}/${fname}.dev.idep) 133 file(READ ${outdir}/${fname}.dev.idep contents) 134 string(REPLACE " " ";" contents "${contents}") 135 string(REPLACE ";" "\\\\;" contents "${contents}") 136 string(REPLACE "\n" ";" contents "${contents}") 137 foreach(dep ${contents}) 138 if (EXISTS ${dep}) 139 set(deps ${deps} ${dep}) 140 endif (EXISTS ${dep}) 141 endforeach(dep ${contents}) 142 endif () 143 144 set(results "${outdir}/${fname}.dev${ISPC_TARGET_EXT}") 145 # if we have multiple targets add additional object files 146 list(LENGTH ISPC_TARGETS NUM_TARGETS) 147 if (NUM_TARGETS GREATER 1) 148 foreach(target ${ISPC_TARGETS}) 149 string(REPLACE "-i8x16" "" target ${target}) 150 string(REPLACE "-i32x4" "" target ${target}) 151 string(REPLACE "-i32x8" "" target ${target}) 152 string(REPLACE "-i32x16" "" target ${target}) 153 string(REPLACE "-i64x4" "" target ${target}) 154 string(REPLACE "-i64x8" "" target ${target}) 155 string(REPLACE "avx1" "avx" target ${target}) 156 list(APPEND results "${outdir}/${fname}.dev_${target}${ISPC_TARGET_EXT}") 157 endforeach() 158 endif() 159 160 add_custom_command( 161 OUTPUT ${results} ${ISPC_TARGET_DIR}/${fname}_ispc.h 162 COMMAND ${CMAKE_COMMAND} -E make_directory ${outdir} 163 COMMAND ${ISPC_EXECUTABLE} 164 ${ISPC_DEFINITIONS} 165 -I ${CMAKE_CURRENT_SOURCE_DIR} 166 ${ISPC_INCLUDE_DIR_PARMS} 167 --arch=${ISPC_ARCHITECTURE} 168 --addressing=${ISPC_ADDRESSING} 169 ${ISPC_OPT_FLAGS} 170 --target=${ISPC_TARGET_ARGS} 171 --woff 172 ${ISPC_ADDITIONAL_ARGS} 173 -h ${ISPC_TARGET_DIR}/${fname}_ispc.h 174 -MMM ${outdir}/${fname}.dev.idep 175 -o ${outdir}/${fname}.dev${ISPC_TARGET_EXT} 176 ${input} 177 DEPENDS ${input} ${deps} 178 COMMENT "Building ISPC object ${outdir}/${fname}.dev${ISPC_TARGET_EXT}" 179 ) 180 181 set(ISPC_OBJECTS ${ISPC_OBJECTS} ${results}) 182 endforeach() 183endmacro() 184 185function(ispc_target_add_sources name) 186 ## Split-out C/C++ from ISPC files ## 187 188 set(ISPC_SOURCES "") 189 set(OTHER_SOURCES "") 190 191 foreach(src ${ARGN}) 192 get_filename_component(ext ${src} EXT) 193 if (ext STREQUAL ".ispc") 194 set(ISPC_SOURCES ${ISPC_SOURCES} ${src}) 195 else() 196 set(OTHER_SOURCES ${OTHER_SOURCES} ${src}) 197 endif() 198 endforeach() 199 200 ## Get existing target definitions and include dirs ## 201 202 # NOTE(jda) - This needs work: BUILD_INTERFACE vs. INSTALL_INTERFACE isn't 203 # handled automatically. 204 205 #get_property(TARGET_DEFINITIONS TARGET ${name} PROPERTY COMPILE_DEFINITIONS) 206 #get_property(TARGET_INCLUDES TARGET ${name} PROPERTY INCLUDE_DIRECTORIES) 207 208 #set(ISPC_DEFINITIONS ${TARGET_DEFINITIONS}) 209 #set(ISPC_INCLUDE_DIR ${TARGET_INCLUDES}) 210 211 ## Compile ISPC files ## 212 213 ispc_compile(${ISPC_SOURCES}) 214 215 ## Set final sources on target ## 216 217 get_property(TARGET_SOURCES TARGET ${name} PROPERTY SOURCES) 218 list(APPEND TARGET_SOURCES ${ISPC_OBJECTS} ${OTHER_SOURCES}) 219 set_target_properties(${name} PROPERTIES SOURCES "${TARGET_SOURCES}") 220endfunction() 221 222 223############################################################################### 224## GPU specific macros/options ################################################ 225############################################################################### 226 227find_program(ISPC_EXECUTABLE_GPU ispc-gpu DOC "Path to GEN enabled ISPC.") 228 229define_ispc_isa_options(GEN genx-x8 genx-x16) 230 231set(ISPC_GENX_ADDITIONAL_ARGS "" CACHE STRING "extra arguments to pass to ISPC for GEN targets") 232 233macro (ispc_compile_gpu parent_target output_prefix) 234 if(ISPC_INCLUDE_DIR) 235 string(REPLACE ";" ";-I;" ISPC_INCLUDE_DIR_PARMS "${ISPC_INCLUDE_DIR}") 236 set(ISPC_INCLUDE_DIR_PARMS "-I" ${ISPC_INCLUDE_DIR_PARMS}) 237 endif() 238 239 # Check If GPU target is passed externally 240 if (NOT ISPC_TARGET_GEN) 241 set(ISPC_TARGET_GEN "genx-x8") 242 endif() 243 244 foreach(src ${ARGN}) 245 get_filename_component(fname ${src} NAME_WE) 246 get_filename_component(dir ${src} PATH) 247 248 message(STATUS "ISPC-GPU source file to be compiled: ${src}") 249 250 set(input ${CMAKE_CURRENT_LIST_DIR}/${dir}/${fname}.ispc) 251 252 if (NOT ISPC_TARGET_DIR) 253 set(ISPC_TARGET_DIR ${CMAKE_BINARY_DIR}) 254 endif() 255 256 set(outdir ${ISPC_TARGET_DIR}) 257 258 set(ISPC_PROGRAM_COUNT 16) 259 if ("${ISPC_TARGET_GEN}" STREQUAL "genx-x8") 260 set(ISPC_PROGRAM_COUNT 8) 261 endif() 262 263 set(ISPC_GENX_FLAGS_DEBUG "-g" CACHE STRING "ISPC GENX Debug flags") 264 mark_as_advanced(ISPC_GENX_FLAGS_DEBUG) 265 set(ISPC_GENX_FLAGS_RELEASE "-O3" CACHE STRING "ISPC GENX Release flags") 266 mark_as_advanced(ISPC_GENX_FLAGS_RELEASE) 267 set(ISPC_GENX_FLAGS_RELWITHDEBINFO "-O2 -g" CACHE STRING "ISPC GENX Release with Debug symbols flags") 268 mark_as_advanced(ISPC_GENX_FLAGS_RELWITHDEBINFO) 269 270 if (WIN32 OR "${CMAKE_BUILD_TYPE}" STREQUAL "Release") 271 set(ISPC_GENX_OPT_FLAGS ${ISPC_GENX_FLAGS_RELEASE}) 272 elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 273 set(ISPC_GENX_OPT_FLAGS ${ISPC_GENX_FLAGS_DEBUG}) 274 else() 275 set(ISPC_GENX_OPT_FLAGS ${ISPC_GENX_FLAGS_RELWITHDEBINFO}) 276 endif() 277 # turn space sparated list into ';' separated list 278 string(REPLACE " " ";" ISPC_GENX_OPT_FLAGS "${ISPC_GENX_OPT_FLAGS}") 279 280 # Additional flags passed by user 281 if (NOT ISPC_GENX_ADDITIONAL_ARGS) 282 set(ISPC_GENX_ADDITIONAL_ARGS "") 283 endif() 284 285 # Output ISPC module format passed by user 286 if (NOT ISPC_GENX_FORMAT) 287 set (ISPC_GENX_FORMAT "spv") 288 endif() 289 290 if (ISPC_GENX_FORMAT STREQUAL "spv") 291 set(ISPC_GPU_TARGET_NAME ${parent_target}_${fname}_spv) 292 set(ISPC_GPU_OUTPUT_OPT "--emit-spirv") 293 set(result "${outdir}/${output_prefix}${parent_target}.spv") 294 elseif (ISPC_GENX_FORMAT STREQUAL "zebin") 295 set(ISPC_GPU_TARGET_NAME ${parent_target}_${fname}_bin) 296 set(ISPC_GPU_OUTPUT_OPT "--emit-zebin") 297 set(result "${outdir}/${output_prefix}${parent_target}.bin") 298 endif() 299 300 add_custom_target(${ISPC_GPU_TARGET_NAME} 301 COMMAND ${ISPC_EXECUTABLE_GPU} 302 -I ${CMAKE_CURRENT_SOURCE_DIR} 303 ${ISPC_INCLUDE_DIR_PARMS} 304 ${ISPC_GENX_OPT_FLAGS} 305 -DISPC_GPU 306 ${ISPC_DEFINITIONS} 307 --addressing=64 308 --target=${ISPC_TARGET_GEN} 309 ${ISPC_GPU_OUTPUT_OPT} 310 --woff 311 ${ISPC_GENX_ADDITIONAL_ARGS} 312 -o ${result} 313 ${input} 314 COMMENT "Building ISPC GPU object ${result}" 315 ) 316 317 add_dependencies(${parent_target} ${ISPC_GPU_TARGET_NAME}) 318 319 target_compile_definitions(${parent_target} 320 PRIVATE 321 ISPC_GPU_PROGRAM_COUNT=${ISPC_PROGRAM_COUNT} 322 ) 323 324 unset(ISPC_PROGRAM_COUNT) 325 endforeach() 326endmacro() 327 328############################################################################### 329## Generic kernel compilation ################################################# 330############################################################################### 331 332function(add_ispc_kernel TARGET_NAME SOURCE PREFIX) 333if (WIN32) 334 set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 335endif() 336 add_library(${TARGET_NAME} SHARED) 337 set_target_properties(${TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX) 338 set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${PREFIX}${TARGET_NAME}") 339 if (WIN32) 340 target_link_libraries(${TARGET_NAME} PRIVATE msvcrt.lib) 341 if (ISPC_BUILD) 342 target_link_libraries(${TARGET_NAME} PRIVATE ${ISPCRT_LIB}) 343 else() 344 target_link_libraries(${TARGET_NAME} PRIVATE ispcrt::ispcrt) 345 endif() 346 endif() 347 ispc_target_add_sources(${TARGET_NAME} ${SOURCE}) 348 if (BUILD_GPU) 349 ispc_compile_gpu(${TARGET_NAME} "${PREFIX}" ${SOURCE}) 350 endif() 351endfunction() 352