Files
panopainter/cmake/ValidatePanoPainterShaders.cmake

76 lines
3.3 KiB
CMake

if(NOT DEFINED PP_SHADER_DIR)
message(FATAL_ERROR "PP_SHADER_DIR is required")
endif()
file(REAL_PATH "${PP_SHADER_DIR}" pp_shader_dir)
if(NOT IS_DIRECTORY "${pp_shader_dir}")
message(FATAL_ERROR "Shader directory does not exist: ${pp_shader_dir}")
endif()
file(GLOB_RECURSE pp_shader_files
"${pp_shader_dir}/*.glsl")
if(NOT pp_shader_files)
message(FATAL_ERROR "No shader files found under: ${pp_shader_dir}")
endif()
set(pp_shader_errors "")
set(pp_top_level_count 0)
set(pp_include_count 0)
foreach(pp_shader_file IN LISTS pp_shader_files)
file(RELATIVE_PATH pp_shader_rel "${pp_shader_dir}" "${pp_shader_file}")
file(READ "${pp_shader_file}" pp_shader_contents)
string(REGEX MATCHALL "#[ \t]*include[ \t]+\"[^\"]+\"" pp_include_lines "${pp_shader_contents}")
foreach(pp_include_line IN LISTS pp_include_lines)
string(REGEX REPLACE ".*\"([^\"]+)\".*" "\\1" pp_include_path "${pp_include_line}")
if(pp_include_path MATCHES "^/")
list(APPEND pp_shader_errors "${pp_shader_rel}: include path must be relative: ${pp_include_path}")
endif()
if(pp_include_path MATCHES "^[A-Za-z]:")
list(APPEND pp_shader_errors "${pp_shader_rel}: include path must not be drive-absolute: ${pp_include_path}")
endif()
if(pp_include_path MATCHES "\\.\\.")
list(APPEND pp_shader_errors "${pp_shader_rel}: include path must not traverse parent directories: ${pp_include_path}")
endif()
if(NOT EXISTS "${pp_shader_dir}/${pp_include_path}")
list(APPEND pp_shader_errors "${pp_shader_rel}: missing include: ${pp_include_path}")
endif()
endforeach()
if(pp_shader_rel MATCHES "^include/")
math(EXPR pp_include_count "${pp_include_count} + 1")
if(pp_shader_contents MATCHES "\\[\\[(vertex|fragment)\\]\\]")
list(APPEND pp_shader_errors "${pp_shader_rel}: include shaders must not declare stage markers")
endif()
else()
math(EXPR pp_top_level_count "${pp_top_level_count} + 1")
string(REGEX MATCHALL "\\[\\[vertex\\]\\]" pp_vertex_markers "${pp_shader_contents}")
string(REGEX MATCHALL "\\[\\[fragment\\]\\]" pp_fragment_markers "${pp_shader_contents}")
list(LENGTH pp_vertex_markers pp_vertex_count)
list(LENGTH pp_fragment_markers pp_fragment_count)
if(NOT pp_vertex_count EQUAL 1)
list(APPEND pp_shader_errors "${pp_shader_rel}: expected exactly one [[vertex]] marker")
endif()
if(NOT pp_fragment_count EQUAL 1)
list(APPEND pp_shader_errors "${pp_shader_rel}: expected exactly one [[fragment]] marker")
endif()
string(FIND "${pp_shader_contents}" "[[vertex]]" pp_vertex_pos)
string(FIND "${pp_shader_contents}" "[[fragment]]" pp_fragment_pos)
if(pp_vertex_pos GREATER_EQUAL 0 AND pp_fragment_pos GREATER_EQUAL 0 AND NOT pp_vertex_pos LESS pp_fragment_pos)
list(APPEND pp_shader_errors "${pp_shader_rel}: [[vertex]] marker must appear before [[fragment]]")
endif()
endif()
endforeach()
if(pp_shader_errors)
list(JOIN pp_shader_errors "\n" pp_shader_error_text)
message(FATAL_ERROR "Shader validation failed:\n${pp_shader_error_text}")
endif()
message(STATUS "Validated ${pp_top_level_count} shader programs and ${pp_include_count} shader includes under ${pp_shader_dir}")