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