summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Moreau <dev@pmoreau.org>2020-05-05 13:16:42 +0200
committerPierre Moreau <dev@pmoreau.org>2021-01-01 21:56:58 +0100
commita92afdea580cd75b93566bcea5f763de09319f88 (patch)
tree1c03948ab2178035e1edcf31be70e154bd980b57
parent7b1659173ac56cd95498b2132e216a6a6309a88c (diff)
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@riseup.net> Signed-off-by: Pierre Moreau <dev@pmoreau.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2078>
-rw-r--r--src/gallium/frontends/clover/api/dispatch.hpp4
-rw-r--r--src/gallium/frontends/clover/api/program.cpp67
-rw-r--r--src/gallium/frontends/clover/core/compiler.hpp17
-rw-r--r--src/gallium/frontends/clover/core/program.cpp20
-rw-r--r--src/gallium/frontends/clover/core/program.hpp8
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;
};
}