Committed as 9ef5b7a.
On Fri, Jul 31, 2015 at 4:07 PM, Zoltán Gilián <zoltan.gil...@gmail.com> wrote: > Could you please commit this? > > On Mon, Jul 27, 2015 at 1:28 PM, Francisco Jerez <curroje...@riseup.net> > wrote: >> Zoltan Gilian <zoltan.gil...@gmail.com> writes: >> >>> Read-only and write-only image arguments are recognized and >>> distinguished. >>> Attributes of the image arguments are passed to the kernel as implicit >>> arguments. >>> --- >>> src/gallium/state_trackers/clover/core/kernel.cpp | 28 +++++ >>> src/gallium/state_trackers/clover/core/kernel.hpp | 15 ++- >>> src/gallium/state_trackers/clover/core/module.hpp | 4 +- >>> .../state_trackers/clover/llvm/invocation.cpp | 135 >>> ++++++++++++++++++++- >>> 4 files changed, 171 insertions(+), 11 deletions(-) >>> >>> diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp >>> b/src/gallium/state_trackers/clover/core/kernel.cpp >>> index 0756f06..955ff7b 100644 >>> --- a/src/gallium/state_trackers/clover/core/kernel.cpp >>> +++ b/src/gallium/state_trackers/clover/core/kernel.cpp >>> @@ -182,6 +182,34 @@ >>> kernel::exec_context::bind(intrusive_ptr<command_queue> _q, >>> } >>> break; >>> } >>> + case module::argument::image_size: { >>> + auto img = dynamic_cast<image_argument &>(**(explicit_arg - >>> 1)).get(); >>> + std::vector<cl_uint> image_size{ >>> + static_cast<cl_uint>(img->width()), >>> + static_cast<cl_uint>(img->height()), >>> + static_cast<cl_uint>(img->depth())}; >>> + for (auto x : image_size) { >>> + auto arg = argument::create(marg); >>> + >>> + arg->set(sizeof(x), &x); >>> + arg->bind(*this, marg); >>> + } >>> + break; >>> + } >>> + case module::argument::image_format: { >>> + auto img = dynamic_cast<image_argument &>(**(explicit_arg - >>> 1)).get(); >>> + cl_image_format fmt = img->format(); >>> + std::vector<cl_uint> image_format{ >>> + static_cast<cl_uint>(fmt.image_channel_data_type), >>> + static_cast<cl_uint>(fmt.image_channel_order)}; >>> + for (auto x : image_format) { >>> + auto arg = argument::create(marg); >>> + >>> + arg->set(sizeof(x), &x); >>> + arg->bind(*this, marg); >>> + } >>> + break; >>> + } >>> } >>> } >>> >>> diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp >>> b/src/gallium/state_trackers/clover/core/kernel.hpp >>> index d6432a4..4ba6ff4 100644 >>> --- a/src/gallium/state_trackers/clover/core/kernel.hpp >>> +++ b/src/gallium/state_trackers/clover/core/kernel.hpp >>> @@ -190,7 +190,16 @@ namespace clover { >>> pipe_surface *st; >>> }; >>> >>> - class image_rd_argument : public argument { >>> + class image_argument : public argument { >>> + public: >>> + const image *get() const { >>> + return img; >>> + } >>> + protected: >>> + image *img; >>> + }; >>> + >>> + class image_rd_argument : public image_argument { >>> public: >>> virtual void set(size_t size, const void *value); >>> virtual void bind(exec_context &ctx, >>> @@ -198,11 +207,10 @@ namespace clover { >>> virtual void unbind(exec_context &ctx); >>> >>> private: >>> - image *img; >>> pipe_sampler_view *st; >>> }; >>> >>> - class image_wr_argument : public argument { >>> + class image_wr_argument : public image_argument { >>> public: >>> virtual void set(size_t size, const void *value); >>> virtual void bind(exec_context &ctx, >>> @@ -210,7 +218,6 @@ namespace clover { >>> virtual void unbind(exec_context &ctx); >>> >>> private: >>> - image *img; >>> pipe_surface *st; >>> }; >>> >>> diff --git a/src/gallium/state_trackers/clover/core/module.hpp >>> b/src/gallium/state_trackers/clover/core/module.hpp >>> index 9d65688..5db0548 100644 >>> --- a/src/gallium/state_trackers/clover/core/module.hpp >>> +++ b/src/gallium/state_trackers/clover/core/module.hpp >>> @@ -72,7 +72,9 @@ namespace clover { >>> enum semantic { >>> general, >>> grid_dimension, >>> - grid_offset >>> + grid_offset, >>> + image_size, >>> + image_format >>> }; >>> >>> argument(enum type type, size_t size, >>> diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp >>> b/src/gallium/state_trackers/clover/llvm/invocation.cpp >>> index 924cb36..86859af 100644 >>> --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp >>> +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp >>> @@ -344,18 +344,91 @@ namespace { >>> PM.run(*mod); >>> } >>> >>> + // Kernel metadata >>> + >>> + const llvm::MDNode * >>> + get_kernel_metadata(const llvm::Function *kernel_func) { >>> + auto mod = kernel_func->getParent(); >>> + auto kernels_node = mod->getNamedMetadata("opencl.kernels"); >>> + if (!kernels_node) { >>> + return nullptr; >>> + } >>> + >>> + const llvm::MDNode *kernel_node = nullptr; >>> + for (unsigned i = 0; i < kernels_node->getNumOperands(); ++i) { >>> +#if HAVE_LLVM >= 0x0306 >>> + auto func = llvm::mdconst::dyn_extract<llvm::Function>( >>> +#else >>> + auto func = llvm::dyn_cast<llvm::Function>( >>> +#endif >>> + >>> kernels_node->getOperand(i)->getOperand(0)); >>> + if (func == kernel_func) { >>> + kernel_node = kernels_node->getOperand(i); >>> + break; >>> + } >>> + } >>> + >>> + return kernel_node; >>> + } >>> + >>> + llvm::MDNode* >>> + node_from_op_checked(const llvm::MDOperand &md_operand, >>> + llvm::StringRef expect_name, >>> + unsigned expect_num_args) >>> + { >>> + auto node = llvm::cast<llvm::MDNode>(md_operand); >>> + assert(node->getNumOperands() == expect_num_args && >>> + "Wrong number of operands."); >>> + >>> + auto str_node = llvm::cast<llvm::MDString>(node->getOperand(0)); >>> + assert(str_node->getString() == expect_name && >>> + "Wrong metadata node name."); >>> + >>> + return node; >>> + } >>> + >>> + struct kernel_arg_md { >>> + llvm::StringRef type_name; >>> + llvm::StringRef access_qual; >>> + kernel_arg_md(llvm::StringRef type_name_, llvm::StringRef >>> access_qual_): >>> + type_name(type_name_), access_qual(access_qual_) {} >>> + }; >>> + >>> + std::vector<kernel_arg_md> >>> + get_kernel_arg_md(const llvm::Function *kernel_func) { >>> + auto num_args = kernel_func->getArgumentList().size(); >>> + >>> + auto kernel_node = get_kernel_metadata(kernel_func); >>> + auto aq = node_from_op_checked(kernel_node->getOperand(2), >>> + "kernel_arg_access_qual", num_args + >>> 1); >>> + auto ty = node_from_op_checked(kernel_node->getOperand(3), >>> + "kernel_arg_type", num_args + 1); >>> + >>> + std::vector<kernel_arg_md> res; >>> + res.reserve(num_args); >>> + for (unsigned i = 0; i < num_args; ++i) { >>> + res.push_back(kernel_arg_md( >>> + llvm::cast<llvm::MDString>(ty->getOperand(i+1))->getString(), >>> + llvm::cast<llvm::MDString>(aq->getOperand(i+1))->getString())); >>> + } >>> + >>> + return res; >>> + } >>> + >>> std::vector<module::argument> >>> get_kernel_args(const llvm::Module *mod, const std::string &kernel_name, >>> const clang::LangAS::Map &address_spaces) { >>> >>> std::vector<module::argument> args; >>> llvm::Function *kernel_func = mod->getFunction(kernel_name); >>> + assert(kernel_func && "Kernel name not found in module."); >>> + auto arg_md = get_kernel_arg_md(kernel_func); >>> >>> llvm::DataLayout TD(mod); >>> + llvm::Type *size_type = >>> + TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * >>> 8); >>> >>> - for (llvm::Function::const_arg_iterator I = kernel_func->arg_begin(), >>> - E = kernel_func->arg_end(); I != E; >>> ++I) { >>> - const llvm::Argument &arg = *I; >>> + for (const auto &arg: kernel_func->args()) { >>> >>> llvm::Type *arg_type = arg.getType(); >>> const unsigned arg_store_size = TD.getTypeStoreSize(arg_type); >>> @@ -373,6 +446,59 @@ namespace { >>> unsigned target_size = TD.getTypeStoreSize(target_type); >>> unsigned target_align = TD.getABITypeAlignment(target_type); >>> >>> + llvm::StringRef type_name = arg_md[arg.getArgNo()].type_name; >>> + llvm::StringRef access_qual = arg_md[arg.getArgNo()].access_qual; >>> + >>> + // Image >>> + const bool is_image2d = type_name == "image2d_t"; >>> + const bool is_image3d = type_name == "image3d_t"; >>> + if (is_image2d || is_image3d) { >>> + const bool is_write_only = access_qual == "write_only"; >>> + const bool is_read_only = access_qual == "read_only"; >>> + >>> + typename module::argument::type marg_type; >>> + if (is_image2d && is_read_only) { >>> + marg_type = module::argument::image2d_rd; >>> + } else if (is_image2d && is_write_only) { >>> + marg_type = module::argument::image2d_wr; >>> + } else if (is_image3d && is_read_only) { >>> + marg_type = module::argument::image3d_rd; >>> + } else if (is_image3d && is_write_only) { >>> + marg_type = module::argument::image3d_wr; >>> + } else { >>> + assert(0 && "Wrong image access qualifier"); >>> + } >>> + >>> + args.push_back(module::argument(marg_type, >>> + arg_store_size, target_size, >>> + target_align, >>> + module::argument::zero_ext)); >>> + continue; >>> + } >>> + >>> + // Image size implicit argument >>> + if (type_name == "__llvm_image_size") { >>> + args.push_back(module::argument(module::argument::scalar, >>> + sizeof(cl_uint), >>> + TD.getTypeStoreSize(size_type), >>> + >>> TD.getABITypeAlignment(size_type), >>> + module::argument::zero_ext, >>> + module::argument::image_size)); >>> + continue; >>> + } >>> + >>> + // Image format implicit argument >>> + if (type_name == "__llvm_image_format") { >>> + args.push_back(module::argument(module::argument::scalar, >>> + sizeof(cl_uint), >>> + TD.getTypeStoreSize(size_type), >>> + >>> TD.getABITypeAlignment(size_type), >>> + module::argument::zero_ext, >>> + >>> module::argument::image_format)); >>> + continue; >>> + } >>> + >>> + // Other types >>> if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) >>> { >>> arg_type = >>> >>> llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType(); >>> @@ -417,9 +543,6 @@ namespace { >>> // Append implicit arguments. XXX - The types, ordering and >>> // vector size of the implicit arguments should depend on the >>> // target according to the selected calling convention. >>> - llvm::Type *size_type = >>> - TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_uint) * >>> 8); >>> - >>> args.push_back( >>> module::argument(module::argument::scalar, sizeof(cl_uint), >>> TD.getTypeStoreSize(size_type), >>> -- >>> 2.4.6 >> >> Reviewed-by: Francisco Jerez <curroje...@riseup.net> _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev