]> git.tdb.fi Git - libs/gl.git/blob - scripts/builtin_funcs.py
Guard against hitting the end of the array in get_gl_type
[libs/gl.git] / scripts / builtin_funcs.py
1 #!/usr/bin/python3
2
3 import sys
4
5 traits = {
6         "sampler1D": { "CDim": 1, "IDim": 1 },
7         "sampler2D": { "CDim": 2, "IDim": 2 },
8         "sampler3D": { "CDim": 3, "IDim": 3 },
9         "sampler1DArray": { "CDim": 2, "IDim": 2 },
10         "sampler2DArray": { "CDim": 3, "IDim": 3 },
11         "samplerCube": { "CDim": 3, "IDim": 2 },
12         "samplerCubeArray": { "CDim": 4, "IDim": 3 },
13         "sampler1DShadow": { "CDim": 3, "IDim": 1 },
14         "sampler2DShadow": { "CDim": 3, "IDim": 2 },
15         "samplerCubeShadow": { "CDim": 4, "IDim": 2 },
16         "sampler1DArrayShadow": { "CDim": 3, "IDim": 2 },
17         "sampler2DArrayShadow": { "CDim": 4, "IDim": 3 },
18         "samplerCubeArrayShadow": { "IDim": 3 },
19         "float": { "Base": "float", "Dim": 1, "Vec": "vec", "Mat": "mat" },
20         "vec2": { "Base": "float", "Dim": 2 },
21         "vec3": { "Base": "float", "Dim": 3 },
22         "vec4": { "Base": "float", "Dim": 4 },
23         "int": { "Base": "int", "Dim": 1, "Vec": "ivec" },
24         "ivec2": { "Base": "int", "Dim": 2 },
25         "ivec3": { "Base": "int", "Dim": 3 },
26         "ivec4": { "Base": "int", "Dim": 4 },
27         "bool": { "Base": "bool", "Dim": 1, "Vec": "bvec" },
28         "bvec2": { "Base": "bool", "Dim": 2 },
29         "bvec3": { "Base": "bool", "Dim": 3 },
30         "bvec4": { "Base": "bool", "Dim": 4 },
31         "mat2": { "Cols": 2, "Rows": 2 },
32         "mat3": { "Cols": 3, "Rows": 3 },
33         "mat4": { "Cols": 4, "Rows": 4 },
34         "mat2x3": { "Cols": 2, "Rows": 3 },
35         "mat3x2": { "Cols": 3, "Rows": 2 },
36         "mat2x4": { "Cols": 2, "Rows": 4 },
37         "mat4x2": { "Cols": 4, "Rows": 2 },
38         "mat3x4": { "Cols": 3, "Rows": 4 },
39         "mat4x3": { "Cols": 4, "Rows": 3 }
40 }
41
42 float32vectypes = ("vec2", "vec3", "vec4")
43 float32types = ("float",)+float32vectypes
44 floattypes = float32types
45 int32vectypes = ("ivec2", "ivec3", "ivec4")
46 int32types = ("int",)+int32vectypes
47 signedtypes = floattypes+int32types
48 arithmetictypes = signedtypes
49 arithmeticvectypes = float32vectypes+int32vectypes
50 boolvectypes = ("bvec2", "bvec3", "bvec4")
51 squarematrixtypes = ("mat2", "mat3", "mat4")
52 matrixtypes = squarematrixtypes+("mat2x3", "mat3x2", "mat2x4", "mat4x2", "mat3x4", "mat4x3")
53 flatsamplertypes = ("sampler1D", "sampler2D", "sampler3D", "sampler1DArray", "sampler2DArray")
54 colorsamplertypes = flatsamplertypes+("samplerCube", "samplerCubeArray")
55 shadowsamplertypes = ("sampler1DShadow", "sampler2DShadow", "samplerCubeShadow", "sampler1DArrayShadow", "sampler2DArrayShadow", "samplerCubeArrayShadow")
56 samplertypes = colorsamplertypes+shadowsamplertypes
57 shared_funcs = [
58         # Trigonometric
59         ("T radians(T degrees)", float32types),
60         ("T degrees(T radians)", float32types),
61         ("T sin(T angle)", float32types),
62         ("T cos(T angle)", float32types),
63         ("T tan(T angle)", float32types),
64         ("T asin(T x)", float32types),
65         ("T acos(T x)", float32types),
66         ("T atan(T y, T x)", float32types),
67         ("T atan(T y_over_x)", float32types),
68         ("T sinh(T angle)", float32types),
69         ("T cosh(T angle)", float32types),
70         ("T tanh(T angle)", float32types),
71         ("T asinh(T x)", float32types),
72         ("T acosh(T x)", float32types),
73         ("T atanh(T x)", float32types),
74
75         # Exponential
76         ("T pow(T x, T y)", float32types),
77         ("T exp(T x)", float32types),
78         ("T log(T x)", float32types),
79         ("T exp2(T x)", float32types),
80         ("T log2(T x)", float32types),
81         ("T sqrt(T x)", floattypes),
82         ("T inversesqrt(T x)", floattypes),
83
84         # Common
85         ("T abs(T x)", signedtypes),
86         ("T sign(T x)", signedtypes),
87         ("T floor(T x)", floattypes),
88         ("T trunc(T x)", floattypes),
89         ("T round(T x)", floattypes),
90         ("T roundEven(T x)", floattypes),
91         ("T ceil(T x)", floattypes),
92         ("T fract(T x)", floattypes),
93         ("T mod(T x, T y)", floattypes),
94         ("T mod(T x, T::Base y)", floattypes),
95         ("T modf(T x, out T y)", floattypes),
96         ("T min(T x, T y)", arithmetictypes),
97         ("T min(T x, T::Base y)", arithmetictypes),
98         ("T max(T x, T y)", arithmetictypes),
99         ("T max(T x, T::Base y)", arithmetictypes),
100         ("T clamp(T x, T minVal, T maxVal)", arithmetictypes),
101         ("T clamp(T x, T::Base minVal, T::Base maxVal)", arithmetictypes),
102         ("T mix(T x, T y, T a)", floattypes),
103         ("T mix(T x, T y, T::Base a)", floattypes),
104         ("T mix(T x, T y, bool[T::Dim] a)", arithmetictypes),
105         ("T step(T edge, T x)", floattypes),
106         ("T step(T::Base edge, T x)", floattypes),
107         ("T smoothstep(T edge0, T edge1, T x)", floattypes),
108         ("T smoothstep(T::Base edge0, T::Base edge1, T x)", floattypes),
109         ("bool[T::Dim] isnan(T x)", floattypes),
110         ("bool[T::Dim] isinf(T x)", floattypes),
111         ("int[T::Dim] floatBitsToInt(T value)", float32types),
112         ("T intBitsToFloat(int[T::Dim] value)", float32types),
113         ("T fma(T a, T b, T c)", floattypes),
114         ("T frexp(T x, out int[T::Dim] exp)", floattypes),
115         ("T ldexp(T x, int[T::Dim] exp)", floattypes),
116
117         # Geometric
118         ("T::Base length(T x)", floattypes),
119         ("T::Base distance(T p0, T p1)", floattypes),
120         ("T::Base dot(T x, T y)", floattypes),
121         "vec3 cross(vec3 x)",
122         ("T normalize(T x)", floattypes),
123         ("T faceforward(T N, T I, T Nref)", floattypes),
124         ("T reflect(T N, T I)", floattypes),
125         ("T refract(T N, T I, float eta)", floattypes),
126
127         # Matrix
128         ("T matrixCompMult(T x, T y)", matrixtypes),
129         ("T outerProduct(float[T::Rows] c, float[T::Cols] r)", matrixtypes),
130         ("float[T::Rows, T::Cols] transpose(T m)", matrixtypes),
131         ("T determinant(T m)", squarematrixtypes),
132         ("T inverse(T m)", squarematrixtypes),
133
134         # Vector relational
135         ("bool[T::Dim] lessThan(T x, T y)", arithmeticvectypes),
136         ("bool[T::Dim] lessThanEqual(T x, T y)", arithmeticvectypes),
137         ("bool[T::Dim] greaterThan(T x, T y)", arithmeticvectypes),
138         ("bool[T::Dim] greaterThanEqual(T x, T y)", arithmeticvectypes),
139         ("bool[T::Dim] equal(T x, T y)", arithmeticvectypes),
140         ("bool[T::Dim] notEqual(T x, T y)", arithmeticvectypes),
141         ("bool any(T x)", boolvectypes),
142         ("bool all(T x)", boolvectypes),
143         ("bool not(T x)", boolvectypes),
144
145         # Integer
146         ("void imulExtended(T x, T y, out T msb, out T lsb)", int32types),
147         ("T bitfieldExtract(T value, int offset, int bits)", int32types),
148         ("T bitfieldInsert(T value, T insert, int offset, int bits)", int32types),
149         ("T bitfieldReverse(T value)", int32types),
150         ("T bitCount(T value)", int32types),
151         ("int[T::Dim] findLSB(T value)", int32types),
152         ("int[T::Dim] findMSB(T value)", int32types),
153
154         # Texture
155         ("int[T::IDim] textureSize(T sampler, int lod)", samplertypes),
156         ("vec4 texture(T sampler, float[T::CDim] P)", colorsamplertypes),
157         ("float texture(T sampler, float[T::CDim] P)", tuple(s for s in shadowsamplertypes if "CubeArray" not in s)),
158         "float texture(samplerCubeArrayShadow sampler, vec4 P, float compare)",
159         ("vec4 textureLod(T sampler, float[T::CDim] P, float lod)", colorsamplertypes),
160         ("vec4 texelFetch(T sampler, int[T::CDim] P, int lod)", flatsamplertypes)
161 ]
162
163 fragment_funcs = [
164         # Derivative
165         ("T dFdx(T p)", float32types),
166         ("T dFdy(T p)", float32types),
167         ("T dFdxFine(T p)", float32types),
168         ("T dFdyFine(T p)", float32types),
169         ("T dFdxCoarse(T p)", float32types),
170         ("T dFdyCoarse(T p)", float32types),
171         ("T fwidth(T p)", float32types),
172         ("T fwidthFine(T p)", float32types),
173         ("T fwidthCoarse(T p)", float32types),
174
175         # Interpolation
176         ("T interpolateAtCentroid(T interpolant)", float32types),
177         ("T interpolateAtSample(T interpolant, int sample)", float32types),
178         ("T interpolateAtOffset(T interpolant, vec2 offset)", float32types)
179 ]
180
181 def tokenize(code):
182         out_tokens = []
183         token = ""
184         for i, c in enumerate(code):
185                 if c.isspace():
186                         continue
187
188                 token += c
189                 n = code[i+1] if i+1<len(code) else " "
190
191                 end = False
192                 if token[0].isalpha():
193                         if not n.isalnum():
194                                 end = True
195                 else:
196                         if n.isalnum() or n.isspace():
197                                 end = True
198
199                 if end:
200                         out_tokens.append(token)
201                         token = ""
202
203         return out_tokens
204
205 def expand_tokens(tokens, i, gentype):
206         t = tokens[i]
207         if t=="T":
208                 t = gentype
209         if i+1<len(tokens):
210                 if tokens[i+1]=="::":
211                         return (traits[t][tokens[i+2]], 3)
212                 elif tokens[i+1]=="[":
213                         sub, advance = expand_tokens(tokens, i+2, gentype)
214                         if tokens[i+2+advance]==",":
215                                 sub2, adv2 = expand_tokens(tokens, i+3+advance, gentype)
216                                 advance += 1+adv2
217                                 if sub2==sub:
218                                         t = traits[t]["Mat"]+str(sub)
219                                 else:
220                                         t = traits[t]["Mat"]+"{}x{}".format(sub, sub2)
221                         elif sub>1:
222                                 t = traits[t]["Vec"]+str(sub)
223                         return (t, 3+advance)
224         return (t, 1)
225
226 def expand_template(template, gentype):
227         result = ""
228         special = True
229         tokens = tokenize(template)
230         i = 0
231         while i<len(tokens):
232                 t, advance = expand_tokens(tokens, i, gentype)
233
234                 if not special and t[0].isalpha():
235                         result += " "
236                 special = not t[0].isalpha()
237
238                 if t==",":
239                         result += ", "
240                 else:
241                         result += t
242
243                 i += advance
244
245         return result
246
247 def generate_functions(funcs):
248         out_lines = []
249         generated = set()
250         for f in funcs:
251                 if type(f)==tuple:
252                         for t in f[1]:
253                                 decl = expand_template(f[0], t)
254                                 if not decl in generated:
255                                         out_lines.append(decl+";\n")
256                                         generated.add(decl)
257                 else:
258                         out_lines.append(f+";\n")
259
260         return out_lines
261
262 def generate_file(fn):
263         out_lines = []
264         skip = False
265         for line in open(fn):
266                 if not skip:
267                         out_lines.append(line)
268                 if "BEGIN BUILTIN FUNCTIONS" in line:
269                         skip = True
270                         out_lines += generate_functions(shared_funcs)
271                 elif "BEGIN BUILTIN FRAGMENT FUNCTIONS" in line:
272                         skip = True
273                         out_lines += generate_functions(fragment_funcs)
274                 elif "END BUILTIN" in line:
275                         out_lines.append(line)
276                         skip = False
277
278         open(fn, "w").writelines(out_lines)
279
280 if __name__=="__main__":
281         generate_file(sys.argv[1])