Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/glsl_builders.py
20852 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 RDHeaderStruct:
9
def __init__(self):
10
self.vertex_lines = []
11
self.fragment_lines = []
12
self.compute_lines = []
13
self.raygen_lines = []
14
self.any_hit_lines = []
15
self.closest_hit_lines = []
16
self.miss_lines = []
17
self.intersection_lines = []
18
19
self.vertex_included_files = []
20
self.fragment_included_files = []
21
self.compute_included_files = []
22
self.raygen_included_files = []
23
self.any_hit_included_files = []
24
self.closest_hit_included_files = []
25
self.miss_included_files = []
26
self.intersection_included_files = []
27
28
self.reading = ""
29
self.line_offset = 0
30
self.vertex_offset = 0
31
self.fragment_offset = 0
32
self.compute_offset = 0
33
self.raygen_offset = 0
34
self.any_hit_offset = 0
35
self.closest_hit_offset = 0
36
self.miss_offset = 0
37
self.intersection_offset = 0
38
39
40
def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth: int) -> RDHeaderStruct:
41
with open(filename, "r", encoding="utf-8") as fs:
42
line = fs.readline()
43
44
while line:
45
index = line.find("//")
46
if index != -1:
47
line = line[:index]
48
49
if line.find("#[vertex]") != -1:
50
header_data.reading = "vertex"
51
line = fs.readline()
52
header_data.line_offset += 1
53
header_data.vertex_offset = header_data.line_offset
54
continue
55
56
if line.find("#[fragment]") != -1:
57
header_data.reading = "fragment"
58
line = fs.readline()
59
header_data.line_offset += 1
60
header_data.fragment_offset = header_data.line_offset
61
continue
62
63
if line.find("#[compute]") != -1:
64
header_data.reading = "compute"
65
line = fs.readline()
66
header_data.line_offset += 1
67
header_data.compute_offset = header_data.line_offset
68
continue
69
70
if line.find("#[raygen]") != -1:
71
header_data.reading = "raygen"
72
line = fs.readline()
73
header_data.line_offset += 1
74
header_data.raygen_offset = header_data.line_offset
75
continue
76
77
if line.find("#[any_hit]") != -1:
78
header_data.reading = "any_hit"
79
line = fs.readline()
80
header_data.line_offset += 1
81
header_data.any_hit_offset = header_data.line_offset
82
continue
83
84
if line.find("#[closest_hit]") != -1:
85
header_data.reading = "closest_hit"
86
line = fs.readline()
87
header_data.line_offset += 1
88
header_data.closest_hit_offset = header_data.line_offset
89
continue
90
91
if line.find("#[miss]") != -1:
92
header_data.reading = "miss"
93
line = fs.readline()
94
header_data.line_offset += 1
95
header_data.miss_offset = header_data.line_offset
96
continue
97
98
if line.find("#[intersection]") != -1:
99
header_data.reading = "intersection"
100
line = fs.readline()
101
header_data.line_offset += 1
102
header_data.intersection_offset = header_data.line_offset
103
continue
104
105
while line.find("#include ") != -1:
106
includeline = line.replace("#include ", "").strip()[1:-1]
107
108
if includeline.startswith("thirdparty/"):
109
included_file = os.path.relpath(includeline)
110
111
else:
112
included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
113
114
if included_file not in header_data.vertex_included_files and header_data.reading == "vertex":
115
header_data.vertex_included_files += [included_file]
116
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
117
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
118
elif included_file not in header_data.fragment_included_files and header_data.reading == "fragment":
119
header_data.fragment_included_files += [included_file]
120
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
121
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
122
elif included_file not in header_data.compute_included_files and header_data.reading == "compute":
123
header_data.compute_included_files += [included_file]
124
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
125
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
126
elif included_file not in header_data.raygen_included_files and header_data.reading == "raygen":
127
header_data.raygen_included_files += [included_file]
128
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
129
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
130
elif included_file not in header_data.any_hit_included_files and header_data.reading == "any_hit":
131
header_data.any_hit_included_files += [included_file]
132
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
133
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
134
elif (
135
included_file not in header_data.closest_hit_included_files and header_data.reading == "closest_hit"
136
):
137
header_data.closest_hit_included_files += [included_file]
138
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
139
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
140
elif included_file not in header_data.miss_included_files and header_data.reading == "miss":
141
header_data.miss_included_files += [included_file]
142
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
143
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
144
elif (
145
included_file not in header_data.intersection_included_files
146
and header_data.reading == "intersection"
147
):
148
header_data.intersection_included_files += [included_file]
149
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
150
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
151
152
line = fs.readline()
153
154
line = line.replace("\r", "").replace("\n", "")
155
156
if header_data.reading == "vertex":
157
header_data.vertex_lines += [line]
158
if header_data.reading == "fragment":
159
header_data.fragment_lines += [line]
160
if header_data.reading == "compute":
161
header_data.compute_lines += [line]
162
if header_data.reading == "raygen":
163
header_data.raygen_lines += [line]
164
if header_data.reading == "any_hit":
165
header_data.any_hit_lines += [line]
166
if header_data.reading == "closest_hit":
167
header_data.closest_hit_lines += [line]
168
if header_data.reading == "miss":
169
header_data.miss_lines += [line]
170
if header_data.reading == "intersection":
171
header_data.intersection_lines += [line]
172
173
line = fs.readline()
174
header_data.line_offset += 1
175
176
return header_data
177
178
179
def build_rd_header(filename: str, shader: str) -> None:
180
include_file_in_rd_header(shader, header_data := RDHeaderStruct(), 0)
181
class_name = os.path.basename(shader).replace(".glsl", "").title().replace("_", "").replace(".", "") + "ShaderRD"
182
183
with generated_wrapper(filename) as file:
184
file.write(f"""\
185
#include "servers/rendering/renderer_rd/shader_rd.h"
186
187
class {class_name} : public ShaderRD {{
188
public:
189
{class_name}() {{
190
""")
191
192
if header_data.raygen_lines:
193
file.write(f"""\
194
static const char _raygen_code[] = {{
195
{to_raw_cstring(header_data.raygen_lines)}
196
}};
197
static const char _any_hit_code[] = {{
198
{to_raw_cstring(header_data.any_hit_lines)}
199
}};
200
static const char _closest_hit_code[] = {{
201
{to_raw_cstring(header_data.closest_hit_lines)}
202
}};
203
static const char _miss_code[] = {{
204
{to_raw_cstring(header_data.miss_lines)}
205
}};
206
static const char _intersection_code[] = {{
207
{to_raw_cstring(header_data.intersection_lines)}
208
}};
209
setup_raytracing(_raygen_code, _any_hit_code, _closest_hit_code, _miss_code, _intersection_code, "{class_name}");
210
""")
211
elif header_data.compute_lines:
212
file.write(f"""\
213
static const char *_vertex_code = nullptr;
214
static const char *_fragment_code = nullptr;
215
static const char _compute_code[] = {{
216
{to_raw_cstring(header_data.compute_lines)}
217
}};
218
setup(_vertex_code, _fragment_code, _compute_code, "{class_name}");
219
""")
220
else:
221
file.write(f"""\
222
static const char _vertex_code[] = {{
223
{to_raw_cstring(header_data.vertex_lines)}
224
}};
225
static const char _fragment_code[] = {{
226
{to_raw_cstring(header_data.fragment_lines)}
227
}};
228
static const char *_compute_code = nullptr;
229
setup(_vertex_code, _fragment_code, _compute_code, "{class_name}");
230
""")
231
232
file.write("""\
233
}
234
};
235
""")
236
237
238
def build_rd_headers(target, source, env):
239
env.NoCache(target)
240
for src in source:
241
build_rd_header(f"{src}.gen.h", str(src))
242
243
244
class RAWHeaderStruct:
245
def __init__(self):
246
self.code = ""
247
248
249
def include_file_in_raw_header(filename: str, header_data: RAWHeaderStruct, depth: int) -> None:
250
with open(filename, "r", encoding="utf-8") as fs:
251
line = fs.readline()
252
253
while line:
254
while line.find("#include ") != -1:
255
includeline = line.replace("#include ", "").strip()[1:-1]
256
257
included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
258
include_file_in_raw_header(included_file, header_data, depth + 1)
259
260
line = fs.readline()
261
262
header_data.code += line
263
line = fs.readline()
264
265
266
def build_raw_header(filename: str, shader: str) -> None:
267
include_file_in_raw_header(shader, header_data := RAWHeaderStruct(), 0)
268
269
with generated_wrapper(filename) as file:
270
file.write(f"""\
271
static const char {os.path.basename(shader).replace(".glsl", "_shader_glsl")}[] = {{
272
{to_raw_cstring(header_data.code)}
273
}};
274
""")
275
276
277
def build_raw_headers(target, source, env):
278
env.NoCache(target)
279
for src in source:
280
build_raw_header(f"{src}.gen.h", str(src))
281
282