From 611d66fe4513e53bde052dd2bab95d448c909a2a Mon Sep 17 00:00:00 2001 From: EdB Date: Mon, 20 Oct 2014 10:34:17 +0300 Subject: [PATCH] clover: Add initial implementation of clCompileProgram for CL 1.2. [ Francisco Jerez: General clean-up. ] Reviewed-by: Francisco Jerez --- .../state_trackers/clover/api/dispatch.cpp | 2 +- .../state_trackers/clover/api/program.cpp | 37 +++++++++++++++++-- .../state_trackers/clover/core/compiler.hpp | 4 ++ .../state_trackers/clover/core/error.hpp | 2 +- .../state_trackers/clover/core/program.cpp | 7 ++-- .../state_trackers/clover/core/program.hpp | 4 +- .../state_trackers/clover/llvm/invocation.cpp | 37 ++++++++++++++++--- 7 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/gallium/state_trackers/clover/api/dispatch.cpp b/src/gallium/state_trackers/clover/api/dispatch.cpp index 35d150d6dc8..b5a4094cf2f 100644 --- a/src/gallium/state_trackers/clover/api/dispatch.cpp +++ b/src/gallium/state_trackers/clover/api/dispatch.cpp @@ -122,7 +122,7 @@ namespace clover { clReleaseDevice, clCreateImage, clCreateProgramWithBuiltInKernels, - NULL, // clCompileProgram + clCompileProgram, NULL, // clLinkProgram clUnloadPlatformCompiler, NULL, // clGetKernelArgInfo diff --git a/src/gallium/state_trackers/clover/api/program.cpp b/src/gallium/state_trackers/clover/api/program.cpp index 67717353a8c..342915be1e2 100644 --- a/src/gallium/state_trackers/clover/api/program.cpp +++ b/src/gallium/state_trackers/clover/api/program.cpp @@ -152,14 +152,30 @@ CLOVER_API cl_int clBuildProgram(cl_program d_prog, cl_uint num_devs, const cl_device_id *d_devs, const char *p_opts, void (*pfn_notify)(cl_program, void *), - void *user_data) try { + void *user_data) { + cl_int ret = clCompileProgram(d_prog, num_devs, d_devs, p_opts, + 0, NULL, NULL, pfn_notify, user_data); + + return (ret == CL_COMPILE_PROGRAM_FAILURE ? + CL_BUILD_PROGRAM_FAILURE : ret); +} + +CLOVER_API cl_int +clCompileProgram(cl_program d_prog, cl_uint num_devs, + const cl_device_id *d_devs, const char *p_opts, + cl_uint num_headers, const cl_program *d_header_progs, + const char **header_names, + void (*pfn_notify)(cl_program, void *), + void *user_data) try { auto &prog = obj(d_prog); auto devs = (d_devs ? objs(d_devs, num_devs) : ref_vector(prog.context().devices())); auto opts = (p_opts ? p_opts : ""); + header_map headers; if (bool(num_devs) != bool(d_devs) || - (!pfn_notify && user_data)) + (!pfn_notify && user_data) || + bool(num_headers) != bool(header_names)) throw error(CL_INVALID_VALUE); if (any_of([&](const device &dev) { @@ -167,10 +183,23 @@ clBuildProgram(cl_program d_prog, cl_uint num_devs, }, devs)) throw error(CL_INVALID_DEVICE); - if (prog.kernel_ref_count()) + if (prog.kernel_ref_count() || + !prog.has_source) throw error(CL_INVALID_OPERATION); - prog.build(devs, opts); + + for_each([&](const char *name, const program &header) { + if (!header.has_source) + throw error(CL_INVALID_OPERATION); + + if (!any_of(key_equals(name), headers)) + headers.push_back(compat::pair( + name, header.source())); + }, + range(header_names, num_headers), + objs(d_header_progs, num_headers)); + + prog.build(devs, opts, headers); return CL_SUCCESS; } catch (error &e) { diff --git a/src/gallium/state_trackers/clover/core/compiler.hpp b/src/gallium/state_trackers/clover/core/compiler.hpp index 6ef84d1c0d8..7210d1e9cdc 100644 --- a/src/gallium/state_trackers/clover/core/compiler.hpp +++ b/src/gallium/state_trackers/clover/core/compiler.hpp @@ -29,7 +29,11 @@ #include "pipe/p_defines.h" namespace clover { + typedef compat::vector > header_map; + module compile_program_llvm(const compat::string &source, + const header_map &headers, pipe_shader_ir ir, const compat::string &target, const compat::string &opts, diff --git a/src/gallium/state_trackers/clover/core/error.hpp b/src/gallium/state_trackers/clover/core/error.hpp index cecbe9b110e..7b010f1b1dd 100644 --- a/src/gallium/state_trackers/clover/core/error.hpp +++ b/src/gallium/state_trackers/clover/core/error.hpp @@ -67,7 +67,7 @@ namespace clover { class build_error : public error { public: build_error(const compat::string &what = "") : - error(CL_BUILD_PROGRAM_FAILURE, what) { + error(CL_COMPILE_PROGRAM_FAILURE, what) { } }; diff --git a/src/gallium/state_trackers/clover/core/program.cpp b/src/gallium/state_trackers/clover/core/program.cpp index 6c224dbe083..8553ca7ec96 100644 --- a/src/gallium/state_trackers/clover/core/program.cpp +++ b/src/gallium/state_trackers/clover/core/program.cpp @@ -21,7 +21,6 @@ // #include "core/program.hpp" -#include "core/compiler.hpp" using namespace clover; @@ -41,7 +40,8 @@ program::program(clover::context &ctx, } void -program::build(const ref_vector &devs, const char *opts) { +program::build(const ref_vector &devs, const char *opts, + const header_map &headers) { if (has_source) { _devices = devs; @@ -57,7 +57,8 @@ program::build(const ref_vector &devs, const char *opts) { try { auto module = (dev.ir_format() == PIPE_SHADER_IR_TGSI ? compile_program_tgsi(_source) : - compile_program_llvm(_source, dev.ir_format(), + compile_program_llvm(_source, headers, + dev.ir_format(), dev.ir_target(), build_opts(dev), log)); _binaries.insert({ &dev, module }); diff --git a/src/gallium/state_trackers/clover/core/program.hpp b/src/gallium/state_trackers/clover/core/program.hpp index 4bb5b680d4e..b5aae7e0dff 100644 --- a/src/gallium/state_trackers/clover/core/program.hpp +++ b/src/gallium/state_trackers/clover/core/program.hpp @@ -28,6 +28,7 @@ #include "core/object.hpp" #include "core/context.hpp" #include "core/module.hpp" +#include "core/compiler.hpp" namespace clover { class program : public ref_counter, public _cl_program { @@ -46,7 +47,8 @@ namespace clover { program & operator=(const program &prog) = delete; - void build(const ref_vector &devs, const char *opts); + void build(const ref_vector &devs, const char *opts, + const header_map &headers); const bool has_source; const std::string &source() const; diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 3cdf883e403..507daa0e376 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -146,10 +146,11 @@ namespace { llvm::Module * compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source, - const std::string &name, const std::string &triple, - const std::string &processor, const std::string &opts, - clang::LangAS::Map& address_spaces, unsigned &optimization_level, - compat::string &r_log) { + const header_map &headers, + const std::string &name, const std::string &triple, + const std::string &processor, const std::string &opts, + clang::LangAS::Map& address_spaces, unsigned &optimization_level, + compat::string &r_log) { clang::CompilerInstance c; clang::EmitLLVMOnlyAction act(&llvm_ctx); @@ -248,6 +249,29 @@ namespace { llvm::MemoryBuffer::getMemBuffer(source)); #endif + if (headers.size()) { + const std::string tmp_header_path = "/tmp/clover/"; + + c.getHeaderSearchOpts().AddPath(tmp_header_path, + clang::frontend::Angled, + false, false +#if HAVE_LLVM < 0x0303 + , false +#endif + ); + + for (header_map::const_iterator it = headers.begin(); + it != headers.end(); ++it) { + const std::string path = tmp_header_path + std::string(it->first); + c.getPreprocessorOpts().addRemappedFile(path, +#if HAVE_LLVM >= 0x0306 + llvm::MemoryBuffer::getMemBuffer(it->second.c_str()).release()); +#else + llvm::MemoryBuffer::getMemBuffer(it->second.c_str())); +#endif + } + } + // Setting this attribute tells clang to link this file before // performing any optimizations. This is required so that // we can replace calls to the OpenCL C barrier() builtin @@ -684,6 +708,7 @@ static const struct debug_named_value debug_options[] = { module clover::compile_program_llvm(const compat::string &source, + const header_map &headers, enum pipe_shader_ir ir, const compat::string &target, const compat::string &opts, @@ -708,8 +733,8 @@ clover::compile_program_llvm(const compat::string &source, // The input file name must have the .cl extension in order for the // CompilerInvocation class to recognize it as an OpenCL source file. - llvm::Module *mod = compile_llvm(llvm_ctx, source, "input.cl", triple, - processor, opts, address_spaces, + llvm::Module *mod = compile_llvm(llvm_ctx, source, headers, "input.cl", + triple, processor, opts, address_spaces, optimization_level, r_log); find_kernels(mod, kernels); -- 2.30.2