1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Check shader code within Nit modules using the tool _glslangValidator_
19 # For this phase to work, _glslangValidator_ must be in PATH. It can be
20 # downloaded from https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
21 module glsl_validation
25 redef class ToolContext
26 # Shader code validation phase
27 var glsl_validation_phase
: Phase = new GLSLValidationPhase(self, [literal_phase
])
30 private class GLSLValidationPhase
35 fun annot_name_vertex
: String do return "glsl_vertex_shader"
36 fun annot_name_fragment
: String do return "glsl_fragment_shader"
38 # TODO support more shader types as needed
40 # Is the tool _glsllangValidator_ in path?
41 var tool_is_in_path
: nullable Bool = null
43 redef fun process_annotated_node
(nstring
, nat
)
45 var annot_name
= nat
.n_atid
.n_id
.text
46 var is_vertex
= annot_name
== annot_name_vertex
47 var is_fragment
= annot_name
== annot_name_fragment
49 # Skip if we are not interested
50 if not is_vertex
and not is_fragment
then return
52 # Only applicable on strings
53 if not nstring
isa AStringFormExpr then
54 toolcontext
.error
(nstring
.location
,
55 "Syntax error: only a string literal can be annotated as \"{annot_name}\
".")
59 # Do not double check if tool is in path
60 var in_path
= tool_is_in_path
61 if in_path
!= null then
62 if not in_path
then return
64 # Is _glslangValidator_ installed?
65 var proc_which
= new IProcess("which", "glslangValidator")
68 var status
= proc_which
.status
70 tool_is_in_path
= in_path
72 toolcontext
.warning
(nat
.location
, "glslvalidator",
73 "Warning: program \"glslangValidator\
" not in PATH, cannot validate this shader.")
78 # Get the shader source
79 var shader
= nstring
.value
82 # Copy the shader to a file
83 # TODO make it more portable
89 var path
= tmp
/ "nit_shader." + ext
91 shader
.write_to_file path
93 # Execute the validator
94 var proc_validator
= new IProcess("glslangValidator", path
)
96 var lines
= proc_validator
.read_all
.split
('\n')
100 var regex
= "[A-Z]+: ([0-9]+):([0-9]+): (.*)".to_re
102 var match
= line
.search
(regex
)
104 # Does it match an error?
105 # If not, then it should be the summary
106 if match
!= null then
107 var shader_line_no
= match
.subs
[1].to_s
.to_i
108 var msg
= match
.subs
[2].to_s
110 var line_start
= nstring
.location
.line_start
+ shader_line_no
113 var loc
= new Location(nat
.location
.file
,
114 line_start
, line_start
,
115 char_start
, char_end
)
117 toolcontext
.warning
(loc
, "glslvalidator",
118 "Shader error on {msg}")