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