# 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
#   <name>/<name>.vk.glsl               -> <name>/<name>.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()
