Ok, thanks for the feedback. On Mon, Jun 8, 2015 at 2:18 PM, Francisco Jerez <curroje...@riseup.net> wrote:
> Zoltan Gilian <zoltan.gil...@gmail.com> writes: > > > Image attributes are passed to the kernel as hidden parameters after the > > image attribute itself. An llvm pass replaces the getter builtins to > > the appropriate parameters. > > --- > > src/gallium/state_trackers/clover/core/kernel.cpp | 13 ++ > > src/gallium/state_trackers/clover/core/memory.cpp | 2 +- > > .../state_trackers/clover/llvm/invocation.cpp | 158 > ++++++++++++++++++++- > > 3 files changed, 170 insertions(+), 3 deletions(-) > > > > diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp > b/src/gallium/state_trackers/clover/core/kernel.cpp > > index 0756f06..4703899 100644 > > --- a/src/gallium/state_trackers/clover/core/kernel.cpp > > +++ b/src/gallium/state_trackers/clover/core/kernel.cpp > > @@ -483,6 +483,19 @@ kernel::image_rd_argument::bind(exec_context &ctx, > > align(ctx.input, marg.target_align); > > insert(ctx.input, v); > > > > + cl_image_format fmt = img->format(); > > + cl_uint image_attribs[] = {img->width(), img->height(), img->depth(), > > + fmt.image_channel_data_type, > > + fmt.image_channel_order}; > > + for (int i = 0; i < 5; i++) { > > + auto v = bytes(image_attribs[i]); > > + > > + extend(v, module::argument::zero_ext, marg.target_size); > > + byteswap(v, ctx.q->device().endianness()); > > + align(ctx.input, marg.target_align); > > + insert(ctx.input, v); > > + } > > + > This seems to be implementing driver-specific policy in a > hardware-independent state tracker. Whether you need to pass the image > dimensions and data type to the kernel as explicit parameters or not > (e.g. because your hardware already supports some sort of image metadata > query opcode) is driver-specific, so it would probably be a better idea > to append these parameters at the end of the input buffer in the r600 > pipe driver itself. > > > st = img->resource(*ctx.q).bind_sampler_view(*ctx.q); > > ctx.sviews.push_back(st); > > } > > diff --git a/src/gallium/state_trackers/clover/core/memory.cpp > b/src/gallium/state_trackers/clover/core/memory.cpp > > index 055336a..b852e68 100644 > > --- a/src/gallium/state_trackers/clover/core/memory.cpp > > +++ b/src/gallium/state_trackers/clover/core/memory.cpp > > @@ -189,7 +189,7 @@ image2d::image2d(clover::context &ctx, cl_mem_flags > flags, > > const cl_image_format *format, size_t width, > > size_t height, size_t row_pitch, > > void *host_ptr) : > > - image(ctx, flags, format, width, height, 0, > > + image(ctx, flags, format, width, height, 1, > > row_pitch, 0, height * row_pitch, host_ptr) { > > } > > > > diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp > b/src/gallium/state_trackers/clover/llvm/invocation.cpp > > index 9b91fee..5d5e619 100644 > > --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp > > +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp > > @@ -33,6 +33,8 @@ > > #include <llvm/IR/DiagnosticInfo.h> > > #include <llvm/IR/DiagnosticPrinter.h> > > #include <llvm/IR/DerivedTypes.h> > > +#include <llvm/IR/InstIterator.h> > > +#include <llvm/IR/Instructions.h> > > #include <llvm/IR/LLVMContext.h> > > #include <llvm/IR/Module.h> > > #include <llvm/Support/SourceMgr.h> > > @@ -80,6 +82,130 @@ > > using namespace clover; > > > > namespace { > > + > > + /* LLVM pass to resolve get_image_* OpenCL builtins. > > + * The image attributes (e.g. width or channel order) are passed as > hidden > > + * arguments to the kernel. > > + * This pass replaces specific function calls with the appropriate > hidden > > + * arguments. The libclc library needs to implements the get_image_* > > + * builtins as these specific functions to avoid dealing with name > mangling > > + * here. > > + */ > > + struct OpenCLImageBuiltinPass : public llvm::FunctionPass { > > + static char ID; > > + > > + OpenCLImageBuiltinPass(): llvm::FunctionPass(ID) {} > > + bool runOnFunction(llvm::Function &F) override; > > + > > + struct ImageAttribArgs { > > + ImageAttribArgs(): image_arg(0), > > + width_arg(0), > > + heigth_arg(0), > > + depth_arg(0), > > + channel_data_type_arg(0), > > + channel_order_arg(0) {} > > + llvm::Argument* image_arg; > > + llvm::Argument* width_arg; > > + llvm::Argument* heigth_arg; > > + llvm::Argument* depth_arg; > > + llvm::Argument* channel_data_type_arg; > > + llvm::Argument* channel_order_arg; > > + }; > > + }; > > + > > + char OpenCLImageBuiltinPass::ID = 0; > > + > > + bool > > + OpenCLImageBuiltinPass::runOnFunction(llvm::Function& F) > > + { > > + llvm::Module* mod = F.getParent(); > > + llvm::DataLayout TD(mod); > > + llvm::Type* cl_int_type = > > + TD.getSmallestLegalIntType(mod->getContext(), sizeof(cl_int)); > > + > > + std::vector<ImageAttribArgs> img_args; > > + for (auto arg = F.arg_begin(), E = F.arg_end(); arg != E; ++arg) { > > + > > + llvm::Type *arg_type = arg->getType(); > > + if (!arg_type->isPointerTy()) continue; > > + > > + llvm::Type *elem_type = arg_type->getPointerElementType(); > > + if (!elem_type->isStructTy()) continue; > > + > > + const llvm::StringRef &type_name = elem_type->getStructName(); > > + if (!type_name.startswith("opencl.image2d_t")) continue; > > + > > + auto name_suffix = llvm::Twine(img_args.size()); > > + ImageAttribArgs attrib_args; > > + attrib_args.image_arg = arg; > > + attrib_args.width_arg = new llvm::Argument( > > + cl_int_type, "image_width" + name_suffix); > > + attrib_args.heigth_arg = new llvm::Argument( > > + cl_int_type, "image_height" + name_suffix); > > + attrib_args.depth_arg = new llvm::Argument( > > + cl_int_type, "image_depth" + name_suffix); > > + attrib_args.channel_data_type_arg = new llvm::Argument( > > + cl_int_type, "image_channel_data_type" + name_suffix); > > + attrib_args.channel_order_arg = new llvm::Argument( > > + cl_int_type, "image_channel_order" + name_suffix); > > + > > + auto& args = F.getArgumentList(); > > + args.insertAfter(arg, attrib_args.channel_order_arg); > > + args.insertAfter(arg, attrib_args.channel_data_type_arg); > > + args.insertAfter(arg, attrib_args.depth_arg); > > + args.insertAfter(arg, attrib_args.heigth_arg); > > + args.insertAfter(arg, attrib_args.width_arg); > > + > > + img_args.push_back(attrib_args); > > + } > > + std::vector<llvm::Instruction*> insts_to_erase; > > + for (auto I = llvm::inst_begin(F), E = llvm::inst_end(F); I != E; > ++I) { > > + llvm::CallInst* callInst = llvm::dyn_cast<llvm::CallInst>(&*I); > > + if (!callInst) continue; > > + > > + for (auto& op: callInst->arg_operands()) { > > + auto op_arg = op.get(); > > + auto image_arg = std::find_if( > > + img_args.begin(), img_args.end(), > > + [op_arg](const ImageAttribArgs& x) { > > + return x.image_arg == op_arg; > > + }); > > + if (image_arg == img_args.end()) continue; > > + > > + llvm::Function* callee = callInst->getCalledFunction(); > > + if (!callee) continue; > > + > > + auto callee_name = callee->getName(); > > + if (callee_name.startswith( > > + "llvm.opencl.image.get.width")) { > > + callInst->replaceAllUsesWith(image_arg->width_arg); > > + insts_to_erase.push_back(callInst); > > + } else if (callee_name.startswith( > > + "llvm.opencl.image.get.height")) { > > + callInst->replaceAllUsesWith(image_arg->heigth_arg); > > + insts_to_erase.push_back(callInst); > > + } else if (callee_name.startswith( > > + "llvm.opencl.image.get.depth")) { > > + callInst->replaceAllUsesWith(image_arg->depth_arg); > > + insts_to_erase.push_back(callInst); > > + } else if (callee_name.startswith( > > + "llvm.opencl.image.get.channel_data_type")) { > > + > callInst->replaceAllUsesWith(image_arg->channel_data_type_arg); > > + insts_to_erase.push_back(callInst); > > + } else if (callee_name.startswith( > > + "llvm.opencl.image.get.channel_order")) { > > + > callInst->replaceAllUsesWith(image_arg->channel_order_arg); > > + insts_to_erase.push_back(callInst); > > + } > > + } > > + } > > + for (auto inst: insts_to_erase) { > > + inst->eraseFromParent(); > > + } > > + > > + return (img_args.size() > 0); > > + } > > + > > #if 0 > > void > > build_binary(const std::string &source, const std::string &target, > > @@ -263,10 +389,21 @@ namespace { > > > sizeof(address_spaces)); > > > > #if HAVE_LLVM >= 0x0306 > > - return act.takeModule().release(); > > + llvm::Module * module = act.takeModule().release(); > > +#else > > + llvm::Module * module = act.takeModule(); > > +#endif > > + > > + // Resolve get_image_* builtins. > > +#if HAVE_LLVM >= 0x0307 > > + llvm::legacy::PassManager PM; > > #else > > - return act.takeModule(); > > + llvm::PassManager PM; > > #endif > > + PM.add(new OpenCLImageBuiltinPass()); > > + PM.run(*module); > > + > > + return module; > > } > > > > void > > @@ -375,6 +512,23 @@ namespace { > > } > > > > if (arg_type->isPointerTy()) { > > + // XXX: Figure out LLVM->OpenCL address space mappings for > each > > + // target. I think we need to ask clang what these are. > For now, > > + // pretend everything is in the global address space. > > + llvm::Type *elem_type = arg_type->getPointerElementType(); > > + if (elem_type->isStructTy()) { > > + const llvm::StringRef &type_name = > elem_type->getStructName(); > > + > > + if (type_name.startswith("opencl.image2d_t")) { > > + > args.push_back(module::argument(module::argument::image2d_rd, > > + arg_store_size, target_size, > target_align, > > + module::argument::zero_ext)); > > + // Skip hidden image attribute arguments. > > + // XXX: Do this based on some kind of metadata. > > + std::advance(I, 5); > > + continue; > > + } > > + } > > unsigned address_space = > llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace(); > > if (address_space == > address_spaces[clang::LangAS::opencl_local > > - > clang::LangAS::Offset]) { > > -- > > 2.4.2 > > > > _______________________________________________ > > mesa-dev mailing list > > mesa-dev@lists.freedesktop.org > > http://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev