# compile_spirv.cmake # Compila shaders GLSL a SPIR-V i genera headers C++ embedibles. # Multiplataforma: Windows, macOS, Linux (no requereix bash ni xxd). # # Invocat per CMakeLists.txt amb: # cmake -D GLSLC= -D SHADERS_DIR= -D HEADERS_DIR= -P compile_spirv.cmake # # També es pot executar manualment des de l'arrel del projecte: # cmake -D GLSLC=glslc -D SHADERS_DIR=shaders \ # -D HEADERS_DIR=source/core/rendering/gpu/spv \ # -P tools/shaders/compile_spirv.cmake cmake_minimum_required(VERSION 3.10) cmake_policy(SET CMP0007 NEW) # Llista de shaders a compilar: font relativa a SHADERS_DIR set(SHADER_SOURCES "line.vert.glsl" "line.frag.glsl" "postfx.vert.glsl" "postfx.frag.glsl" "bloom.frag.glsl" ) # Nom de la variable C++ per a cada shader (mateix ordre). # UPPER_CASE perquè són constexpr globals (.clang-tidy ho exigeix). set(SHADER_VARS "LINE_VERT_SPV" "LINE_FRAG_SPV" "POSTFX_VERT_SPV" "POSTFX_FRAG_SPV" "BLOOM_FRAG_SPV" ) # Flags extra per a cada shader (necessaris perquè .vert.glsl/.frag.glsl no s'infereixen) set(SHADER_FLAGS "-fshader-stage=vert" "-fshader-stage=frag" "-fshader-stage=vert" "-fshader-stage=frag" "-fshader-stage=frag" ) list(LENGTH SHADER_SOURCES NUM_SHADERS) math(EXPR LAST_IDX "${NUM_SHADERS} - 1") foreach(IDX RANGE ${LAST_IDX}) list(GET SHADER_SOURCES ${IDX} SRC_NAME) list(GET SHADER_VARS ${IDX} VAR) list(GET SHADER_FLAGS ${IDX} EXTRA_FLAG) # Derivem el nom del header a partir de la variable: LINE_VERT_SPV → line_vert_spv.h string(TOLOWER "${VAR}" HDR_BASE) set(SRC "${SHADERS_DIR}/${SRC_NAME}") set(SPV "${HEADERS_DIR}/${HDR_BASE}.spv") set(HDR "${HEADERS_DIR}/${HDR_BASE}.h") message(STATUS "Compilant ${SRC} ...") if(EXTRA_FLAG) execute_process( COMMAND "${GLSLC}" "${EXTRA_FLAG}" -O "${SRC}" -o "${SPV}" RESULT_VARIABLE GLSLC_RESULT ERROR_VARIABLE GLSLC_ERROR ) else() execute_process( COMMAND "${GLSLC}" -O "${SRC}" -o "${SPV}" RESULT_VARIABLE GLSLC_RESULT ERROR_VARIABLE GLSLC_ERROR ) endif() if(NOT GLSLC_RESULT EQUAL 0) message(FATAL_ERROR "glslc ha fallat per a ${SRC}:\n${GLSLC_ERROR}") endif() # Llegim el binari SPV com a hex (sense separadors) i el dividim en bytes. file(READ "${SPV}" HEX_DATA HEX) string(REGEX MATCHALL ".." BYTES "${HEX_DATA}") list(LENGTH BYTES NUM_BYTES) set(ARRAY_BODY "") foreach(BYTE ${BYTES}) string(APPEND ARRAY_BODY " 0x${BYTE},\n") endforeach() file(WRITE "${HDR}" "#pragma once\n" "#include \n" "#include \n" "static const uint8_t ${VAR}[] = {\n" "${ARRAY_BODY}" "};\n" "static const size_t ${VAR}_SIZE = ${NUM_BYTES};\n" ) file(REMOVE "${SPV}") message(STATUS " -> ${HDR} (${NUM_BYTES} bytes)") endforeach() message(STATUS "Shaders SPIR-V compilats correctament.")