Files
orni-attack/tools/shaders/compile_spirv.cmake
T

103 lines
3.0 KiB
CMake

# 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=<path> -D SHADERS_DIR=<path> -D HEADERS_DIR=<path> -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 <cstddef>\n"
"#include <cstdint>\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.")