function(engine_read_shader_includes shaderpath include_dirs includes_list_out) file(READ "${shaderpath}" contents) string(REGEX REPLACE ";" "\\\\;" contents "${contents}") string(REGEX REPLACE "\r" "" contents "${contents}") string(REGEX REPLACE "\n" ";" contents "${contents}") set(_local_list "${${includes_list_out}}") foreach (line ${contents}) string(FIND "${line}" "#include" out) if("${out}" EQUAL 0) string(SUBSTRING ${line} 8 -1 include_file) string(REPLACE " " "" include_file ${include_file}) string(REPLACE "\"" "" include_file ${include_file}) foreach (dir ${include_dirs}) if (EXISTS "${dir}/${include_file}") list(APPEND _local_list "${dir}/${include_file}") break() endif() endforeach() endif() endforeach() list(REMOVE_DUPLICATES _local_list) set(${includes_list_out} ${_local_list} PARENT_SCOPE) endfunction() function(engine_generate_shaders TARGET) if (NOT DEFINED video_SOURCE_DIR) message(FATAL_ERROR "video project not found") endif() set(SHADERTOOL_INCLUDE_DIRS) list(APPEND SHADERTOOL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/shaders) set(DEPENDENCIES) engine_resolve_dependencies(${TARGET} DEPENDENCIES) foreach (D ${DEPENDENCIES}) if (EXISTS ${${D}_SOURCE_DIR}/shaders) list(APPEND SHADERTOOL_INCLUDE_DIRS "${${D}_SOURCE_DIR}/shaders") endif() endforeach() list(REMOVE_DUPLICATES SHADERTOOL_INCLUDE_DIRS) set(SHADERTOOL_INCLUDE_DIRS_PARAM) foreach (IDIR ${SHADERTOOL_INCLUDE_DIRS}) list(APPEND SHADERTOOL_INCLUDE_DIRS_PARAM "-I") list(APPEND SHADERTOOL_INCLUDE_DIRS_PARAM "${IDIR}") endforeach() set(GEN_DIR ${GENERATE_DIR}/shaders/${TARGET}/) engine_generated_library(${TARGET}-shaders) target_include_directories(${TARGET}-shaders PUBLIC ${GEN_DIR}) target_link_libraries(${TARGET}-shaders PUBLIC video) foreach (SHADER ${ARGN}) generate_shader(${TARGET}-shaders ${SHADER} ${GEN_DIR} ${SHADERTOOL_INCLUDE_DIRS}) endforeach() target_link_libraries(${TARGET} PUBLIC ${TARGET}-shaders) endfunction() function(generate_shader TARGET SHADER GEN_DIR SHADERTOOL_INCLUDE_DIRS) set(SRC_DIR ${ROOT_DIR}/src/tools/shadertool) set(SHADER_TEMPLATE_HDR_FILE ${SRC_DIR}/ShaderTemplate.h.in) set(SHADER_TEMPLATE_CPP_FILE ${SRC_DIR}/ShaderTemplate.cpp.in) set(SHADER_TEMPLATE_CONST_FILE ${SRC_DIR}/ShaderConstantsTemplate.h.in) set(SHADER_TEMPLATE_UB_FILE ${SRC_DIR}/UniformBufferTemplate.h.in) set(SHADER_SEARCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shaders) set(FOUND_SHADER_FILES) if (EXISTS ${SHADER_SEARCH_DIR}/${SHADER}.frag AND EXISTS ${SHADER_SEARCH_DIR}/${SHADER}.vert) list(APPEND FOUND_SHADER_FILES ${SHADER_SEARCH_DIR}/${SHADER}.frag ${SHADER_SEARCH_DIR}/${SHADER}.vert) if (EXISTS ${SHADER_SEARCH_DIR}/${SHADER}.geom) list(APPEND FOUND_SHADER_FILES ${SHADER_SEARCH_DIR}/${SHADER}.geom) endif() endif() if (EXISTS ${SHADER_SEARCH_DIR}/${SHADER}.comp) list(APPEND FOUND_SHADER_FILES ${SHADER_SEARCH_DIR}/${SHADER}.comp) endif() if (FOUND_SHADER_FILES) set(SHADER_DEPENDENCIES) foreach (FOUND_SHADER_FILE ${FOUND_SHADER_FILES}) engine_read_shader_includes(${FOUND_SHADER_FILE} "${SHADERTOOL_INCLUDE_DIRS}" SHADER_DEPENDENCIES) endforeach() convert_to_camel_case(${SHADER} SHADER_NAME_CAMEL_CASE) set(SHADER_TARGET_HDR_FILE "${GEN_DIR}${SHADER_NAME_CAMEL_CASE}Shader.h") set(SHADER_TARGET_CPP_FILE "${GEN_DIR}${SHADER_NAME_CAMEL_CASE}Shader.cpp") set(SHADER_TARGET_CONST_FILE "${GEN_DIR}${SHADER_NAME_CAMEL_CASE}ShaderConstants.h") set(MD5_VAR "") string(MD5 MD5_VAR ${SHADER_TARGET_HDR_FILE}) if (NOT CMAKE_CROSSCOMPILING) set(_args ${SHADERTOOL_INCLUDE_DIRS_PARAM} --shader ${SHADER_SEARCH_DIR}/${SHADER} --constantstemplate ${SHADER_TEMPLATE_CONST_FILE} --headertemplate ${SHADER_TEMPLATE_HDR_FILE} --sourcetemplate ${SHADER_TEMPLATE_CPP_FILE} --buffertemplate ${SHADER_TEMPLATE_UB_FILE} --sourcedir ${GEN_DIR} ) if (USE_GLSLANG_VALIDATOR AND GLSLANG_EXECUTABLE) list(APPEND _args --glslang ${GLSLANG_EXECUTABLE}) endif() add_custom_command( OUTPUT ${SHADER_TARGET_HDR_FILE} ${SHADER_TARGET_CPP_FILE} ${SHADER_TARGET_CONST_FILE} IMPLICIT_DEPENDS C ${FOUND_SHADER_FILES} COMMENT "Validate ${SHADER}" COMMAND ${CMAKE_COMMAND} -E env "APP_HOMEPATH=${CMAKE_CURRENT_BINARY_DIR}/" "LSAN_OPTIONS=exitcode=0" $ ${_args} DEPENDS shadertool ${FOUND_SHADER_FILES} ${SHADER_DEPENDENCIES} ${SHADER_TEMPLATE_HDR_FILE} ${SHADER_TEMPLATE_CPP_FILE} ${SHADER_TEMPLATE_UB_FILE} ${SHADER_TEMPLATE_CONST_FILE} ) elseif (NOT EXISTS "${SHADER_TARGET_HDR_FILE}") message(WARNING "Source code generation must be done by native toolchain") else() set_source_files_properties(${SHADER_TARGET_HDR_FILE} ${SHADER_TARGET_CPP_FILE} ${SHADER_TARGET_CONST_FILE} PROPERTIES GENERATED TRUE) endif() target_sources(${TARGET} PRIVATE ${SHADER_TARGET_HDR_FILE} ${SHADER_TARGET_CPP_FILE} ${SHADER_TARGET_CONST_FILE}) else() message(FATAL_ERROR "Could not find any shader files for ${SHADER} and target '${TARGET}'") endif() endfunction()