From: Tom Stellard <thomas.stell...@amd.com> v2: - Extend to target size rather than aligned size - Support for big-endian --- src/gallium/state_trackers/clover/core/kernel.cpp | 58 ++++++++++++++++------ src/gallium/state_trackers/clover/core/kernel.hpp | 17 ++++--- src/gallium/state_trackers/clover/core/module.hpp | 27 ++++++++-- .../state_trackers/clover/llvm/invocation.cpp | 20 +++++++- 4 files changed, 95 insertions(+), 27 deletions(-)
diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp index 2b6fbe5..99723ff 100644 --- a/src/gallium/state_trackers/clover/core/kernel.cpp +++ b/src/gallium/state_trackers/clover/core/kernel.cpp @@ -152,10 +152,12 @@ _cl_kernel::exec_context::bind(clover::command_queue *__q) { 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); + break; } + + assert(arg.arg_index >= 0); + + kern.args[arg.arg_index]->bind(*this, arg); } // Create a new compute state if anything changed. @@ -202,9 +204,7 @@ _cl_kernel::argument::storage() const { return 0; } -_cl_kernel::scalar_argument::scalar_argument(size_t size) : - argument(size) { -} +_cl_kernel::scalar_argument::scalar_argument(size_t size) : argument(size) { } void _cl_kernel::scalar_argument::set(size_t size, const void *value) { @@ -216,8 +216,32 @@ _cl_kernel::scalar_argument::set(size_t size, const void *value) { } void -_cl_kernel::scalar_argument::bind(exec_context &ctx) { - ctx.input.insert(ctx.input.end(), v.begin(), v.end()); +_cl_kernel::scalar_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { + // Extend the value + bool little_endian = ctx.q->dev.endianness() == PIPE_ENDIAN_LITTLE; + bool has_sign; + if (little_endian) { + has_sign = v[__size - 1] & 0x80; + } else { + has_sign = v[0] & 0x80; + } + uint8_t ext_value; + if (arg.ext_type == module::argument::sext && has_sign) { + ext_value = 0xff; + } else { + ext_value = 0; + } + + if (little_endian) { + ctx.input.insert(ctx.input.end(), v.begin(), v.end()); + } + for (unsigned i = __size; i < arg.target_size; ++i) { + ctx.input.push_back(ext_value); + } + if (!little_endian) { + ctx.input.insert(ctx.input.end(), v.begin(), v.end()); + } } void @@ -241,7 +265,8 @@ _cl_kernel::global_argument::set(size_t size, const void *value) { } void -_cl_kernel::global_argument::bind(exec_context &ctx) { +_cl_kernel::global_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { size_t offset = ctx.input.size(); size_t idx = ctx.g_buffers.size(); @@ -277,7 +302,8 @@ _cl_kernel::local_argument::set(size_t size, const void *value) { } void -_cl_kernel::local_argument::bind(exec_context &ctx) { +_cl_kernel::local_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { size_t offset = ctx.input.size(); size_t ptr = ctx.mem_local; @@ -308,7 +334,8 @@ _cl_kernel::constant_argument::set(size_t size, const void *value) { } void -_cl_kernel::constant_argument::bind(exec_context &ctx) { +_cl_kernel::constant_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { size_t offset = ctx.input.size(); size_t idx = ctx.resources.size(); @@ -341,7 +368,8 @@ _cl_kernel::image_rd_argument::set(size_t size, const void *value) { } void -_cl_kernel::image_rd_argument::bind(exec_context &ctx) { +_cl_kernel::image_rd_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { size_t offset = ctx.input.size(); size_t idx = ctx.sviews.size(); @@ -374,7 +402,8 @@ _cl_kernel::image_wr_argument::set(size_t size, const void *value) { } void -_cl_kernel::image_wr_argument::bind(exec_context &ctx) { +_cl_kernel::image_wr_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { size_t offset = ctx.input.size(); size_t idx = ctx.resources.size(); @@ -404,7 +433,8 @@ _cl_kernel::sampler_argument::set(size_t size, const void *value) { } void -_cl_kernel::sampler_argument::bind(exec_context &ctx) { +_cl_kernel::sampler_argument::bind(exec_context &ctx, + const clover::module::argument &arg) { size_t idx = ctx.samplers.size(); ctx.samplers.resize(idx + 1); diff --git a/src/gallium/state_trackers/clover/core/kernel.hpp b/src/gallium/state_trackers/clover/core/kernel.hpp index 2c540be..2ccd027 100644 --- a/src/gallium/state_trackers/clover/core/kernel.hpp +++ b/src/gallium/state_trackers/clover/core/kernel.hpp @@ -84,7 +84,8 @@ public: /// Allocate the necessary resources to bind the specified /// object to this argument, and update \a ctx accordingly. - virtual void bind(exec_context &ctx) = 0; + virtual void bind(exec_context &ctx, + const clover::module::argument &arg) = 0; /// Free any resources that were allocated in bind(). virtual void unbind(exec_context &ctx) = 0; @@ -125,7 +126,7 @@ private: scalar_argument(size_t size); virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: @@ -137,7 +138,7 @@ private: global_argument(size_t size); virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: @@ -151,7 +152,7 @@ private: virtual size_t storage() const; virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: @@ -163,7 +164,7 @@ private: constant_argument(size_t size); virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: @@ -176,7 +177,7 @@ private: image_rd_argument(size_t size); virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: @@ -189,7 +190,7 @@ private: image_wr_argument(size_t size); virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: @@ -202,7 +203,7 @@ private: sampler_argument(size_t size); virtual void set(size_t size, const void *value); - virtual void bind(exec_context &ctx); + virtual void bind(exec_context &ctx, const clover::module::argument &arg); virtual void unbind(exec_context &ctx); private: diff --git a/src/gallium/state_trackers/clover/core/module.hpp b/src/gallium/state_trackers/clover/core/module.hpp index d4b3413..c880315 100644 --- a/src/gallium/state_trackers/clover/core/module.hpp +++ b/src/gallium/state_trackers/clover/core/module.hpp @@ -69,17 +69,36 @@ namespace clover { pad }; + enum ext_type { + zext, + sext, + noext, + }; + + argument(enum type type, size_t size, size_t arg_index, + size_t target_size, enum ext_type ext_type) : type(type), + size(size), arg_index(arg_index), + target_size(target_size), ext_type(ext_type) { } 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) { } + size(size), arg_index(arg_index), target_size(size), + ext_type(noext) { } + argument(enum type type, size_t size) : type(type), + size(size), arg_index(-1), target_size(size), + ext_type(noext) { } + argument() : type(scalar), size(0), arg_index(-1), target_size(0), + ext_type(noext) { } 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; + + /// The size of this argument in the target architecture. This will + /// typically be the smallest natively supported integer size of a + /// target. + size_t target_size; + ext_type ext_type; }; struct symbol { diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 68f7eac..16198e0 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -344,8 +344,26 @@ namespace { break; } } else { + unsigned attr_index = arg.getArgNo() + 1; + // Determine the argument's alignment. When the SExt or ZExt + // attribute is set on a function, it means that the caller must + // extend the value to the appropriate size. We will extend the + // value when binding it to a kernel. + // See _cl_kernel::scalar_argument::bind() + enum module::argument::ext_type ext_type = + module::argument::noext; + + if (kernel_func->getAttributes().hasAttribute(attr_index, + llvm::Attribute::SExt)) { + ext_type = module::argument::sext; + } else if (kernel_func->getAttributes().hasAttribute(attr_index, + llvm::Attribute::ZExt)) { + ext_type = module::argument::zext; + } + args.push_back(module::argument(module::argument::scalar, - arg_size, arg.getArgNo())); + arg_size, arg.getArgNo(), + target_size >> 3, ext_type)); } if (aligned_size > target_size) { args.push_back(module::argument(module::argument::pad, -- 1.7.11.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev