asahi: precompile helper program

1. avoids cluttering shaders,internal print
2. reduces screen create overhead. this cuts average "glxinfo" runtime by about
   25%, and seems to shave maybe 0.5% off the CTS job.
3. enforces helper program builds successfully as a build-time assertion
4. reduces the libagx generated blob for now, since g13 binaries are more
   compact than serialized NIR

Closes https://gitlab.freedesktop.org/asahi/mesa/-/issues/37

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27616>
This commit is contained in:
Alyssa Rosenzweig
2024-02-09 12:34:50 -04:00
committed by Marge Bot
parent e1644a2307
commit a3f647fde1
3 changed files with 42 additions and 27 deletions

View File

@@ -260,7 +260,6 @@ print_u32_data(FILE *fp, const char *prefix, const char *arr_name,
const uint32_t *data, size_t len)
{
assert(len % 4 == 0);
fprintf(fp, "#include <stdint.h>\n");
fprintf(fp, "static const uint32_t %s_%s[] = {", prefix, arr_name);
for (unsigned i = 0; i < (len / 4); i++) {
if (i % 4 == 0)
@@ -489,12 +488,47 @@ main(int argc, char **argv)
fprintf(fp, " *\n");
fprintf(fp, " * Autogenerated file, do not edit\n");
fprintf(fp, " */\n");
spirv_library_to_nir_builder(fp, final_spirv.data, final_spirv.size / 4,
&spirv_options);
fprintf(fp, " #include <stdint.h>\n");
/* Compile SPIR-V to NIR */
nir_shader *nir = compile(NULL, final_spirv.data, final_spirv.size);
{
struct util_dynarray binary;
util_dynarray_init(&binary, NULL);
nir_builder b = nir_builder_init_simple_shader(
MESA_SHADER_COMPUTE, &agx_nir_options, "Helper shader");
nir_function *func =
nir_shader_get_function_for_name(nir, "libagx_helper");
nir_call(&b, nir_function_clone(b.shader, func));
UNUSED struct agx_uncompiled_shader_info info;
UNUSED struct agx_shader_info compiled_info;
struct agx_shader_key key = {.libagx = nir};
agx_preprocess_nir(b.shader, nir, false, &info);
agx_compile_shader_nir(b.shader, &key, NULL, &binary, &compiled_info);
/* Pad out */
uint8_t zero = 0;
while (binary.size % 4) {
util_dynarray_append(&binary, uint8_t, zero);
}
print_u32_data(fp, "libagx_g13", "helper", binary.data, binary.size);
util_dynarray_fini(&binary);
ralloc_free(b.shader);
/* Remove the NIR function, it's compiled, we don't need it at runtime */
exec_node_remove(&func->node);
}
spirv_library_to_nir_builder(fp, final_spirv.data, final_spirv.size / 4,
&spirv_options);
/* Serialize NIR for embedding */
struct blob blob;
blob_init(&blob);

View File

@@ -4,7 +4,7 @@
prog_asahi_clc = executable(
'asahi_clc',
['asahi_clc.c'],
link_with : [],
link_with : [libasahi_compiler],
include_directories : [inc_include, inc_src],
c_args : [pre_args, no_override_init_args],
link_args : [ld_args_build_id],

View File

@@ -32,30 +32,11 @@ struct spill_size {
struct agx_bo *
agx_build_helper(struct agx_device *dev)
{
struct agx_bo *bo;
struct util_dynarray binary;
util_dynarray_init(&binary, NULL);
nir_builder b = nir_builder_init_simple_shader(
MESA_SHADER_COMPUTE, &agx_nir_options, "Helper shader");
libagx_helper(&b);
UNUSED struct agx_uncompiled_shader_info info;
UNUSED struct agx_shader_info compiled_info;
struct agx_shader_key key = {.libagx = dev->libagx};
agx_preprocess_nir(b.shader, dev->libagx, false, &info);
agx_compile_shader_nir(b.shader, &key, NULL, &binary, &compiled_info);
bo = agx_bo_create(dev, binary.size,
AGX_BO_READONLY | AGX_BO_EXEC | AGX_BO_LOW_VA,
"Helper shader");
struct agx_bo *bo = agx_bo_create(
dev, sizeof(libagx_g13_helper),
AGX_BO_READONLY | AGX_BO_EXEC | AGX_BO_LOW_VA, "Helper shader");
assert(bo);
memcpy(bo->ptr.cpu, binary.data, binary.size);
util_dynarray_fini(&binary);
ralloc_free(b.shader);
memcpy(bo->ptr.cpu, libagx_g13_helper, sizeof(libagx_g13_helper));
if (dev->debug & AGX_DBG_SCRATCH)
fprintf(stderr, "Helper: 0x%" PRIx64 "\n", bo->ptr.gpu);