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