glsl_builders.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. """Functions used to generate source files during build time"""
  2. import os.path
  3. from methods import generated_wrapper, print_error, to_raw_cstring
  4. class RDHeaderStruct:
  5. def __init__(self):
  6. self.vertex_lines = []
  7. self.fragment_lines = []
  8. self.compute_lines = []
  9. self.vertex_included_files = []
  10. self.fragment_included_files = []
  11. self.compute_included_files = []
  12. self.reading = ""
  13. self.line_offset = 0
  14. self.vertex_offset = 0
  15. self.fragment_offset = 0
  16. self.compute_offset = 0
  17. def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth: int) -> RDHeaderStruct:
  18. with open(filename, "r", encoding="utf-8") as fs:
  19. line = fs.readline()
  20. while line:
  21. index = line.find("//")
  22. if index != -1:
  23. line = line[:index]
  24. if line.find("#[vertex]") != -1:
  25. header_data.reading = "vertex"
  26. line = fs.readline()
  27. header_data.line_offset += 1
  28. header_data.vertex_offset = header_data.line_offset
  29. continue
  30. if line.find("#[fragment]") != -1:
  31. header_data.reading = "fragment"
  32. line = fs.readline()
  33. header_data.line_offset += 1
  34. header_data.fragment_offset = header_data.line_offset
  35. continue
  36. if line.find("#[compute]") != -1:
  37. header_data.reading = "compute"
  38. line = fs.readline()
  39. header_data.line_offset += 1
  40. header_data.compute_offset = header_data.line_offset
  41. continue
  42. while line.find("#include ") != -1:
  43. includeline = line.replace("#include ", "").strip()[1:-1]
  44. if includeline.startswith("thirdparty/"):
  45. included_file = os.path.relpath(includeline)
  46. else:
  47. included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
  48. if included_file not in header_data.vertex_included_files and header_data.reading == "vertex":
  49. header_data.vertex_included_files += [included_file]
  50. if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
  51. print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
  52. elif included_file not in header_data.fragment_included_files and header_data.reading == "fragment":
  53. header_data.fragment_included_files += [included_file]
  54. if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
  55. print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
  56. elif included_file not in header_data.compute_included_files and header_data.reading == "compute":
  57. header_data.compute_included_files += [included_file]
  58. if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
  59. print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
  60. line = fs.readline()
  61. line = line.replace("\r", "").replace("\n", "")
  62. if header_data.reading == "vertex":
  63. header_data.vertex_lines += [line]
  64. if header_data.reading == "fragment":
  65. header_data.fragment_lines += [line]
  66. if header_data.reading == "compute":
  67. header_data.compute_lines += [line]
  68. line = fs.readline()
  69. header_data.line_offset += 1
  70. return header_data
  71. def build_rd_header(filename: str, shader: str) -> None:
  72. include_file_in_rd_header(shader, header_data := RDHeaderStruct(), 0)
  73. class_name = os.path.basename(shader).replace(".glsl", "").title().replace("_", "").replace(".", "") + "ShaderRD"
  74. with generated_wrapper(filename) as file:
  75. file.write(f"""\
  76. #include "servers/rendering/renderer_rd/shader_rd.h"
  77. class {class_name} : public ShaderRD {{
  78. public:
  79. {class_name}() {{
  80. """)
  81. if header_data.compute_lines:
  82. file.write(f"""\
  83. static const char *_vertex_code = nullptr;
  84. static const char *_fragment_code = nullptr;
  85. static const char _compute_code[] = {{
  86. {to_raw_cstring(header_data.compute_lines)}
  87. }};
  88. """)
  89. else:
  90. file.write(f"""\
  91. static const char _vertex_code[] = {{
  92. {to_raw_cstring(header_data.vertex_lines)}
  93. }};
  94. static const char _fragment_code[] = {{
  95. {to_raw_cstring(header_data.fragment_lines)}
  96. }};
  97. static const char *_compute_code = nullptr;
  98. """)
  99. file.write(f"""\
  100. setup(_vertex_code, _fragment_code, _compute_code, "{class_name}");
  101. }}
  102. }};
  103. """)
  104. def build_rd_headers(target, source, env):
  105. env.NoCache(target)
  106. for src in source:
  107. build_rd_header(f"{src}.gen.h", str(src))
  108. class RAWHeaderStruct:
  109. def __init__(self):
  110. self.code = ""
  111. def include_file_in_raw_header(filename: str, header_data: RAWHeaderStruct, depth: int) -> None:
  112. with open(filename, "r", encoding="utf-8") as fs:
  113. line = fs.readline()
  114. while line:
  115. while line.find("#include ") != -1:
  116. includeline = line.replace("#include ", "").strip()[1:-1]
  117. included_file = os.path.relpath(os.path.dirname(filename) + "/" + includeline)
  118. include_file_in_raw_header(included_file, header_data, depth + 1)
  119. line = fs.readline()
  120. header_data.code += line
  121. line = fs.readline()
  122. def build_raw_header(filename: str, shader: str) -> None:
  123. include_file_in_raw_header(shader, header_data := RAWHeaderStruct(), 0)
  124. with generated_wrapper(filename) as file:
  125. file.write(f"""\
  126. static const char {os.path.basename(shader).replace(".glsl", "_shader_glsl")}[] = {{
  127. {to_raw_cstring(header_data.code)}
  128. }};
  129. """)
  130. def build_raw_headers(target, source, env):
  131. env.NoCache(target)
  132. for src in source:
  133. build_raw_header(f"{src}.gen.h", str(src))