# compile_shaders.cmake — invoked via `cmake -P`. # # Required cache vars: # GLSLC — path to the glslc executable. # SHADERS_DIR — path to the shaders/ directory. # # Walks SHADERS_DIR for: # _common/passthrough.vk.glsl -> _common/passthrough.vert.spv # /.vk.glsl -> /.frag.spv # # Shaders are recompiled only if the .spv is missing or older than its source. if(NOT GLSLC) message(FATAL_ERROR "compile_shaders.cmake: GLSLC not provided") endif() if(NOT SHADERS_DIR) message(FATAL_ERROR "compile_shaders.cmake: SHADERS_DIR not provided") endif() if(NOT EXISTS "${SHADERS_DIR}") message(FATAL_ERROR "compile_shaders.cmake: SHADERS_DIR does not exist: ${SHADERS_DIR}") endif() function(_compile_to_spv SOURCE STAGE OUTPUT) if(EXISTS "${OUTPUT}") file(TIMESTAMP "${SOURCE}" SRC_T "%s") file(TIMESTAMP "${OUTPUT}" OUT_T "%s") if(NOT "${SRC_T}" STREQUAL "" AND NOT "${OUT_T}" STREQUAL "") if(SRC_T LESS_EQUAL OUT_T) return() endif() endif() endif() message(STATUS "glslc (${STAGE}) ${SOURCE} -> ${OUTPUT}") execute_process( COMMAND "${GLSLC}" "-fshader-stage=${STAGE}" "${SOURCE}" -o "${OUTPUT}" RESULT_VARIABLE RC OUTPUT_VARIABLE STDOUT ERROR_VARIABLE STDERR ) if(NOT RC EQUAL 0) message(FATAL_ERROR "glslc failed for ${SOURCE}:\n${STDERR}") endif() endfunction() set(VERT_SOURCE "${SHADERS_DIR}/_common/passthrough.vk.glsl") set(VERT_OUTPUT "${SHADERS_DIR}/_common/passthrough.vert.spv") if(EXISTS "${VERT_SOURCE}") _compile_to_spv("${VERT_SOURCE}" "vert" "${VERT_OUTPUT}") else() message(WARNING "Missing shared vertex shader: ${VERT_SOURCE}") endif() file(GLOB SHADER_DIRS LIST_DIRECTORIES true RELATIVE "${SHADERS_DIR}" "${SHADERS_DIR}/*") foreach(DIR ${SHADER_DIRS}) set(ABS_DIR "${SHADERS_DIR}/${DIR}") if(NOT IS_DIRECTORY "${ABS_DIR}") continue() endif() string(SUBSTRING "${DIR}" 0 1 FIRST_CHAR) if(FIRST_CHAR STREQUAL "_" OR FIRST_CHAR STREQUAL ".") continue() endif() set(VK_SOURCE "${ABS_DIR}/${DIR}.vk.glsl") set(SPV_OUTPUT "${ABS_DIR}/${DIR}.frag.spv") if(EXISTS "${VK_SOURCE}") _compile_to_spv("${VK_SOURCE}" "frag" "${SPV_OUTPUT}") endif() endforeach()