Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/gles3_builders.py
9819 views
1
"""Functions used to generate source files during build time"""
2
3
import os.path
4
5
from methods import generated_wrapper, print_error, to_raw_cstring
6
7
8
class GLES3HeaderStruct:
9
def __init__(self):
10
self.vertex_lines = []
11
self.fragment_lines = []
12
self.uniforms = []
13
self.fbos = []
14
self.texunits = []
15
self.texunit_names = []
16
self.ubos = []
17
self.ubo_names = []
18
self.feedbacks = []
19
20
self.vertex_included_files = []
21
self.fragment_included_files = []
22
23
self.reading = ""
24
self.line_offset = 0
25
self.vertex_offset = 0
26
self.fragment_offset = 0
27
self.variant_defines = []
28
self.variant_names = []
29
self.specialization_names = []
30
self.specialization_values = []
31
32
33
def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct, depth: int):
34
with open(filename, "r", encoding="utf-8") as fs:
35
line = fs.readline()
36
37
while line:
38
if line.find("=") != -1 and header_data.reading == "":
39
# Mode
40
eqpos = line.find("=")
41
defname = line[:eqpos].strip().upper()
42
define = line[eqpos + 1 :].strip()
43
header_data.variant_names.append(defname)
44
header_data.variant_defines.append(define)
45
line = fs.readline()
46
header_data.line_offset += 1
47
header_data.vertex_offset = header_data.line_offset
48
continue
49
50
if line.find("=") != -1 and header_data.reading == "specializations":
51
# Specialization
52
eqpos = line.find("=")
53
specname = line[:eqpos].strip()
54
specvalue = line[eqpos + 1 :]
55
header_data.specialization_names.append(specname)
56
header_data.specialization_values.append(specvalue)
57
line = fs.readline()
58
header_data.line_offset += 1
59
header_data.vertex_offset = header_data.line_offset
60
continue
61
62
if line.find("#[modes]") != -1:
63
# Nothing really, just skip
64
line = fs.readline()
65
header_data.line_offset += 1
66
header_data.vertex_offset = header_data.line_offset
67
continue
68
69
if line.find("#[specializations]") != -1:
70
header_data.reading = "specializations"
71
line = fs.readline()
72
header_data.line_offset += 1
73
header_data.vertex_offset = header_data.line_offset
74
continue
75
76
if line.find("#[vertex]") != -1:
77
header_data.reading = "vertex"
78
line = fs.readline()
79
header_data.line_offset += 1
80
header_data.vertex_offset = header_data.line_offset
81
continue
82
83
if line.find("#[fragment]") != -1:
84
header_data.reading = "fragment"
85
line = fs.readline()
86
header_data.line_offset += 1
87
header_data.fragment_offset = header_data.line_offset
88
continue
89
90
while line.find("#include ") != -1:
91
includeline = line.replace("#include ", "").strip()[1:-1]
92
93
included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
94
if included_file not in header_data.vertex_included_files and header_data.reading == "vertex":
95
header_data.vertex_included_files += [included_file]
96
if include_file_in_gles3_header(included_file, header_data, depth + 1) is None:
97
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
98
elif included_file not in header_data.fragment_included_files and header_data.reading == "fragment":
99
header_data.fragment_included_files += [included_file]
100
if include_file_in_gles3_header(included_file, header_data, depth + 1) is None:
101
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
102
103
line = fs.readline()
104
105
if line.find("uniform") != -1 and line.lower().find("texunit:") != -1:
106
# texture unit
107
texunitstr = line[line.find(":") + 1 :].strip()
108
if texunitstr == "auto":
109
texunit = "-1"
110
else:
111
texunit = str(int(texunitstr))
112
uline = line[: line.lower().find("//")]
113
uline = uline.replace("uniform", "")
114
uline = uline.replace("highp", "")
115
uline = uline.replace(";", "")
116
lines = uline.split(",")
117
for x in lines:
118
x = x.strip()
119
x = x[x.rfind(" ") + 1 :]
120
if x.find("[") != -1:
121
# unfiorm array
122
x = x[: x.find("[")]
123
124
if x not in header_data.texunit_names:
125
header_data.texunits += [(x, texunit)]
126
header_data.texunit_names += [x]
127
128
elif line.find("uniform") != -1 and line.lower().find("ubo:") != -1:
129
# uniform buffer object
130
ubostr = line[line.find(":") + 1 :].strip()
131
ubo = str(int(ubostr))
132
uline = line[: line.lower().find("//")]
133
uline = uline[uline.find("uniform") + len("uniform") :]
134
uline = uline.replace("highp", "")
135
uline = uline.replace(";", "")
136
uline = uline.replace("{", "").strip()
137
lines = uline.split(",")
138
for x in lines:
139
x = x.strip()
140
x = x[x.rfind(" ") + 1 :]
141
if x.find("[") != -1:
142
# unfiorm array
143
x = x[: x.find("[")]
144
145
if x not in header_data.ubo_names:
146
header_data.ubos += [(x, ubo)]
147
header_data.ubo_names += [x]
148
149
elif line.find("uniform") != -1 and line.find("{") == -1 and line.find(";") != -1:
150
uline = line.replace("uniform", "")
151
uline = uline.replace(";", "")
152
lines = uline.split(",")
153
for x in lines:
154
x = x.strip()
155
x = x[x.rfind(" ") + 1 :]
156
if x.find("[") != -1:
157
# unfiorm array
158
x = x[: x.find("[")]
159
160
if x not in header_data.uniforms:
161
header_data.uniforms += [x]
162
163
if (line.strip().find("out ") == 0 or line.strip().find("flat ") == 0) and line.find("tfb:") != -1:
164
uline = line.replace("flat ", "")
165
uline = uline.replace("out ", "")
166
uline = uline.replace("highp ", "")
167
uline = uline.replace(";", "")
168
uline = uline[uline.find(" ") :].strip()
169
170
if uline.find("//") != -1:
171
name, bind = uline.split("//")
172
if bind.find("tfb:") != -1:
173
name = name.strip()
174
bind = bind.replace("tfb:", "").strip()
175
header_data.feedbacks += [(name, bind)]
176
177
line = line.replace("\r", "")
178
line = line.replace("\n", "")
179
180
if header_data.reading == "vertex":
181
header_data.vertex_lines += [line]
182
if header_data.reading == "fragment":
183
header_data.fragment_lines += [line]
184
185
line = fs.readline()
186
header_data.line_offset += 1
187
188
return header_data
189
190
191
def build_gles3_header(filename: str, shader: str) -> None:
192
include_file_in_gles3_header(shader, header_data := GLES3HeaderStruct(), 0)
193
out_file_class = (
194
os.path.basename(shader).replace(".glsl", "").title().replace("_", "").replace(".", "") + "ShaderGLES3"
195
)
196
197
with generated_wrapper(filename) as file:
198
defspec = 0
199
defvariant = ""
200
201
file.write(f"""\
202
#include "drivers/gles3/shader_gles3.h"
203
204
class {out_file_class} : public ShaderGLES3 {{
205
public:
206
""")
207
208
if header_data.uniforms:
209
uniforms = ",\n\t\t".join(uniform.upper() for uniform in header_data.uniforms)
210
file.write(f"""\
211
enum Uniforms {{
212
{uniforms},
213
}};
214
215
""")
216
217
if header_data.variant_names:
218
variant_names = ",\n\t\t".join(name for name in header_data.variant_names)
219
else:
220
variant_names = "DEFAULT"
221
defvariant = " = DEFAULT"
222
file.write(f"""\
223
enum ShaderVariant {{
224
{variant_names},
225
}};
226
227
""")
228
229
if header_data.specialization_names:
230
specialization_names = ",\n\t\t".join(
231
f"{name.upper()} = {1 << index}" for index, name in enumerate(header_data.specialization_names)
232
)
233
file.write(f"""\
234
enum Specializations {{
235
{specialization_names},
236
}};
237
238
""")
239
for index, specialization_value in enumerate(header_data.specialization_values):
240
if specialization_value.strip().upper() in ["TRUE", "1"]:
241
defspec |= 1 << index
242
243
file.write(f"""\
244
_FORCE_INLINE_ bool version_bind_shader(RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
245
return _version_bind_shader(p_version, p_variant, p_specialization);
246
}}
247
248
""")
249
250
if header_data.uniforms:
251
file.write(f"""\
252
_FORCE_INLINE_ int version_get_uniform(Uniforms p_uniform, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
253
return _version_get_uniform(p_uniform, p_version, p_variant, p_specialization);
254
}}
255
256
/* clang-format off */
257
#define TRY_GET_UNIFORM(var_name) int var_name = version_get_uniform(p_uniform, p_version, p_variant, p_specialization); if (var_name < 0) return
258
/* clang-format on */
259
260
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, float p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
261
TRY_GET_UNIFORM(uniform_location);
262
glUniform1f(uniform_location, p_value);
263
}}
264
265
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, double p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
266
TRY_GET_UNIFORM(uniform_location);
267
glUniform1f(uniform_location, p_value);
268
}}
269
270
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, uint8_t p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
271
TRY_GET_UNIFORM(uniform_location);
272
glUniform1ui(uniform_location, p_value);
273
}}
274
275
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int8_t p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
276
TRY_GET_UNIFORM(uniform_location);
277
glUniform1i(uniform_location, p_value);
278
}}
279
280
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, uint16_t p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
281
TRY_GET_UNIFORM(uniform_location);
282
glUniform1ui(uniform_location, p_value);
283
}}
284
285
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int16_t p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
286
TRY_GET_UNIFORM(uniform_location);
287
glUniform1i(uniform_location, p_value);
288
}}
289
290
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, uint32_t p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
291
TRY_GET_UNIFORM(uniform_location);
292
glUniform1ui(uniform_location, p_value);
293
}}
294
295
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, int32_t p_value, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
296
TRY_GET_UNIFORM(uniform_location);
297
glUniform1i(uniform_location, p_value);
298
}}
299
300
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Color &p_color, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
301
TRY_GET_UNIFORM(uniform_location);
302
GLfloat col[4] = {{ p_color.r, p_color.g, p_color.b, p_color.a }};
303
glUniform4fv(uniform_location, 1, col);
304
}}
305
306
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Vector2 &p_vec2, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
307
TRY_GET_UNIFORM(uniform_location);
308
GLfloat vec2[2] = {{ float(p_vec2.x), float(p_vec2.y) }};
309
glUniform2fv(uniform_location, 1, vec2);
310
}}
311
312
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Size2i &p_vec2, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
313
TRY_GET_UNIFORM(uniform_location);
314
GLint vec2[2] = {{ GLint(p_vec2.x), GLint(p_vec2.y) }};
315
glUniform2iv(uniform_location, 1, vec2);
316
}}
317
318
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Vector3 &p_vec3, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
319
TRY_GET_UNIFORM(uniform_location);
320
GLfloat vec3[3] = {{ float(p_vec3.x), float(p_vec3.y), float(p_vec3.z) }};
321
glUniform3fv(uniform_location, 1, vec3);
322
}}
323
324
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Vector4 &p_vec4, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
325
TRY_GET_UNIFORM(uniform_location);
326
GLfloat vec4[4] = {{ float(p_vec4.x), float(p_vec4.y), float(p_vec4.z), float(p_vec4.w) }};
327
glUniform4fv(uniform_location, 1, vec4);
328
}}
329
330
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, float p_a, float p_b, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
331
TRY_GET_UNIFORM(uniform_location);
332
glUniform2f(uniform_location, p_a, p_b);
333
}}
334
335
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
336
TRY_GET_UNIFORM(uniform_location);
337
glUniform3f(uniform_location, p_a, p_b, p_c);
338
}}
339
340
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, float p_a, float p_b, float p_c, float p_d, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
341
TRY_GET_UNIFORM(uniform_location);
342
glUniform4f(uniform_location, p_a, p_b, p_c, p_d);
343
}}
344
345
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Transform3D &p_transform, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
346
TRY_GET_UNIFORM(uniform_location);
347
const Transform3D &tr = p_transform;
348
349
GLfloat matrix[16] = {{ /* build a 16x16 matrix */
350
(GLfloat)tr.basis.rows[0][0],
351
(GLfloat)tr.basis.rows[1][0],
352
(GLfloat)tr.basis.rows[2][0],
353
(GLfloat)0,
354
(GLfloat)tr.basis.rows[0][1],
355
(GLfloat)tr.basis.rows[1][1],
356
(GLfloat)tr.basis.rows[2][1],
357
(GLfloat)0,
358
(GLfloat)tr.basis.rows[0][2],
359
(GLfloat)tr.basis.rows[1][2],
360
(GLfloat)tr.basis.rows[2][2],
361
(GLfloat)0,
362
(GLfloat)tr.origin.x,
363
(GLfloat)tr.origin.y,
364
(GLfloat)tr.origin.z,
365
(GLfloat)1
366
}};
367
368
glUniformMatrix4fv(uniform_location, 1, false, matrix);
369
}}
370
371
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Transform2D &p_transform, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
372
TRY_GET_UNIFORM(uniform_location);
373
const Transform2D &tr = p_transform;
374
375
GLfloat matrix[16] = {{ /* build a 16x16 matrix */
376
(GLfloat)tr.columns[0][0],
377
(GLfloat)tr.columns[0][1],
378
(GLfloat)0,
379
(GLfloat)0,
380
(GLfloat)tr.columns[1][0],
381
(GLfloat)tr.columns[1][1],
382
(GLfloat)0,
383
(GLfloat)0,
384
(GLfloat)0,
385
(GLfloat)0,
386
(GLfloat)1,
387
(GLfloat)0,
388
(GLfloat)tr.columns[2][0],
389
(GLfloat)tr.columns[2][1],
390
(GLfloat)0,
391
(GLfloat)1
392
}};
393
394
glUniformMatrix4fv(uniform_location, 1, false, matrix);
395
}}
396
397
_FORCE_INLINE_ void version_set_uniform(Uniforms p_uniform, const Projection &p_matrix, RID p_version, ShaderVariant p_variant{defvariant}, uint64_t p_specialization = {defspec}) {{
398
TRY_GET_UNIFORM(uniform_location);
399
GLfloat matrix[16];
400
401
for (int i = 0; i < 4; i++) {{
402
for (int j = 0; j < 4; j++) {{
403
matrix[i * 4 + j] = p_matrix.columns[i][j];
404
}}
405
}}
406
407
glUniformMatrix4fv(uniform_location, 1, false, matrix);
408
}}
409
410
#undef TRY_GET_UNIFORM
411
412
""")
413
414
file.write("""\
415
protected:
416
virtual void _init() override {
417
""")
418
419
if header_data.uniforms:
420
uniforms = ",\n\t\t\t".join(f'"{uniform}"' for uniform in header_data.uniforms)
421
file.write(f"""\
422
static const char *_uniform_strings[] = {{
423
{uniforms}
424
}};
425
""")
426
else:
427
file.write("""\
428
static const char **_uniform_strings = nullptr;
429
""")
430
431
if header_data.variant_defines:
432
variant_count = len(header_data.variant_defines)
433
variant_defines = ",\n\t\t\t".join(f'"{define}"' for define in header_data.variant_defines)
434
file.write(f"""\
435
static const char *_variant_defines[] = {{
436
{variant_defines},
437
}};
438
""")
439
else:
440
variant_count = 1
441
file.write("""\
442
static const char **_variant_defines[] = {" "};
443
""")
444
445
if header_data.texunits:
446
texunits = ",\n\t\t\t".join(f'{{ "{name}", {texunit} }}' for name, texunit in header_data.texunits)
447
file.write(f"""\
448
static TexUnitPair _texunit_pairs[] = {{
449
{texunits},
450
}};
451
""")
452
else:
453
file.write("""\
454
static TexUnitPair *_texunit_pairs = nullptr;
455
""")
456
457
if header_data.ubos:
458
ubos = ",\n\t\t\t".join(f'{{ "{name}", {ubo} }}' for name, ubo in header_data.ubos)
459
file.write(f"""\
460
static UBOPair _ubo_pairs[] = {{
461
{ubos},
462
}};
463
""")
464
else:
465
file.write("""\
466
static UBOPair *_ubo_pairs = nullptr;
467
""")
468
469
if header_data.specialization_names:
470
specializations = ",\n\t\t\t".join(
471
f'{{ "{name}", {"true" if header_data.specialization_values[index].strip().upper() in ["TRUE", "1"] else "false"} }}'
472
for index, name in enumerate(header_data.specialization_names)
473
)
474
file.write(f"""\
475
static Specialization _spec_pairs[] = {{
476
{specializations},
477
}};
478
""")
479
else:
480
file.write("""\
481
static Specialization *_spec_pairs = nullptr;
482
""")
483
484
if header_data.feedbacks:
485
feedbacks = ",\n\t\t\t".join(
486
f'{{ "{name}", {0 if spec not in header_data.specialization_names else (1 << header_data.specialization_names.index(spec))} }}'
487
for name, spec in header_data.feedbacks
488
)
489
file.write(f"""\
490
static const Feedback _feedbacks[] = {{
491
{feedbacks},
492
}};
493
""")
494
else:
495
file.write("""\
496
static const Feedback *_feedbacks = nullptr;
497
""")
498
499
file.write(f"""\
500
static const char _vertex_code[] = {{
501
{to_raw_cstring(header_data.vertex_lines)}
502
}};
503
504
static const char _fragment_code[] = {{
505
{to_raw_cstring(header_data.fragment_lines)}
506
}};
507
508
_setup(_vertex_code, _fragment_code, "{out_file_class}",
509
{len(header_data.uniforms)}, _uniform_strings, {len(header_data.ubos)}, _ubo_pairs,
510
{len(header_data.feedbacks)}, _feedbacks, {len(header_data.texunits)}, _texunit_pairs,
511
{len(header_data.specialization_names)}, _spec_pairs, {variant_count}, _variant_defines);
512
}}
513
}};
514
""")
515
516
517
def build_gles3_headers(target, source, env):
518
env.NoCache(target)
519
for src in source:
520
build_gles3_header(f"{src}.gen.h", str(src))
521
522