clover: Pass execution dimensions and offset to the kernel as implicit arguments.
authorFrancisco Jerez <currojerez@riseup.net>
Wed, 8 Oct 2014 14:39:35 +0000 (17:39 +0300)
committerFrancisco Jerez <currojerez@riseup.net>
Sat, 11 Oct 2014 22:44:19 +0000 (01:44 +0300)
Reviewed-by: Jan Vesely <jan.vesely@rutgers.edu>
src/gallium/state_trackers/clover/core/kernel.cpp
src/gallium/state_trackers/clover/core/kernel.hpp

index e4b2152e4abfacb3b45846ce18305da4a774a4df..947e785903ebc362b88d728200c0fff5c1a32a95 100644 (file)
@@ -33,24 +33,8 @@ kernel::kernel(clover::program &prog, const std::string &name,
    program(prog), _name(name), exec(*this),
    program_ref(prog._kernel_ref_counter) {
    for (auto &marg : margs) {
-      if (marg.type == module::argument::scalar)
-         _args.emplace_back(new scalar_argument(marg.size));
-      else if (marg.type == module::argument::global)
-         _args.emplace_back(new global_argument);
-      else if (marg.type == module::argument::local)
-         _args.emplace_back(new local_argument);
-      else if (marg.type == module::argument::constant)
-         _args.emplace_back(new constant_argument);
-      else if (marg.type == module::argument::image2d_rd ||
-               marg.type == module::argument::image3d_rd)
-         _args.emplace_back(new image_rd_argument);
-      else if (marg.type == module::argument::image2d_wr ||
-               marg.type == module::argument::image3d_wr)
-         _args.emplace_back(new image_wr_argument);
-      else if (marg.type == module::argument::sampler)
-         _args.emplace_back(new sampler_argument);
-      else
-         throw error(CL_INVALID_KERNEL_DEFINITION);
+      if (marg.semantic == module::argument::general)
+         _args.emplace_back(argument::create(marg));
    }
 }
 
@@ -70,7 +54,7 @@ kernel::launch(command_queue &q,
    const auto m = program().binary(q.device());
    const auto reduced_grid_size =
       map(divides(), grid_size, block_size);
-   void *st = exec.bind(&q);
+   void *st = exec.bind(&q, grid_offset);
 
    // The handles are created during exec_context::bind(), so we need make
    // sure to call exec_context::bind() before retrieving them.
@@ -165,17 +149,38 @@ kernel::exec_context::~exec_context() {
 }
 
 void *
-kernel::exec_context::bind(intrusive_ptr<command_queue> _q) {
+kernel::exec_context::bind(intrusive_ptr<command_queue> _q,
+                           const std::vector<size_t> &grid_offset) {
    std::swap(q, _q);
 
    // Bind kernel arguments.
    auto &m = kern.program().binary(q->device());
    auto margs = find(name_equals(kern.name()), m.syms).args;
    auto msec = find(type_equals(module::section::text), m.secs);
+   auto explicit_arg = kern._args.begin();
 
-   for_each([=](kernel::argument &karg, const module::argument &marg) {
-               karg.bind(*this, marg);
-            }, kern.args(), margs);
+   for (auto &marg : margs) {
+      switch (marg.semantic) {
+      case module::argument::general:
+         (*(explicit_arg++))->bind(*this, marg);
+
+      case module::argument::grid_dimension: {
+         const cl_uint dimension = grid_offset.size();
+         auto arg = argument::create(marg);
+
+         arg->set(sizeof(dimension), &dimension);
+         arg->bind(*this, marg);
+      }
+      case module::argument::grid_offset: {
+         for (cl_uint x : pad_vector(*q, grid_offset, 1)) {
+            auto arg = argument::create(marg);
+
+            arg->set(sizeof(x), &x);
+            arg->bind(*this, marg);
+         }
+      }
+      }
+   }
 
    // Create a new compute state if anything changed.
    if (!st || q != _q ||
@@ -283,6 +288,42 @@ namespace {
    }
 }
 
+std::unique_ptr<kernel::argument>
+kernel::argument::create(const module::argument &marg) {
+      if (marg.type == module::argument::scalar)
+         return std::unique_ptr<kernel::argument>(
+            new scalar_argument(marg.size));
+
+      else if (marg.type == module::argument::global)
+         return std::unique_ptr<kernel::argument>(
+            new global_argument);
+
+      else if (marg.type == module::argument::local)
+         return std::unique_ptr<kernel::argument>(
+            new local_argument);
+
+      else if (marg.type == module::argument::constant)
+         return std::unique_ptr<kernel::argument>(
+            new constant_argument);
+
+      else if (marg.type == module::argument::image2d_rd ||
+               marg.type == module::argument::image3d_rd)
+         return std::unique_ptr<kernel::argument>(
+            new image_rd_argument);
+
+      else if (marg.type == module::argument::image2d_wr ||
+               marg.type == module::argument::image3d_wr)
+         return std::unique_ptr<kernel::argument>(
+            new image_wr_argument);
+
+      else if (marg.type == module::argument::sampler)
+         return std::unique_ptr<kernel::argument>(
+            new sampler_argument);
+
+      else
+         throw error(CL_INVALID_KERNEL_DEFINITION);
+}
+
 kernel::argument::argument() : _set(false) {
 }
 
index f9e2765ee365ae818194e25d7c2805ff912ce798..bf5998de8257ce98c0ff3c18201d2d49f189bc90 100644 (file)
@@ -46,7 +46,8 @@ namespace clover {
          exec_context &
          operator=(const exec_context &) = delete;
 
-         void *bind(intrusive_ptr<command_queue> _q);
+         void *bind(intrusive_ptr<command_queue> _q,
+                    const std::vector<size_t> &grid_offset);
          void unbind();
 
          kernel &kern;
@@ -68,7 +69,8 @@ namespace clover {
    public:
       class argument {
       public:
-         argument();
+         static std::unique_ptr<argument>
+         create(const module::argument &marg);
 
          argument(const argument &arg) = delete;
          argument &
@@ -92,6 +94,8 @@ namespace clover {
          virtual void unbind(exec_context &ctx) = 0;
 
       protected:
+         argument();
+
          bool _set;
       };