<p dir="ltr">Sent a new patch with subject [Mesa-dev] [PATCH] clover: Pass image attributes to the kernel.</p>
<div class="gmail_quote">2015.07.06. 17:58 ezt írta ("Zoltán Gilián" <<a href="mailto:zoltan.gilian@gmail.com">zoltan.gilian@gmail.com</a>>):<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> Hint: you'll need new<br>
> module::argument::semantic enums<br>
<br>
I see. Reworked it a bit.<br>
<br>
On Mon, Jul 6, 2015 at 1:13 PM, Francisco Jerez <<a href="mailto:currojerez@riseup.net">currojerez@riseup.net</a>> wrote:<br>
> Zoltán Gilián <<a href="mailto:zoltan.gilian@gmail.com">zoltan.gilian@gmail.com</a>> writes:<br>
><br>
>>> This seems to be doing essentially the same thing as v1?  Is it the<br>
>>> right patch?<br>
>><br>
>> The llvm pass was invoked in clover in v1. This patch relies on llvm<br>
>> to perform that task (). What this patch does basically is that it<br>
>> adds the image attributes to the end of the kernel input vector.<br>
>> The commit message of this patch is misleading, I'll fix it.<br>
>><br>
> NAK.  Just like in v1, you're implementing the same pipe driver-specific<br>
> policy in Clover's core layer -- If you don't feel like fixing this<br>
> properly as I described in my reply to v1, it would be acceptable to<br>
> implement it for the time being using a workaround similar to<br>
> llvm/invocation.cpp:433 -- Hint: you'll need new<br>
> module::argument::semantic enums.<br>
><br>
> Thanks.<br>
><br>
>> On Wed, Jun 24, 2015 at 2:48 PM, Francisco Jerez <<a href="mailto:currojerez@riseup.net">currojerez@riseup.net</a>> wrote:<br>
>>> 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>
>>> This seems to be doing essentially the same thing as v1?  Is it the<br>
>>> right patch?<br>
>>><br>
>>>> ---<br>
>>>>  src/gallium/state_trackers/clover/core/kernel.cpp  | 26 +++++++<br>
>>>>  src/gallium/state_trackers/clover/core/kernel.hpp  | 13 ++--<br>
>>>>  src/gallium/state_trackers/clover/core/memory.cpp  |  2 +-<br>
>>>>  .../state_trackers/clover/llvm/invocation.cpp      | 81 +++++++++++++++++++++-<br>
>>>>  4 files changed, 116 insertions(+), 6 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..291c799 100644<br>
>>>> --- a/src/gallium/state_trackers/clover/core/kernel.cpp<br>
>>>> +++ b/src/gallium/state_trackers/clover/core/kernel.cpp<br>
>>>> @@ -185,6 +185,13 @@ kernel::exec_context::bind(intrusive_ptr<command_queue> _q,<br>
>>>>        }<br>
>>>>     }<br>
>>>><br>
>>>> +   // Bind image attribute args.<br>
>>>> +   for (const auto& arg: kern._args) {<br>
>>>> +      if (auto img_arg = dynamic_cast<image_argument*>(arg.get())) {<br>
>>>> +         img_arg->bind_attributes(*this);<br>
>>>> +      }<br>
>>>> +   }<br>
>>>> +<br>
>>>>     // Create a new compute state if anything changed.<br>
>>>>     if (!st || q != _q ||<br>
>>>>         cs.req_local_mem != mem_local ||<br>
>>>> @@ -465,6 +472,25 @@ kernel::constant_argument::unbind(exec_context &ctx) {<br>
>>>>  }<br>
>>>><br>
>>>>  void<br>
>>>> +kernel::image_argument::bind_attributes(exec_context &ctx) {<br>
>>>> +   cl_image_format format = img->format();<br>
>>>> +   cl_uint attributes[] = {<br>
>>>> +         static_cast<cl_uint>(img->width()),<br>
>>>> +         static_cast<cl_uint>(img->height()),<br>
>>>> +         static_cast<cl_uint>(img->depth()),<br>
>>>> +         format.image_channel_data_type,<br>
>>>> +         format.image_channel_order};<br>
>>>> +   for (unsigned i = 0; i < 5; ++i) {<br>
>>>> +      auto v = bytes(attributes[i]);<br>
>>>> +<br>
>>>> +      extend(v, module::argument::zero_ext, sizeof(cl_uint));<br>
>>>> +      byteswap(v, ctx.q->device().endianness());<br>
>>>> +      align(ctx.input, sizeof(cl_uint));<br>
>>>> +      insert(ctx.input, v);<br>
>>>> +   }<br>
>>>> +}<br>
>>>> +<br>
>>>> +void<br>
>>>>  kernel::image_rd_argument::set(size_t size, const void *value) {<br>
>>>>     if (size != sizeof(cl_mem))<br>
>>>>        throw error(CL_INVALID_ARG_SIZE);<br>
>>>> diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp b/src/gallium/state_trackers/clover/core/kernel.hpp<br>
>>>> index d6432a4..8c15b2f 100644<br>
>>>> --- a/src/gallium/state_trackers/clover/core/kernel.hpp<br>
>>>> +++ b/src/gallium/state_trackers/clover/core/kernel.hpp<br>
>>>> @@ -190,7 +190,14 @@ namespace clover {<br>
>>>>           pipe_surface *st;<br>
>>>>        };<br>
>>>><br>
>>>> -      class image_rd_argument : public argument {<br>
>>>> +      class image_argument : public argument {<br>
>>>> +      public:<br>
>>>> +         void bind_attributes(exec_context &ctx);<br>
>>>> +      protected:<br>
>>>> +         image *img;<br>
>>>> +      };<br>
>>>> +<br>
>>>> +      class image_rd_argument : public image_argument {<br>
>>>>        public:<br>
>>>>           virtual void set(size_t size, const void *value);<br>
>>>>           virtual void bind(exec_context &ctx,<br>
>>>> @@ -198,11 +205,10 @@ namespace clover {<br>
>>>>           virtual void unbind(exec_context &ctx);<br>
>>>><br>
>>>>        private:<br>
>>>> -         image *img;<br>
>>>>           pipe_sampler_view *st;<br>
>>>>        };<br>
>>>><br>
>>>> -      class image_wr_argument : public argument {<br>
>>>> +      class image_wr_argument : public image_argument {<br>
>>>>        public:<br>
>>>>           virtual void set(size_t size, const void *value);<br>
>>>>           virtual void bind(exec_context &ctx,<br>
>>>> @@ -210,7 +216,6 @@ namespace clover {<br>
>>>>           virtual void unbind(exec_context &ctx);<br>
>>>><br>
>>>>        private:<br>
>>>> -         image *img;<br>
>>>>           pipe_surface *st;<br>
>>>>        };<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..a33d450 100644<br>
>>>> --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp<br>
>>>> +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp<br>
>>>> @@ -80,6 +80,7 @@<br>
>>>>  using namespace clover;<br>
>>>><br>
>>>>  namespace {<br>
>>>> +<br>
>>>>  #if 0<br>
>>>>     void<br>
>>>>     build_binary(const std::string &source, const std::string &target,<br>
>>>> @@ -340,17 +341,65 @@ namespace {<br>
>>>>        PM.run(*mod);<br>
>>>>     }<br>
>>>><br>
>>>> +   const llvm::MDNode *<br>
>>>> +   get_kernel_metadata(const llvm::Function *kernel_func) {<br>
>>>> +      auto mod = kernel_func->getParent();<br>
>>>> +      auto kernels_node = mod->getNamedMetadata("opencl.kernels");<br>
>>>> +      if (!kernels_node) {<br>
>>>> +         return nullptr;<br>
>>>> +      }<br>
>>>> +<br>
>>>> +      const llvm::MDNode *kernel_node = nullptr;<br>
>>>> +      for (unsigned i = 0; i < kernels_node->getNumOperands(); ++i) {<br>
>>>> +#if HAVE_LLVM >= 0x0306<br>
>>>> +         auto func = llvm::mdconst::dyn_extract<llvm::Function>(<br>
>>>> +#else<br>
>>>> +         auto func = llvm::dyn_cast<llvm::Function>(<br>
>>>> +#endif<br>
>>>> +                                    kernels_node->getOperand(i)->getOperand(0));<br>
>>>> +         if (func == kernel_func) {<br>
>>>> +            kernel_node = kernels_node->getOperand(i);<br>
>>>> +            break;<br>
>>>> +         }<br>
>>>> +      }<br>
>>>> +<br>
>>>> +      return kernel_node;<br>
>>>> +   }<br>
>>>> +<br>
>>>> +   std::vector<llvm::StringRef><br>
>>>> +   get_kernel_access_qualifiers(const llvm::Function *kernel_func) {<br>
>>>> +      auto num_args = kernel_func->getArgumentList().size();<br>
>>>> +      auto access_quals = std::vector<llvm::StringRef>(num_args);<br>
>>>> +<br>
>>>> +      auto kernel_node = get_kernel_metadata(kernel_func);<br>
>>>> +      auto aq_node = llvm::cast<llvm::MDNode>(kernel_node->getOperand(2));<br>
>>>> +      auto str_node = llvm::cast<llvm::MDString>(aq_node->getOperand(0));<br>
>>>> +      assert(str_node->getString() == "kernel_arg_access_qual" &&<br>
>>>> +             "Cannot find kernel_arg_access_qual metadata node.");<br>
>>>> +      assert(aq_node->getNumOperands() == num_args + 1 &&<br>
>>>> +             "Wrong number of operands in kernel_arg_access_qual metadata.");<br>
>>>> +<br>
>>>> +      for (unsigned i = 1; i < aq_node->getNumOperands(); ++i) {<br>
>>>> +        auto aq = llvm::cast<llvm::MDString>(aq_node->getOperand(i));<br>
>>>> +        access_quals[i-1] = aq->getString();<br>
>>>> +      }<br>
>>>> +<br>
>>>> +      return access_quals;<br>
>>>> +   }<br>
>>>> +<br>
>>>>     std::vector<module::argument><br>
>>>>     get_kernel_args(const llvm::Module *mod, const std::string &kernel_name,<br>
>>>>                     const clang::LangAS::Map &address_spaces) {<br>
>>>><br>
>>>>        std::vector<module::argument> args;<br>
>>>>        llvm::Function *kernel_func = mod->getFunction(kernel_name);<br>
>>>> +      auto access_quals = get_kernel_access_qualifiers(kernel_func);<br>
>>>><br>
>>>>        llvm::DataLayout TD(mod);<br>
>>>><br>
>>>> +      unsigned arg_idx = 0;<br>
>>>>        for (llvm::Function::const_arg_iterator I = kernel_func->arg_begin(),<br>
>>>> -                                      E = kernel_func->arg_end(); I != E; ++I) {<br>
>>>> +                           E = kernel_func->arg_end(); I != E; ++I, ++arg_idx) {<br>
>>>>           const llvm::Argument &arg = *I;<br>
>>>><br>
>>>>           llvm::Type *arg_type = arg.getType();<br>
>>>> @@ -375,6 +424,36 @@ 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>
>>>> +               llvm::StringRef type_name = elem_type->getStructName();<br>
>>>> +               llvm::StringRef access_qual = access_quals[arg_idx];<br>
>>>> +<br>
>>>> +               typename module::argument::type marg_type;<br>
>>>> +               if (type_name.startswith("opencl.image2d_t")) {<br>
>>>> +                  if (access_qual == "write_only") {<br>
>>>> +                     marg_type = module::argument::image2d_wr;<br>
>>>> +                  } else {<br>
>>>> +                     marg_type = module::argument::image2d_rd;<br>
>>>> +                  }<br>
>>>> +               } else if (type_name.startswith("opencl.image3d_t")) {<br>
>>>> +                  if (access_qual == "write_only") {<br>
>>>> +                     marg_type = module::argument::image3d_wr;<br>
>>>> +                  } else {<br>
>>>> +                     marg_type = module::argument::image3d_rd;<br>
>>>> +                  }<br>
>>>> +               } else {<br>
>>>> +                  continue;<br>
>>>> +               }<br>
>>>> +<br>
>>>> +               args.push_back(module::argument(marg_type,<br>
>>>> +                              arg_store_size, target_size, target_align,<br>
>>>> +                              module::argument::zero_ext));<br>
>>>> +               continue;<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>
</blockquote></div>