diff options
author | Dave Airlie <airlied@redhat.com> | 2019-04-10 10:24:46 +1000 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2020-09-01 21:44:07 +0000 |
commit | 5be69ed6b9c8746889aa517ddb96ab9cfebabd46 (patch) | |
tree | f334f4ca9ec26bd71d2cb46156c293269d1f6972 /src/gallium/frontends/clover/nir/invocation.cpp | |
parent | 96fbe9a02243aed0ae1fc75002ebaaed3de9d687 (diff) |
clover: handle libclc shader (v3)libclc-overwritten
This works by taking the spirv produced by libclc which contains
a lot of mangled function entrypoints identified with LinkageAttribute decorations.
This patch just sets up clover to load the libclc blob and convert it to
library nir, and support inlining application nir with calls to libclc.
v2: Add a disk cache support for this object, to avoid the spirv parsing
overheads each time. move spirv->nir to lazy instantiation to avoid
the mess with glsl types and constructor ordering.
v3: make disk cache optional
v1-Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
make disk cache optional
Diffstat (limited to 'src/gallium/frontends/clover/nir/invocation.cpp')
-rw-r--r-- | src/gallium/frontends/clover/nir/invocation.cpp | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/src/gallium/frontends/clover/nir/invocation.cpp b/src/gallium/frontends/clover/nir/invocation.cpp index 8ea6d3cf4d0..da9e62b2159 100644 --- a/src/gallium/frontends/clover/nir/invocation.cpp +++ b/src/gallium/frontends/clover/nir/invocation.cpp @@ -37,6 +37,10 @@ #include <compiler/spirv/nir_spirv.h> #include <util/u_math.h> +extern "C" { +#include "nir_lower_libclc.h" +} + using namespace clover; #ifdef HAVE_CLOVER_SPIRV @@ -131,8 +135,8 @@ clover_lower_nir(nir_shader *nir, std::vector<module::argument> &args, uint32_t clover_lower_nir_filter, clover_lower_nir_instr, &state); } -module clover::nir::spirv_to_nir(const module &mod, const device &dev, - std::string &r_log) +static spirv_to_nir_options +create_spirv_options(const device &dev, std::string &r_log) { struct spirv_to_nir_options spirv_options = {}; spirv_options.environment = NIR_SPIRV_OPENCL; @@ -156,6 +160,87 @@ module clover::nir::spirv_to_nir(const module &mod, const device &dev, spirv_options.caps.int64_atomics = dev.has_int64_atomics(); spirv_options.debug.func = &debug_function; spirv_options.debug.private_data = &r_log; + return spirv_options; +} + +struct disk_cache *clover::nir::create_clc_disk_cache(void) +{ + struct mesa_sha1 ctx; + unsigned char sha1[20]; + char cache_id[20 * 2 + 1]; + _mesa_sha1_init(&ctx); + + if (!disk_cache_get_function_identifier((void *)clover::nir::create_clc_disk_cache, &ctx)) + return NULL; + + _mesa_sha1_final(&ctx, sha1); + + disk_cache_format_hex_id(cache_id, sha1, 20 * 2); + return disk_cache_create("clover-clc", cache_id, 0); +} + +nir_shader *clover::nir::libclc_spirv_to_nir(const module &mod, const device &dev, + std::string &r_log) +{ + spirv_to_nir_options spirv_options = create_spirv_options(dev, r_log); + spirv_options.create_library = true; + + auto §ion = mod.secs[0]; + const auto *binary = + reinterpret_cast<const pipe_binary_program_header *>(section.data.data()); + const uint32_t *data = reinterpret_cast<const uint32_t *>(binary->blob); + const size_t num_words = binary->num_bytes / 4; + auto *compiler_options = dev_get_nir_compiler_options(dev); + unsigned char clc_cache_key[20]; + unsigned char sha1[CACHE_KEY_SIZE]; + /* caching ftw. */ + struct mesa_sha1 ctx; + + size_t binary_size = 0; + uint8_t *buffer = NULL; + if (dev.clc_cache) { + _mesa_sha1_init(&ctx); + _mesa_sha1_update(&ctx, data, num_words * 4); + _mesa_sha1_final(&ctx, clc_cache_key); + + disk_cache_compute_key(dev.clc_cache, clc_cache_key, 20, sha1); + + buffer = (uint8_t *)disk_cache_get(dev.clc_cache, sha1, &binary_size); + } + + nir_shader *nir; + if (!buffer) { + nir = spirv_to_nir(data, num_words, nullptr, 0, + MESA_SHADER_KERNEL, "clcspirv", + &spirv_options, compiler_options); + nir_validate_shader(nir, "clover-libclc"); + nir->info.internal = true; + NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp); + NIR_PASS_V(nir, nir_lower_returns); + + if (dev.clc_cache) { + struct blob blob = { 0 }; + blob_init(&blob); + nir_serialize(&blob, nir, true); + disk_cache_put(dev.clc_cache, sha1, blob.data, blob.size, NULL); + blob_finish(&blob); + } + } else { + struct blob_reader blob_read; + blob_reader_init(&blob_read, buffer, binary_size); + nir = nir_deserialize(NULL, compiler_options, &blob_read); + free(buffer); + } + + return nir; +} + +module clover::nir::spirv_to_nir(const module &mod, const device &dev, + std::string &r_log) +{ + spirv_to_nir_options spirv_options = create_spirv_options(dev, r_log); + std::shared_ptr<nir_shader> nir = dev.clc_nir; + spirv_options.clc_shader = nir.get(); module m; // We only insert one section. @@ -189,6 +274,8 @@ module clover::nir::spirv_to_nir(const module &mod, const device &dev, // according to the comment on nir_inline_functions NIR_PASS_V(nir, nir_lower_variable_initializers, nir_var_function_temp); NIR_PASS_V(nir, nir_lower_returns); + NIR_PASS_V(nir, nir_lower_libclc, spirv_options.clc_shader); + NIR_PASS_V(nir, nir_inline_functions); NIR_PASS_V(nir, nir_copy_prop); NIR_PASS_V(nir, nir_opt_deref); |