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