[Mesa-dev] [PATCH 1/2] clover: Implement image attribute getters
Zoltán Gilián
zoltan.gilian at gmail.com
Tue Jun 9 02:09:02 PDT 2015
Ok, thanks for the feedback.
On Mon, Jun 8, 2015 at 2:18 PM, Francisco Jerez <currojerez at riseup.net>
wrote:
> Zoltan Gilian <zoltan.gilian at 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 at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150609/48e6eca8/attachment-0001.html>
More information about the mesa-dev
mailing list