[Mesa-dev] [PATCH v5 17/21] clover: Implement clCreateProgramWithILKHR

Pierre Moreau pierre.morrow at free.fr
Sun Mar 25 18:02:26 UTC 2018


Signed-off-by: Pierre Moreau <pierre.morrow at free.fr>
---
Changes in v5:
* Use is_binary_spirv and is_valid_spirv from the SPIR-V backend;
* Drop the SPIRV-Tools and llvm-spirv dependencies on clover.

 src/gallium/state_trackers/clover/api/dispatch.hpp |  4 ++
 src/gallium/state_trackers/clover/api/program.cpp  | 60 +++++++++++++++++++++-
 src/gallium/state_trackers/clover/core/program.cpp | 47 ++++++++++++++---
 src/gallium/state_trackers/clover/core/program.hpp | 12 +++++
 4 files changed, 113 insertions(+), 10 deletions(-)

diff --git a/src/gallium/state_trackers/clover/api/dispatch.hpp b/src/gallium/state_trackers/clover/api/dispatch.hpp
index 84b992af9b..dc9c94a540 100644
--- a/src/gallium/state_trackers/clover/api/dispatch.hpp
+++ b/src/gallium/state_trackers/clover/api/dispatch.hpp
@@ -974,6 +974,10 @@ namespace clover {
    cl_int
    IcdGetPlatformIDsKHR(cl_uint num_entries, cl_platform_id *rd_platforms,
                         cl_uint *rnum_platforms);
+
+   cl_program
+   CreateProgramWithILKHR(cl_context d_ctx, const void *il,
+                          size_t length, cl_int *r_errcode);
 }
 
 #endif
diff --git a/src/gallium/state_trackers/clover/api/program.cpp b/src/gallium/state_trackers/clover/api/program.cpp
index 7d57d3f0e9..3c7e56efb9 100644
--- a/src/gallium/state_trackers/clover/api/program.cpp
+++ b/src/gallium/state_trackers/clover/api/program.cpp
@@ -22,6 +22,7 @@
 
 #include "api/util.hpp"
 #include "core/program.hpp"
+#include "spirv/invocation.hpp"
 #include "util/u_debug.h"
 
 #include <sstream>
@@ -46,6 +47,26 @@ namespace {
             }, objs<allow_empty_tag>(d_devs, num_devs)))
          throw error(CL_INVALID_DEVICE);
    }
+
+   enum program::il_type
+   identify_and_validate_il(const void *il, size_t length,
+                            const std::string &opencl_version,
+                            const context::notify_action &notify) {
+
+      enum program::il_type il_type = program::il_type::none;
+
+#ifdef CLOVER_ALLOW_SPIRV
+      const uint32_t *stream = reinterpret_cast<const uint32_t*>(il);
+      if (spirv::is_binary_spirv(reinterpret_cast<const char*>(il), length)) {
+         if (!spirv::is_valid_spirv(stream, length / 4u, opencl_version,
+                                    notify))
+            throw error(CL_INVALID_VALUE);
+         il_type = program::il_type::spirv;
+      }
+#endif
+
+      return il_type;
+   }
 }
 
 CLOVER_API cl_program
@@ -129,6 +150,41 @@ 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.
+   std::string min_opencl_version;
+   for (const device &dev : ctx.devices()) {
+      const std::string opencl_version = dev.device_version();
+      if (min_opencl_version.empty())
+         min_opencl_version = opencl_version;
+      else if (opencl_version < min_opencl_version)
+         min_opencl_version = opencl_version;
+   }
+
+   const enum program::il_type il_type = identify_and_validate_il(il, length,
+                                                                  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, reinterpret_cast<const char*>(il), length, 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,
@@ -185,7 +241,7 @@ clBuildProgram(cl_program d_prog, cl_uint num_devs,
    validate_build_common(prog, num_devs, d_devs, valid_devs, pfn_notify,
                          user_data);
 
-   if (prog.has_source) {
+   if (prog.has_source || prog.has_il) {
       prog.compile(devs, opts);
       prog.link(devs, opts, { prog });
    } else if (any_of([&](const device &dev){
@@ -223,7 +279,7 @@ 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.has_source && !prog.has_il)
       throw error(CL_INVALID_OPERATION);
 
    for_each([&](const char *name, const program &header) {
diff --git a/src/gallium/state_trackers/clover/core/program.cpp b/src/gallium/state_trackers/clover/core/program.cpp
index 62fa13efbf..9480cfb0b4 100644
--- a/src/gallium/state_trackers/clover/core/program.cpp
+++ b/src/gallium/state_trackers/clover/core/program.cpp
@@ -25,26 +25,48 @@
 
 using namespace clover;
 
+namespace {
+   module
+   compile_program(const program &prog, const device &dev,
+                   const std::string &opts, const header_map &headers,
+                   std::string &log) {
+      if (!prog.source().empty())
+         return llvm::compile_program(prog.source(), headers, dev, opts, log);
+#ifdef CLOVER_ALLOW_SPIRV
+      else if (prog.il_type() == program::il_type::spirv)
+         return llvm::compile_from_spirv(prog.il(), dev, log);
+#endif
+      else
+         throw error(CL_INVALID_VALUE);
+   }
+} // end of anonymous namespace
+
 program::program(clover::context &ctx, const std::string &source) :
-   has_source(true), context(ctx), _devices(ctx.devices()), _source(source),
-   _kernel_ref_counter(0) {
+   has_source(true), has_il(false), context(ctx), _devices(ctx.devices()),
+   _source(source), _kernel_ref_counter(0), _il(), _il_type(il_type::none) {
 }
 
 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) {
+   has_source(false), has_il(false), context(ctx), _devices(devs),
+   _kernel_ref_counter(0), _il(), _il_type(il_type::none) {
    for_each([&](device &dev, const module &bin) {
          _builds[&dev] = { bin };
       },
       devs, binaries);
 }
 
+program::program(clover::context &ctx, const char *il, size_t length,
+                 enum il_type il_type) :
+   has_source(false), has_il(true), context(ctx), _devices(ctx.devices()),
+   _kernel_ref_counter(0), _il(il, il + length), _il_type(il_type) {
+}
+
 void
 program::compile(const ref_vector<device> &devs, const std::string &opts,
                  const header_map &headers) {
-   if (has_source) {
+   if (has_source || has_il) {
       _devices = devs;
 
       for (auto &dev : devs) {
@@ -52,9 +74,8 @@ program::compile(const ref_vector<device> &devs, const std::string &opts,
 
          try {
             assert(dev.ir_format() == PIPE_SHADER_IR_NATIVE);
-            const module m = llvm::compile_program(_source, headers, dev, opts,
-                                                   log);
-            _builds[&dev] = { m, opts, log };
+            _builds[&dev] = { compile_program(*this, dev, opts, headers, log),
+               opts, log };
          } catch (...) {
             _builds[&dev] = { module(), opts, log };
             throw;
@@ -85,6 +106,16 @@ program::link(const ref_vector<device> &devs, const std::string &opts,
    }
 }
 
+const std::vector<char> &
+program::il() const {
+   return _il;
+}
+
+enum program::il_type
+program::il_type() const {
+   return _il_type;
+}
+
 const std::string &
 program::source() const {
    return _source;
diff --git a/src/gallium/state_trackers/clover/core/program.hpp b/src/gallium/state_trackers/clover/core/program.hpp
index 05964e78a7..ce0607982d 100644
--- a/src/gallium/state_trackers/clover/core/program.hpp
+++ b/src/gallium/state_trackers/clover/core/program.hpp
@@ -38,11 +38,17 @@ namespace clover {
          evals, const std::vector<intrusive_ref<device>> &> device_range;
 
    public:
+      enum class il_type { none, llvm_ir, spirv };
+
       program(clover::context &ctx,
               const std::string &source);
       program(clover::context &ctx,
               const ref_vector<device> &devs = {},
               const std::vector<module> &binaries = {});
+      program(clover::context &ctx,
+              const char *il,
+              size_t length,
+              enum il_type il_type);
 
       program(const program &prog) = delete;
       program &
@@ -56,6 +62,10 @@ namespace clover {
       const bool has_source;
       const std::string &source() const;
 
+      const bool has_il;
+      const std::vector<char> &il() const;
+      enum il_type il_type() const;
+
       device_range devices() const;
 
       struct build {
@@ -85,6 +95,8 @@ namespace clover {
       std::map<const device *, struct build> _builds;
       std::string _source;
       ref_counter _kernel_ref_counter;
+      std::vector<char> _il;
+      enum il_type _il_type;
    };
 }
 
-- 
2.16.3



More information about the mesa-dev mailing list