[Mesa-dev] [PATCH 6/7] clover: Align kernel arguments when storing them in the input buffer v2

Tom Stellard tom at stellard.net
Tue Jul 9 21:21:43 PDT 2013


From: Tom Stellard <thomas.stellard at amd.com>

v2:
  - Use a 'pad' argument to align arguments to the correct size.
---
 .../state_trackers/clover/core/compiler.hpp        |  3 +-
 src/gallium/state_trackers/clover/core/kernel.cpp  | 16 ++++++-
 src/gallium/state_trackers/clover/core/kernel.hpp  |  3 ++
 src/gallium/state_trackers/clover/core/module.hpp  | 13 ++++--
 src/gallium/state_trackers/clover/core/program.cpp |  4 +-
 .../state_trackers/clover/llvm/invocation.cpp      | 53 ++++++++++++++++++----
 .../state_trackers/clover/tgsi/compiler.cpp        | 27 +++++++----
 7 files changed, 91 insertions(+), 28 deletions(-)

diff --git a/src/gallium/state_trackers/clover/core/compiler.hpp b/src/gallium/state_trackers/clover/core/compiler.hpp
index b8af1c8..b1df312 100644
--- a/src/gallium/state_trackers/clover/core/compiler.hpp
+++ b/src/gallium/state_trackers/clover/core/compiler.hpp
@@ -54,8 +54,7 @@ namespace clover {
    };
 
    module compile_program_llvm(const compat::string &source,
-                               enum pipe_shader_ir ir,
-                               const compat::string &target,
+                               const struct pipe_screen *pipe,
                                const compat::string &opts);
 
    module compile_program_tgsi(const compat::string &source);
diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp
index c95285d..2b6fbe5 100644
--- a/src/gallium/state_trackers/clover/core/kernel.cpp
+++ b/src/gallium/state_trackers/clover/core/kernel.cpp
@@ -31,6 +31,8 @@ _cl_kernel::_cl_kernel(clover::program &prog,
                        const std::vector<clover::module::argument> &args) :
    prog(prog), __name(name), exec(*this) {
    for (auto arg : args) {
+      if (arg.type == module::argument::pad)
+         continue;
       if (arg.type == module::argument::scalar)
          this->args.emplace_back(new scalar_argument(arg.size));
       else if (arg.type == module::argument::global)
@@ -129,6 +131,10 @@ _cl_kernel::module(const clover::command_queue &q) const {
    return prog.binaries().find(&q.dev)->second;
 }
 
+const clover::compat::vector<clover::module::argument> &
+_cl_kernel::module_args(const clover::command_queue &q) const {
+   return module(q).sym(__name).args;
+}
 
 _cl_kernel::exec_context::exec_context(clover::kernel &kern) :
    kern(kern), q(NULL), mem_local(0), st(NULL) {
@@ -143,8 +149,14 @@ void *
 _cl_kernel::exec_context::bind(clover::command_queue *__q) {
    std::swap(q, __q);
 
-   for (auto &arg : kern.args)
-      arg->bind(*this);
+   for (const clover::module::argument &arg : kern.module_args(*q)) {
+      if (arg.type == clover::module::argument::pad) {
+         input.resize(input.size() + arg.size);
+      } else {
+         assert(arg.arg_index >= 0);
+         kern.args[arg.arg_index]->bind(*this);
+      }
+   }
 
    // Create a new compute state if anything changed.
    if (!st || q != __q ||
diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp b/src/gallium/state_trackers/clover/core/kernel.hpp
index 6b336d0..2c540be 100644
--- a/src/gallium/state_trackers/clover/core/kernel.hpp
+++ b/src/gallium/state_trackers/clover/core/kernel.hpp
@@ -117,6 +117,9 @@ private:
    const clover::module &
    module(const clover::command_queue &q) const;
 
+   const clover::compat::vector<clover::module::argument> &
+   module_args(const clover::command_queue &q) const;
+
    class scalar_argument : public argument {
    public:
       scalar_argument(size_t size);
diff --git a/src/gallium/state_trackers/clover/core/module.hpp b/src/gallium/state_trackers/clover/core/module.hpp
index 88dfc9f..d4b3413 100644
--- a/src/gallium/state_trackers/clover/core/module.hpp
+++ b/src/gallium/state_trackers/clover/core/module.hpp
@@ -65,14 +65,21 @@ namespace clover {
             image2d_wr,
             image3d_rd,
             image3d_wr,
-            sampler
+            sampler,
+            pad
          };
 
-         argument(enum type type, size_t size) : type(type), size(size) { }
-         argument() : type(scalar), size(0) { }
+         argument(enum type type, size_t size, size_t arg_index) : type(type),
+                      size(size), arg_index(arg_index) { }
+         argument(enum type type, size_t size) : type(type), size(size),
+                      arg_index(-1) { }
+         argument() : type(scalar), size(0), arg_index(-1) { }
 
          type type;
          size_t size;
+         /// The index of this argument in the function.  If arg_index is -1,
+         /// then this arguement is not a formal argument of the function.
+         size_t arg_index;
       };
 
       struct symbol {
diff --git a/src/gallium/state_trackers/clover/core/program.cpp b/src/gallium/state_trackers/clover/core/program.cpp
index e85f27a..1e5a126 100644
--- a/src/gallium/state_trackers/clover/core/program.cpp
+++ b/src/gallium/state_trackers/clover/core/program.cpp
@@ -53,8 +53,8 @@ _cl_program::build(const std::vector<clover::device *> &devs,
       try {
          auto module = (dev->ir_format() == PIPE_SHADER_IR_TGSI ?
                         compile_program_tgsi(__source) :
-                        compile_program_llvm(__source, dev->ir_format(),
-                        dev->ir_target(), build_opts(dev)));
+                        compile_program_llvm(__source, dev->get_pipe(),
+                                             build_opts(dev)));
          __binaries.insert({ dev, module });
 
       } catch (build_error &e) {
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
index dae61f7..68f7eac 100644
--- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
+++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
@@ -20,6 +20,7 @@
 // OTHER DEALINGS IN THE SOFTWARE.
 //
 
+#include "pipe/p_screen.h"
 #include "core/compiler.hpp"
 
 #include <clang/Frontend/CompilerInstance.h>
@@ -58,6 +59,7 @@
 #endif
 
 #include "pipe/p_state.h"
+#include "util/u_math.h"
 #include "util/u_memory.h"
 
 #include <iostream>
@@ -282,6 +284,7 @@ namespace {
 
    module
    build_module_llvm(llvm::Module *mod,
+                     const struct pipe_screen *pipe,
                      const std::vector<llvm::Function *> &kernels) {
 
       module m;
@@ -311,6 +314,18 @@ namespace {
             llvm::DataLayout TD(kernel_func->getParent()->getDataLayout());
 #endif
             unsigned arg_size = TD.getTypeStoreSize(arg_type);
+            size_t alignment = arg_size;
+            pipe->get_compute_param(pipe, PIPE_COMPUTE_CAP_KERNEL_ARG_ALIGNMENT,
+                                    &alignment);
+            unsigned aligned_size = align(arg_size, alignment);
+            size_t target_size;
+            if (arg_type->isIntegerTy()) {
+               llvm::Type *target_type = TD.getSmallestLegalIntType(
+                     mod->getContext(), arg_type->getPrimitiveSizeInBits());
+               target_size = target_type->getPrimitiveSizeInBits();
+            } else {
+               target_size = aligned_size;
+            }
 
             if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) {
                arg_type =
@@ -324,11 +339,17 @@ namespace {
                unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace();
                switch (address_space) {
                   default:
-                     args.push_back(module::argument(module::argument::global, arg_size));
+                     args.push_back(module::argument(module::argument::global,
+                                                     arg_size, arg.getArgNo()));
                      break;
                }
             } else {
-               args.push_back(module::argument(module::argument::scalar, arg_size));
+               args.push_back(module::argument(module::argument::scalar,
+                                               arg_size, arg.getArgNo()));
+            }
+            if (aligned_size > target_size) {
+               args.push_back(module::argument(module::argument::pad,
+                                               aligned_size - target_size));
             }
          }
 
@@ -349,15 +370,24 @@ namespace {
 
 module
 clover::compile_program_llvm(const compat::string &source,
-                             enum pipe_shader_ir ir,
-                             const compat::string &target,
+                             const struct pipe_screen *pipe,
                              const compat::string &opts) {
 
    std::vector<llvm::Function *> kernels;
-   size_t processor_str_len = std::string(target.begin()).find_first_of("-");
-   std::string processor(target.begin(), 0, processor_str_len);
-   std::string triple(target.begin(), processor_str_len + 1,
-                      target.size() - processor_str_len - 1);
+   enum pipe_shader_ir ir = (enum pipe_shader_ir) pipe->get_shader_param(pipe,
+                                                  PIPE_SHADER_COMPUTE,
+                                                  PIPE_SHADER_CAP_PREFERRED_IR);
+   size_t target_str_len = pipe->get_compute_param(pipe,
+                                              PIPE_COMPUTE_CAP_IR_TARGET, NULL);
+   char *target = (char*)MALLOC(target_str_len);
+   pipe->get_compute_param(pipe, PIPE_COMPUTE_CAP_IR_TARGET, target);
+
+   size_t processor_str_len = strchr(target, '-') - target;
+   char *triple_start = target + processor_str_len + 1;
+   size_t triple_str_len = strlen(target) - processor_str_len - 1;
+
+   std::string processor(target, processor_str_len);
+   std::string triple(triple_start, triple_str_len);
 
    // The input file name must have the .cl extension in order for the
    // CompilerInvocation class to recognize it as an OpenCL source file.
@@ -367,13 +397,16 @@ clover::compile_program_llvm(const compat::string &source,
 
    link(mod, triple, processor, kernels);
 
+   module clover_mod;
    // Build the clover::module
    switch (ir) {
       case PIPE_SHADER_IR_TGSI:
          //XXX: Handle TGSI
          assert(0);
-         return module();
+         clover_mod = module();
       default:
-         return build_module_llvm(mod, kernels);
+         clover_mod = build_module_llvm(mod, pipe, kernels);
    }
+   FREE(target);
+   return clover_mod;
 }
diff --git a/src/gallium/state_trackers/clover/tgsi/compiler.cpp b/src/gallium/state_trackers/clover/tgsi/compiler.cpp
index 93dfeb5..698c504 100644
--- a/src/gallium/state_trackers/clover/tgsi/compiler.cpp
+++ b/src/gallium/state_trackers/clover/tgsi/compiler.cpp
@@ -50,23 +50,32 @@ namespace {
 
          while (ts >> tok) {
             if (tok == "scalar")
-               args.push_back({ module::argument::scalar, 4 });
+               args.push_back({ module::argument::scalar, 4,
+                                (module::size_t) args.size() });
             else if (tok == "global")
-               args.push_back({ module::argument::global, 4 });
+               args.push_back({ module::argument::global, 4,
+                                (module::size_t) args.size() });
             else if (tok == "local")
-               args.push_back({ module::argument::local, 4 });
+               args.push_back({ module::argument::local, 4,
+                                (module::size_t) args.size() });
             else if (tok == "constant")
-               args.push_back({ module::argument::constant, 4 });
+               args.push_back({ module::argument::constant, 4,
+                                (module::size_t) args.size() });
             else if (tok == "image2d_rd")
-               args.push_back({ module::argument::image2d_rd, 4 });
+               args.push_back({ module::argument::image2d_rd, 4,
+                                (module::size_t) args.size() });
             else if (tok == "image2d_wr")
-               args.push_back({ module::argument::image2d_wr, 4 });
+               args.push_back({ module::argument::image2d_wr, 4,
+                                (module::size_t) args.size() });
             else if (tok == "image3d_rd")
-               args.push_back({ module::argument::image3d_rd, 4 });
+               args.push_back({ module::argument::image3d_rd, 4,
+                                (module::size_t) args.size() });
             else if (tok == "image3d_wr")
-               args.push_back({ module::argument::image3d_wr, 4 });
+               args.push_back({ module::argument::image3d_wr, 4,
+                                (module::size_t) args.size() });
             else if (tok == "sampler")
-               args.push_back({ module::argument::sampler, 0 });
+               args.push_back({ module::argument::sampler, 0,
+                                (module::size_t) args.size() });
             else
                throw build_error("invalid kernel argument");
          }
-- 
1.7.11.4



More information about the mesa-dev mailing list