Add shader validation automation hook
This commit is contained in:
75
cmake/ValidatePanoPainterShaders.cmake
Normal file
75
cmake/ValidatePanoPainterShaders.cmake
Normal file
@@ -0,0 +1,75 @@
|
||||
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}")
|
||||
Reference in New Issue
Block a user