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