From 4a931ec9eb542a84e1e7826c434ebf214db2798c Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 31 Oct 2024 09:40:16 -0400 Subject: [PATCH] asahi/clc: ingest spir-v use mesa_clc for the spir-v part, this improves incremental build granularity. Signed-off-by: Alyssa Rosenzweig Reviewed-by: Matt Turner Reviewed-by: Jesse Natalie Part-of: --- src/asahi/clc/asahi_clc.c | 187 ++++---------------------------------- src/asahi/lib/meson.build | 22 ++++- 2 files changed, 35 insertions(+), 174 deletions(-) diff --git a/src/asahi/clc/asahi_clc.c b/src/asahi/clc/asahi_clc.c index 898543f087e..0e0a58956bf 100644 --- a/src/asahi/clc/asahi_clc.c +++ b/src/asahi/clc/asahi_clc.c @@ -5,15 +5,8 @@ */ #include "asahi/compiler/agx_compile.h" -#include "compiler/clc/clc.h" #include "compiler/glsl_types.h" #include "compiler/spirv/nir_spirv.h" -#include "compiler/spirv/spirv_info.h" -#include "util/build_id.h" -#include "util/disk_cache.h" -#include "util/macros.h" -#include "util/mesa-sha1.h" -#include "util/u_dynarray.h" #include "nir.h" #include "nir_builder.h" #include "nir_serialize.h" @@ -264,16 +257,6 @@ compile(void *memctx, const uint32_t *spirv, size_t spirv_size) return nir; } -/* Shader functions */ -#define SPIR_V_MAGIC_NUMBER 0x07230203 - -static void -msg_callback(void *priv, const char *msg) -{ - (void)priv; - fprintf(stderr, "%s", msg); -} - static void print_u32_data(FILE *fp, const char *prefix, const char *arr_name, const uint32_t *data, size_t len) @@ -318,22 +301,6 @@ print_usage(char *exec_name, FILE *f) #define OPT_PREFIX 1000 -static uint32_t -get_module_spirv_version(const uint32_t *spirv, size_t size) -{ - assert(size >= 8); - assert(spirv[0] == SPIR_V_MAGIC_NUMBER); - return spirv[1]; -} - -static void -set_module_spirv_version(uint32_t *spirv, size_t size, uint32_t version) -{ - assert(size >= 8); - assert(spirv[0] == SPIR_V_MAGIC_NUMBER); - spirv[1] = version; -} - int main(int argc, char **argv) { @@ -342,26 +309,15 @@ main(int argc, char **argv) {"prefix", required_argument, 0, OPT_PREFIX}, {"in", required_argument, 0, 'i'}, {"out", required_argument, 0, 'o'}, - {"spv", required_argument, 0, 's'}, {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}, }; - char *outfile = NULL, *spv_outfile = NULL, *prefix = NULL; - struct util_dynarray clang_args; - struct util_dynarray input_files; - struct util_dynarray spirv_objs; - struct util_dynarray spirv_ptr_objs; - + char *infile = NULL, *outfile = NULL, *prefix = NULL; void *mem_ctx = ralloc_context(NULL); - util_dynarray_init(&clang_args, mem_ctx); - util_dynarray_init(&input_files, mem_ctx); - util_dynarray_init(&spirv_objs, mem_ctx); - util_dynarray_init(&spirv_ptr_objs, mem_ctx); - int ch; - while ((ch = getopt_long(argc, argv, "he:p:s:i:o:v", long_options, NULL)) != + while ((ch = getopt_long(argc, argv, "he:p:i:o:v", long_options, NULL)) != -1) { switch (ch) { case 'h': @@ -371,10 +327,7 @@ main(int argc, char **argv) outfile = optarg; break; case 'i': - util_dynarray_append(&input_files, char *, optarg); - break; - case 's': - spv_outfile = optarg; + infile = optarg; break; case OPT_PREFIX: prefix = optarg; @@ -386,124 +339,27 @@ main(int argc, char **argv) } } - for (int i = optind; i < argc; i++) { - util_dynarray_append(&clang_args, char *, argv[i]); - } - - if (util_dynarray_num_elements(&input_files, char *) == 0) { - fprintf(stderr, "No input file(s).\n"); + if (infile == NULL || outfile == NULL || prefix == NULL) { + fprintf(stderr, "Missing required argument.\n"); print_usage(argv[0], stderr); return -1; } - if (prefix == NULL) { - fprintf(stderr, "No prefix specified.\n"); - print_usage(argv[0], stderr); - return -1; - } - - struct clc_logger logger = { - .error = msg_callback, - .warning = msg_callback, - }; - - util_dynarray_foreach(&input_files, char *, infile) { - int fd = open(*infile, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Failed to open %s\n", *infile); - ralloc_free(mem_ctx); - return 1; - } - - off_t len = lseek(fd, 0, SEEK_END); - const void *map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - if (map == MAP_FAILED) { - fprintf(stderr, "Failed to mmap the file: errno=%d, %s\n", errno, - strerror(errno)); - ralloc_free(mem_ctx); - return 1; - } - - const char *allowed_spirv_extensions[] = { - "SPV_EXT_shader_atomic_float_add", - "SPV_EXT_shader_atomic_float_min_max", - "SPV_KHR_float_controls", - "SPV_INTEL_subgroups", - NULL, - }; - - struct clc_compile_args clc_args = { - .source = - { - .name = *infile, - .value = map, - }, - .features = - { - .fp16 = true, - .intel_subgroups = true, - .subgroups = true, - .subgroups_ifp = true, - }, - .args = util_dynarray_begin(&clang_args), - .num_args = util_dynarray_num_elements(&clang_args, char *), - .allowed_spirv_extensions = allowed_spirv_extensions, - }; - - struct clc_binary *spirv_out = - util_dynarray_grow(&spirv_objs, struct clc_binary, 1); - - if (!clc_compile_c_to_spirv(&clc_args, &logger, spirv_out)) { - ralloc_free(mem_ctx); - return 1; - } - } - - util_dynarray_foreach(&spirv_objs, struct clc_binary, p) { - util_dynarray_append(&spirv_ptr_objs, struct clc_binary *, p); - } - - /* The SPIRV-Tools linker started checking that all modules have the same - * version. But SPIRV-LLVM-Translator picks the lower required version for - * each module it compiles. So we have to iterate over all of them and set - * the max found to make SPIRV-Tools link our modules. - * - * TODO: This is not the correct thing to do. We need SPIRV-LLVM-Translator - * to pick a given SPIRV version given to it and have all the modules - * at that version. We should remove this hack when this issue is - * fixed : - * https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1445 - */ - uint32_t max_spirv_version = 0; - util_dynarray_foreach(&spirv_ptr_objs, struct clc_binary *, module) { - max_spirv_version = - MAX2(max_spirv_version, - get_module_spirv_version((*module)->data, (*module)->size)); - } - - assert(max_spirv_version > 0); - util_dynarray_foreach(&spirv_ptr_objs, struct clc_binary *, module) { - set_module_spirv_version((*module)->data, (*module)->size, - max_spirv_version); - } - - struct clc_linker_args link_args = { - .in_objs = util_dynarray_begin(&spirv_ptr_objs), - .num_in_objs = - util_dynarray_num_elements(&spirv_ptr_objs, struct clc_binary *), - .create_library = true, - }; - struct clc_binary final_spirv; - if (!clc_link_spirv(&link_args, &logger, &final_spirv)) { + int fd = open(infile, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Failed to open %s\n", infile); ralloc_free(mem_ctx); return 1; } - if (spv_outfile) { - FILE *fp = fopen(spv_outfile, "w"); - fwrite(final_spirv.data, final_spirv.size, 1, fp); - fclose(fp); + off_t spirv_len = lseek(fd, 0, SEEK_END); + const void *spirv_map = mmap(NULL, spirv_len, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + if (spirv_map == MAP_FAILED) { + fprintf(stderr, "Failed to mmap the file: errno=%d, %s\n", errno, + strerror(errno)); + ralloc_free(mem_ctx); + return 1; } FILE *fp = stdout; @@ -521,7 +377,7 @@ main(int argc, char **argv) fprintf(fp, " #include \n"); /* Compile SPIR-V to NIR */ - nir_shader *nir = compile(mem_ctx, final_spirv.data, final_spirv.size); + nir_shader *nir = compile(mem_ctx, spirv_map, spirv_len); { nir_builder b = nir_builder_init_simple_shader( @@ -550,8 +406,7 @@ main(int argc, char **argv) exec_node_remove(&func->node); } - spirv_library_to_nir_builder(fp, final_spirv.data, final_spirv.size / 4, - &spirv_options); + spirv_library_to_nir_builder(fp, spirv_map, spirv_len / 4, &spirv_options); /* Serialize NIR for embedding */ struct blob blob; @@ -565,12 +420,6 @@ main(int argc, char **argv) if (fp != stdout) fclose(fp); - util_dynarray_foreach(&spirv_objs, struct clc_binary, p) { - clc_free_spirv(p); - } - - clc_free_spirv(&final_spirv); ralloc_free(mem_ctx); - return 0; } diff --git a/src/asahi/lib/meson.build b/src/asahi/lib/meson.build index 1cea9742515..638f7422493 100644 --- a/src/asahi/lib/meson.build +++ b/src/asahi/lib/meson.build @@ -71,12 +71,12 @@ prepended_input_args = [] foreach input_arg : libagx_shader_files prepended_input_args += ['--in', input_arg] endforeach -libagx_shaders = custom_target( - 'libagx_shaders.h', +libagx_spv = custom_target( + 'libagx.spv', input : libagx_shader_files, - output : 'libagx_shaders.h', + output : 'libagx.spv', command : [ - prog_asahi_clc, '--prefix', 'libagx_shaders', + prog_mesa_clc, prepended_input_args, '-o', '@OUTPUT@', '--', '-cl-std=cl2.0', '-D__OPENCL_VERSION__=200', '-I' + join_paths(meson.current_source_dir(), '.'), @@ -85,7 +85,19 @@ libagx_shaders = custom_target( '-I' + join_paths(meson.current_build_dir(), '../genxml'), ], env: ['MESA_SHADER_CACHE_DISABLE=true'], - depends : [prog_asahi_clc, agx_pack], + depends : [prog_mesa_clc, agx_pack], +) + +libagx_shaders = custom_target( + 'libagx_shaders.h', + input : libagx_spv, + output : 'libagx_shaders.h', + command : [ + prog_asahi_clc, '--prefix', 'libagx_shaders', + '--in', libagx_spv, '-o', '@OUTPUT@' + ], + env: ['MESA_SHADER_CACHE_DISABLE=true'], + depends : [prog_asahi_clc], ) libasahi_lib = static_library(