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