summaryrefslogtreecommitdiff
path: root/src/gallium/frontends/clover/nir/invocation.cpp
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2019-04-10 10:24:46 +1000
committerDave Airlie <airlied@linux.ie>2020-09-01 21:44:07 +0000
commit5be69ed6b9c8746889aa517ddb96ab9cfebabd46 (patch)
treef334f4ca9ec26bd71d2cb46156c293269d1f6972 /src/gallium/frontends/clover/nir/invocation.cpp
parent96fbe9a02243aed0ae1fc75002ebaaed3de9d687 (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.cpp91
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 &section = 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);