Mesa (master): clover: Implement clCreateProgramWithILKHR

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jan 1 22:28:33 UTC 2021


Module: Mesa
Branch: master
Commit: a92afdea580cd75b93566bcea5f763de09319f88
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a92afdea580cd75b93566bcea5f763de09319f88

Author: Pierre Moreau <dev at pmoreau.org>
Date:   Tue May  5 13:16:42 2020 +0200

clover: Implement clCreateProgramWithILKHR

v2: Use the same storage for OpenCL C sources and ILs representations
    (Karol Herbst, Francisco Jerez)
v3:
* Remove `program::has_source` and instead add a value to
  `program::il_type` for sources. (Francisco Jerez)
* Use `std::move()` on sources.
* Replace `CL_MAKE_VERSION(99999999u, 0u, 0u)` with
  `std::numeric_limits<uint32_t>::max()` (Francisco Jerez)

Reviewed-by: Francisco Jerez <currojerez at riseup.net>
Signed-off-by: Pierre Moreau <dev at pmoreau.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2078>

---

 src/gallium/frontends/clover/api/dispatch.hpp  |  4 ++
 src/gallium/frontends/clover/api/program.cpp   | 67 ++++++++++++++++++++++++--
 src/gallium/frontends/clover/core/compiler.hpp | 17 +++++--
 src/gallium/frontends/clover/core/program.cpp  | 20 +++++---
 src/gallium/frontends/clover/core/program.hpp  |  8 ++-
 5 files changed, 100 insertions(+), 16 deletions(-)

diff --git a/src/gallium/frontends/clover/api/dispatch.hpp b/src/gallium/frontends/clover/api/dispatch.hpp
index ea835ed6da4..a190a8cbba0 100644
--- a/src/gallium/frontends/clover/api/dispatch.hpp
+++ b/src/gallium/frontends/clover/api/dispatch.hpp
@@ -100,6 +100,10 @@ namespace clover {
                    const cl_event *event_wait_list,
                    cl_event *event,
                    cl_int cmd);
+
+   cl_program
+   CreateProgramWithILKHR(cl_context d_ctx, const void *il,
+                          size_t length, cl_int *r_errcode);
 }
 
 #endif
diff --git a/src/gallium/frontends/clover/api/program.cpp b/src/gallium/frontends/clover/api/program.cpp
index d390c1c9e13..fb03ab74bcb 100644
--- a/src/gallium/frontends/clover/api/program.cpp
+++ b/src/gallium/frontends/clover/api/program.cpp
@@ -22,8 +22,10 @@
 
 #include "api/util.hpp"
 #include "core/program.hpp"
+#include "spirv/invocation.hpp"
 #include "util/u_debug.h"
 
+#include <limits>
 #include <sstream>
 
 using namespace clover;
@@ -71,6 +73,29 @@ namespace {
             }, objs<allow_empty_tag>(d_devs, num_devs)))
          throw error(CL_INVALID_DEVICE);
    }
+
+   enum program::il_type
+   identify_and_validate_il(const std::string &il,
+                            const cl_version opencl_version,
+                            const context::notify_action &notify) {
+
+      enum program::il_type il_type = program::il_type::none;
+
+#ifdef HAVE_CLOVER_SPIRV
+      if (spirv::is_binary_spirv(il)) {
+         std::string log;
+         if (!spirv::is_valid_spirv(il, opencl_version, log)) {
+            if (notify) {
+               notify(log.c_str());
+            }
+            throw error(CL_INVALID_VALUE);
+         }
+         il_type = program::il_type::spirv;
+      }
+#endif
+
+      return il_type;
+   }
 }
 
 CLOVER_API cl_program
@@ -92,7 +117,7 @@ clCreateProgramWithSource(cl_context d_ctx, cl_uint count,
 
    // ...and create a program object for them.
    ret_error(r_errcode, CL_SUCCESS);
-   return new program(ctx, source);
+   return new program(ctx, std::move(source), program::il_type::source);
 
 } catch (error &e) {
    ret_error(r_errcode, e);
@@ -154,6 +179,40 @@ clCreateProgramWithBinary(cl_context d_ctx, cl_uint n,
    return NULL;
 }
 
+cl_program
+clover::CreateProgramWithILKHR(cl_context d_ctx, const void *il,
+                               size_t length, cl_int *r_errcode) try {
+   auto &ctx = obj(d_ctx);
+
+   if (!il || !length)
+      throw error(CL_INVALID_VALUE);
+
+   // Compute the highest OpenCL version supported by all devices associated to
+   // the context. That is the version used for validating the SPIR-V binary.
+   cl_version min_opencl_version = std::numeric_limits<uint32_t>::max();
+   for (const device &dev : ctx.devices()) {
+      const cl_version opencl_version = dev.device_version();
+      min_opencl_version = std::min(opencl_version, min_opencl_version);
+   }
+
+   const char *stream = reinterpret_cast<const char *>(il);
+   std::string binary(stream, stream + length);
+   const enum program::il_type il_type = identify_and_validate_il(binary,
+                                                                  min_opencl_version,
+                                                                  ctx.notify);
+
+   if (il_type == program::il_type::none)
+      throw error(CL_INVALID_VALUE);
+
+   // Initialize a program object with it.
+   ret_error(r_errcode, CL_SUCCESS);
+   return new program(ctx, std::move(binary), il_type);
+
+} catch (error &e) {
+   ret_error(r_errcode, e);
+   return NULL;
+}
+
 CLOVER_API cl_program
 clCreateProgramWithBuiltInKernels(cl_context d_ctx, cl_uint n,
                                   const cl_device_id *d_devs,
@@ -210,7 +269,7 @@ clBuildProgram(cl_program d_prog, cl_uint num_devs,
 
    auto notifier = build_notifier(d_prog, pfn_notify, user_data);
 
-   if (prog.has_source) {
+   if (prog.il_type() != program::il_type::none) {
       prog.compile(devs, opts);
       prog.link(devs, opts, { prog });
    } else if (any_of([&](const device &dev){
@@ -248,11 +307,11 @@ clCompileProgram(cl_program d_prog, cl_uint num_devs,
    if (bool(num_headers) != bool(header_names))
       throw error(CL_INVALID_VALUE);
 
-   if (!prog.has_source)
+   if (prog.il_type() == program::il_type::none)
       throw error(CL_INVALID_OPERATION);
 
    for_each([&](const char *name, const program &header) {
-         if (!header.has_source)
+         if (header.il_type() == program::il_type::none)
             throw error(CL_INVALID_OPERATION);
 
          if (!any_of(key_equals(name), headers))
diff --git a/src/gallium/frontends/clover/core/compiler.hpp b/src/gallium/frontends/clover/core/compiler.hpp
index 6ef30df9b7f..30dfe448c8b 100644
--- a/src/gallium/frontends/clover/core/compiler.hpp
+++ b/src/gallium/frontends/clover/core/compiler.hpp
@@ -32,16 +32,27 @@
 namespace clover {
    namespace compiler {
       static inline module
-      compile_program(const std::string &source, const header_map &headers,
+      compile_program(const program &prog, const header_map &headers,
                       const device &dev, const std::string &opts,
                       std::string &log) {
          switch (dev.ir_format()) {
 #ifdef HAVE_CLOVER_SPIRV
          case PIPE_SHADER_IR_NIR_SERIALIZED:
-            return llvm::compile_to_spirv(source, headers, dev, opts, log);
+            switch (prog.il_type()) {
+            case program::il_type::source:
+               return llvm::compile_to_spirv(prog.source(), headers, dev, opts, log);
+            case program::il_type::spirv:
+               return spirv::compile_program(prog.source(), dev, log);
+            default:
+               unreachable("device with unsupported IL");
+               throw error(CL_INVALID_VALUE);
+            }
 #endif
          case PIPE_SHADER_IR_NATIVE:
-            return llvm::compile_program(source, headers, dev, opts, log);
+            if (prog.il_type() == program::il_type::source)
+               return llvm::compile_program(prog.source(), headers, dev, opts, log);
+            else
+               throw error(CL_INVALID_VALUE);
          default:
             unreachable("device with unsupported IR");
             throw error(CL_INVALID_VALUE);
diff --git a/src/gallium/frontends/clover/core/program.cpp b/src/gallium/frontends/clover/core/program.cpp
index 526e06a26c3..0d97904d419 100644
--- a/src/gallium/frontends/clover/core/program.cpp
+++ b/src/gallium/frontends/clover/core/program.cpp
@@ -25,16 +25,17 @@
 
 using namespace clover;
 
-program::program(clover::context &ctx, const std::string &source) :
-   has_source(true), context(ctx), _devices(ctx.devices()), _source(source),
-   _kernel_ref_counter(0) {
+program::program(clover::context &ctx, std::string &&source,
+                 enum il_type il_type) :
+   context(ctx), _devices(ctx.devices()), _source(std::move(source)),
+   _kernel_ref_counter(0), _il_type(il_type) {
 }
 
 program::program(clover::context &ctx,
                  const ref_vector<device> &devs,
                  const std::vector<module> &binaries) :
-   has_source(false), context(ctx),
-   _devices(devs), _kernel_ref_counter(0) {
+   context(ctx), _devices(devs), _kernel_ref_counter(0),
+   _il_type(il_type::none) {
    for_each([&](device &dev, const module &bin) {
          _builds[&dev] = { bin };
       },
@@ -44,7 +45,7 @@ program::program(clover::context &ctx,
 void
 program::compile(const ref_vector<device> &devs, const std::string &opts,
                  const header_map &headers) {
-   if (has_source) {
+   if (_il_type != il_type::none) {
       _devices = devs;
 
       for (auto &dev : devs) {
@@ -52,7 +53,7 @@ program::compile(const ref_vector<device> &devs, const std::string &opts,
 
          try {
             const module m =
-               compiler::compile_program(_source, headers, dev, opts, log);
+               compiler::compile_program(*this, headers, dev, opts, log);
             _builds[&dev] = { m, opts, log };
          } catch (...) {
             _builds[&dev] = { module(), opts, log };
@@ -83,6 +84,11 @@ program::link(const ref_vector<device> &devs, const std::string &opts,
    }
 }
 
+enum program::il_type
+program::il_type() const {
+   return _il_type;
+}
+
 const std::string &
 program::source() const {
    return _source;
diff --git a/src/gallium/frontends/clover/core/program.hpp b/src/gallium/frontends/clover/core/program.hpp
index 05964e78a79..5cc80d2b620 100644
--- a/src/gallium/frontends/clover/core/program.hpp
+++ b/src/gallium/frontends/clover/core/program.hpp
@@ -38,8 +38,11 @@ namespace clover {
          evals, const std::vector<intrusive_ref<device>> &> device_range;
 
    public:
+      enum class il_type { none, source, spirv };
+
       program(clover::context &ctx,
-              const std::string &source);
+              std::string &&il,
+              enum il_type il_type);
       program(clover::context &ctx,
               const ref_vector<device> &devs = {},
               const std::vector<module> &binaries = {});
@@ -53,8 +56,8 @@ namespace clover {
       void link(const ref_vector<device> &devs, const std::string &opts,
                 const ref_vector<program> &progs);
 
-      const bool has_source;
       const std::string &source() const;
+      enum il_type il_type() const;
 
       device_range devices() const;
 
@@ -85,6 +88,7 @@ namespace clover {
       std::map<const device *, struct build> _builds;
       std::string _source;
       ref_counter _kernel_ref_counter;
+      enum il_type _il_type;
    };
 }
 



More information about the mesa-commit mailing list