Skip to content

Commit ac39fdf

Browse files
committed
[ET-VK][codegen][fix] Split codegen and SPIR-V compilation into separate steps in gen_vulkan_spv
## Changes * As title * Also removed caching mechanism for the codegen step for simplicity, and ad hoc latency testing didn't reveal any improvements from caching this step ## Motivation As written, gen_vulkan_spv has a potential bug where generated header files are out of date when SPIR-V compilation occurs. Due to the parallelization of SPIR-V compilation, it's possible for a generated GLSL file to be processed before header files that it uses are generated. The fix is to separate the steps of code generation and SPIR-V compilation, such that code generation finished before SPIR-V compilation occurs. Differential Revision: [D77034022](https://our.internmc.facebook.com/intern/diff/D77034022/) ghstack-source-id: 291681597 Pull Request resolved: #11823
1 parent 496cb05 commit ac39fdf

File tree

1 file changed

+68
-60
lines changed

1 file changed

+68
-60
lines changed

backends/vulkan/runtime/gen_vulkan_spv.py

Lines changed: 68 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -845,85 +845,88 @@ def generateSPV( # noqa: C901
845845
) -> Dict[str, str]:
846846
output_file_map = {}
847847

848-
def process_shader(shader_paths_pair):
848+
def generate_src_file(shader_paths_pair):
849+
# Extract components from the input tuple
850+
# name of .glsl, .glslh, or .h to be generated
849851
src_file_name = shader_paths_pair[0]
850-
852+
# path of template file used for codegen
851853
src_file_fullpath = shader_paths_pair[1][0]
854+
# args to be used for codegen
852855
codegen_params = shader_paths_pair[1][1]
853856

854-
requires_codegen = True
855-
if "YAML_SRC_FULLPATH" not in codegen_params:
856-
requires_codegen = False
857-
857+
# Assume that generated files will have the same file extension as the
858+
# source template file.
858859
src_file_ext = extract_extension(src_file_fullpath)
859860
out_file_ext = src_file_ext
860-
compile_spv = False
861861

862-
if out_file_ext == "glsl":
863-
compile_spv = True
862+
# Construct generated file name
863+
gen_out_path = os.path.join(output_dir, f"{src_file_name}.{out_file_ext}")
864+
# Construct path of cached generated file
865+
cached_gen_out_path = os.path.join(
866+
cache_dir, f"{src_file_name}.{out_file_ext}"
867+
)
868+
869+
# Execute codegen to generate the output file
870+
with codecs.open(src_file_fullpath, "r", encoding="utf-8") as input_file:
871+
input_text = input_file.read()
872+
input_text = self.maybe_replace_u16vecn(input_text)
873+
output_text = preprocess(input_text, codegen_params)
874+
875+
with codecs.open(gen_out_path, "w", encoding="utf-8") as output_file:
876+
output_file.write(output_text)
877+
878+
if cache_dir is not None:
879+
# Store the generated file in the cache for SPIR-V compilation
880+
shutil.copyfile(gen_out_path, cached_gen_out_path)
864881

882+
def compile_spirv(shader_paths_pair):
883+
# Extract components from the input tuple
884+
# name of generated .glsl, .glslh, or .h
885+
src_file_name = shader_paths_pair[0]
886+
# path of template file used for codegen
887+
src_file_fullpath = shader_paths_pair[1][0]
888+
889+
# Assume that generated files will have the same file extension as the
890+
# source template file.
891+
src_file_ext = extract_extension(src_file_fullpath)
892+
out_file_ext = src_file_ext
893+
894+
# Infer name of generated file (created by generate_src_file)
865895
gen_out_path = os.path.join(output_dir, f"{src_file_name}.{out_file_ext}")
866-
spv_out_path = None
867-
if compile_spv:
868-
spv_out_path = os.path.join(output_dir, f"{src_file_name}.spv")
896+
897+
# Only proceed if GLSL -> SPIR-V compilation is required for this file
898+
if out_file_ext != "glsl":
899+
return (None, gen_out_path)
900+
901+
# Construct name of SPIR-V file to be compiled, if needed
902+
spv_out_path = os.path.join(output_dir, f"{src_file_name}.spv")
869903

870904
if cache_dir is not None:
871-
cached_src_file_fullpath = os.path.join(
872-
cache_dir, os.path.basename(src_file_fullpath) + ".t"
873-
)
874-
cached_codegen_yaml = os.path.join(cache_dir, f"{src_file_name}.yaml")
905+
# Construct the file names of cached SPIR-V file to check if they exist
906+
# in the cache.
875907
cached_gen_out_path = os.path.join(
876908
cache_dir, f"{src_file_name}.{out_file_ext}"
877909
)
878910
cached_spv_out_path = os.path.join(cache_dir, f"{src_file_name}.spv")
911+
912+
# Only use cached artifacts if all of the expected artifacts are present
879913
if (
880914
not force_rebuild
881-
and os.path.exists(cached_src_file_fullpath)
882915
and os.path.exists(cached_gen_out_path)
883-
and (not requires_codegen or os.path.exists(cached_codegen_yaml))
884-
and (not compile_spv or os.path.exists(cached_spv_out_path))
916+
and os.path.exists(cached_spv_out_path)
885917
):
886-
current_checksum = self.get_md5_checksum(src_file_fullpath)
887-
cached_checksum = self.get_md5_checksum(cached_src_file_fullpath)
888-
yaml_unchanged = True
889-
if requires_codegen:
890-
yaml_file_fullpath = codegen_params["YAML_SRC_FULLPATH"]
891-
current_yaml_checksum = self.get_md5_checksum(
892-
yaml_file_fullpath
893-
)
894-
cached_yaml_checksum = self.get_md5_checksum(
895-
cached_codegen_yaml
896-
)
897-
yaml_unchanged = current_yaml_checksum == cached_yaml_checksum
898-
# If the cached source GLSL template is the same as the current GLSL
899-
# source file, then assume that the generated GLSL and SPIR-V will
900-
# not have changed. In that case, just copy over the GLSL and SPIR-V
901-
# files from the cache.
902-
if yaml_unchanged and current_checksum == cached_checksum:
903-
shutil.copyfile(cached_gen_out_path, gen_out_path)
904-
if compile_spv:
905-
shutil.copyfile(cached_spv_out_path, spv_out_path)
918+
current_checksum = self.get_md5_checksum(gen_out_path)
919+
cached_checksum = self.get_md5_checksum(cached_gen_out_path)
920+
# If the cached generated GLSL file is the same as the current GLSL
921+
# generated file, then assume that the generated GLSL and SPIR-V
922+
# will not have changed. In that case, just copy over the GLSL and
923+
# SPIR-V files from the cache and return.
924+
if current_checksum == cached_checksum:
925+
shutil.copyfile(cached_spv_out_path, spv_out_path)
906926
return (spv_out_path, gen_out_path)
907927

908-
with codecs.open(src_file_fullpath, "r", encoding="utf-8") as input_file:
909-
input_text = input_file.read()
910-
input_text = self.maybe_replace_u16vecn(input_text)
911-
output_text = preprocess(input_text, codegen_params)
912-
913-
with codecs.open(gen_out_path, "w", encoding="utf-8") as output_file:
914-
output_file.write(output_text)
915-
916-
if cache_dir is not None:
917-
# Otherwise, store the generated GLSL files in the cache
918-
shutil.copyfile(gen_out_path, cached_gen_out_path)
919-
# If a YAML file was used to configure codegen, cache it as well
920-
if requires_codegen:
921-
yaml_file_fullpath = codegen_params["YAML_SRC_FULLPATH"]
922-
shutil.copyfile(yaml_file_fullpath, cached_codegen_yaml)
923-
924-
# If no GLSL compiler is specified, or the source file is not a GLSL shader
925-
# then only write out the generated GLSL shaders.
926-
if compile_spv and self.glslc_path is not None:
928+
# Only proceed if a GLSL compiler was specified
929+
if self.glslc_path is not None:
927930
cmd_base = [
928931
self.glslc_path,
929932
"-fshader-stage=compute",
@@ -961,10 +964,15 @@ def process_shader(shader_paths_pair):
961964

962965
return (spv_out_path, gen_out_path)
963966

964-
# Parallelize shader compilation as much as possible to optimize build time.
967+
# Run codegen serially to ensure that all .glsl, .glslh, and .h files are up to
968+
# date before compilation
969+
for generated_file_tuple in self.output_file_map.items():
970+
generate_src_file(generated_file_tuple)
971+
972+
# Parallelize SPIR-V compilation to optimize build time
965973
with ThreadPool(os.cpu_count()) as pool:
966974
for spv_out_path, glsl_out_path in pool.map(
967-
process_shader, self.output_file_map.items()
975+
compile_spirv, self.output_file_map.items()
968976
):
969977
output_file_map[spv_out_path] = glsl_out_path
970978

0 commit comments

Comments
 (0)