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