Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/glsl_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 RDHeaderStruct:
9
def __init__(self):
10
self.vertex_lines = []
11
self.fragment_lines = []
12
self.compute_lines = []
13
14
self.vertex_included_files = []
15
self.fragment_included_files = []
16
self.compute_included_files = []
17
18
self.reading = ""
19
self.line_offset = 0
20
self.vertex_offset = 0
21
self.fragment_offset = 0
22
self.compute_offset = 0
23
24
25
def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth: int) -> RDHeaderStruct:
26
with open(filename, "r", encoding="utf-8") as fs:
27
line = fs.readline()
28
29
while line:
30
index = line.find("//")
31
if index != -1:
32
line = line[:index]
33
34
if line.find("#[vertex]") != -1:
35
header_data.reading = "vertex"
36
line = fs.readline()
37
header_data.line_offset += 1
38
header_data.vertex_offset = header_data.line_offset
39
continue
40
41
if line.find("#[fragment]") != -1:
42
header_data.reading = "fragment"
43
line = fs.readline()
44
header_data.line_offset += 1
45
header_data.fragment_offset = header_data.line_offset
46
continue
47
48
if line.find("#[compute]") != -1:
49
header_data.reading = "compute"
50
line = fs.readline()
51
header_data.line_offset += 1
52
header_data.compute_offset = header_data.line_offset
53
continue
54
55
while line.find("#include ") != -1:
56
includeline = line.replace("#include ", "").strip()[1:-1]
57
58
if includeline.startswith("thirdparty/"):
59
included_file = os.path.relpath(includeline)
60
61
else:
62
included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
63
64
if included_file not in header_data.vertex_included_files and header_data.reading == "vertex":
65
header_data.vertex_included_files += [included_file]
66
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
67
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
68
elif included_file not in header_data.fragment_included_files and header_data.reading == "fragment":
69
header_data.fragment_included_files += [included_file]
70
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
71
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
72
elif included_file not in header_data.compute_included_files and header_data.reading == "compute":
73
header_data.compute_included_files += [included_file]
74
if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
75
print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
76
77
line = fs.readline()
78
79
line = line.replace("\r", "").replace("\n", "")
80
81
if header_data.reading == "vertex":
82
header_data.vertex_lines += [line]
83
if header_data.reading == "fragment":
84
header_data.fragment_lines += [line]
85
if header_data.reading == "compute":
86
header_data.compute_lines += [line]
87
88
line = fs.readline()
89
header_data.line_offset += 1
90
91
return header_data
92
93
94
def build_rd_header(filename: str, shader: str) -> None:
95
include_file_in_rd_header(shader, header_data := RDHeaderStruct(), 0)
96
class_name = os.path.basename(shader).replace(".glsl", "").title().replace("_", "").replace(".", "") + "ShaderRD"
97
98
with generated_wrapper(filename) as file:
99
file.write(f"""\
100
#include "servers/rendering/renderer_rd/shader_rd.h"
101
102
class {class_name} : public ShaderRD {{
103
public:
104
{class_name}() {{
105
""")
106
107
if header_data.compute_lines:
108
file.write(f"""\
109
static const char *_vertex_code = nullptr;
110
static const char *_fragment_code = nullptr;
111
static const char _compute_code[] = {{
112
{to_raw_cstring(header_data.compute_lines)}
113
}};
114
""")
115
else:
116
file.write(f"""\
117
static const char _vertex_code[] = {{
118
{to_raw_cstring(header_data.vertex_lines)}
119
}};
120
static const char _fragment_code[] = {{
121
{to_raw_cstring(header_data.fragment_lines)}
122
}};
123
static const char *_compute_code = nullptr;
124
""")
125
126
file.write(f"""\
127
setup(_vertex_code, _fragment_code, _compute_code, "{class_name}");
128
}}
129
}};
130
""")
131
132
133
def build_rd_headers(target, source, env):
134
env.NoCache(target)
135
for src in source:
136
build_rd_header(f"{src}.gen.h", str(src))
137
138
139
class RAWHeaderStruct:
140
def __init__(self):
141
self.code = ""
142
143
144
def include_file_in_raw_header(filename: str, header_data: RAWHeaderStruct, depth: int) -> None:
145
with open(filename, "r", encoding="utf-8") as fs:
146
line = fs.readline()
147
148
while line:
149
while line.find("#include ") != -1:
150
includeline = line.replace("#include ", "").strip()[1:-1]
151
152
included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
153
include_file_in_raw_header(included_file, header_data, depth + 1)
154
155
line = fs.readline()
156
157
header_data.code += line
158
line = fs.readline()
159
160
161
def build_raw_header(filename: str, shader: str) -> None:
162
include_file_in_raw_header(shader, header_data := RAWHeaderStruct(), 0)
163
164
with generated_wrapper(filename) as file:
165
file.write(f"""\
166
static const char {os.path.basename(shader).replace(".glsl", "_shader_glsl")}[] = {{
167
{to_raw_cstring(header_data.code)}
168
}};
169
""")
170
171
172
def build_raw_headers(target, source, env):
173
env.NoCache(target)
174
for src in source:
175
build_raw_header(f"{src}.gen.h", str(src))
176
177