diff options
author | Francisco Jerez <[email protected]> | 2013-07-22 23:08:46 +0200 |
---|---|---|
committer | Francisco Jerez <[email protected]> | 2013-07-22 23:09:34 +0200 |
commit | f64c0ca692d3e8c78dd9ae1f015f58f1dfc1c760 (patch) | |
tree | 35512d47ec0074b4106cdf4af851229ec12e58e0 /src/gallium/state_trackers | |
parent | 829caf410e2c2c6f79902199da5a7900abc16129 (diff) |
clover: Extend kernel arguments for differing host and device data types.
Loosely based on a similar patch by Tom Stellard.
Cc: [email protected]
Reviewed-by: Tom Stellard <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r-- | src/gallium/state_trackers/clover/core/kernel.cpp | 35 | ||||
-rw-r--r-- | src/gallium/state_trackers/clover/llvm/invocation.cpp | 25 |
2 files changed, 56 insertions, 4 deletions
diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp index 82e937eeea5..7023f291fe2 100644 --- a/src/gallium/state_trackers/clover/core/kernel.cpp +++ b/src/gallium/state_trackers/clover/core/kernel.cpp @@ -197,6 +197,34 @@ namespace { std::reverse(v.begin(), v.end()); } + bool + msb(const std::vector<uint8_t> &s) { + if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE) + return s.back() & 0x80; + else + return s.front() & 0x80; + } + + /// + /// Resize buffer \a v to size \a n using sign or zero extension + /// according to \a ext. + /// + template<typename T> + void + extend(T &v, enum clover::module::argument::ext_type ext, size_t n) { + const size_t m = std::min(v.size(), n); + const bool sign_ext = (ext == module::argument::sign_ext); + const uint8_t fill = (sign_ext && msb(v) ? ~0 : 0); + T w(n, fill); + + if (PIPE_ENDIAN_NATIVE == PIPE_ENDIAN_LITTLE) + std::copy_n(v.begin(), m, w.begin()); + else + std::copy_n(v.end() - m, m, w.end() - m); + + std::swap(v, w); + } + /// /// Append buffer \a w to \a v. /// @@ -248,6 +276,7 @@ _cl_kernel::scalar_argument::bind(exec_context &ctx, const clover::module::argument &marg) { auto w = v; + extend(w, marg.ext_type, marg.target_size); byteswap(w, ctx.q->dev.endianness()); insert(ctx.input, w); } @@ -271,7 +300,7 @@ _cl_kernel::global_argument::set(size_t size, const void *value) { void _cl_kernel::global_argument::bind(exec_context &ctx, const clover::module::argument &marg) { - ctx.g_handles.push_back(allocate(ctx.input, marg.size)); + ctx.g_handles.push_back(allocate(ctx.input, marg.target_size)); ctx.g_buffers.push_back(obj->resource(ctx.q).pipe); } @@ -298,6 +327,7 @@ _cl_kernel::local_argument::bind(exec_context &ctx, const clover::module::argument &marg) { auto v = bytes(ctx.mem_local); + extend(v, module::argument::zero_ext, marg.target_size); byteswap(v, ctx.q->dev.endianness()); insert(ctx.input, v); @@ -325,6 +355,7 @@ _cl_kernel::constant_argument::bind(exec_context &ctx, const clover::module::argument &marg) { auto v = bytes(ctx.resources.size() << 24); + extend(v, module::argument::zero_ext, marg.target_size); byteswap(v, ctx.q->dev.endianness()); insert(ctx.input, v); @@ -354,6 +385,7 @@ _cl_kernel::image_rd_argument::bind(exec_context &ctx, const clover::module::argument &marg) { auto v = bytes(ctx.sviews.size()); + extend(v, module::argument::zero_ext, marg.target_size); byteswap(v, ctx.q->dev.endianness()); insert(ctx.input, v); @@ -383,6 +415,7 @@ _cl_kernel::image_wr_argument::bind(exec_context &ctx, const clover::module::argument &marg) { auto v = bytes(ctx.resources.size()); + extend(v, module::argument::zero_ext, marg.target_size); byteswap(v, ctx.q->dev.endianness()); insert(ctx.input, v); diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index dae61f7fa7d..a50cf37dfcb 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -304,14 +304,20 @@ namespace { for (llvm::Function::arg_iterator I = kernel_func->arg_begin(), E = kernel_func->arg_end(); I != E; ++I) { llvm::Argument &arg = *I; - llvm::Type *arg_type = arg.getType(); #if HAVE_LLVM < 0x0302 llvm::TargetData TD(kernel_func->getParent()); #else llvm::DataLayout TD(kernel_func->getParent()->getDataLayout()); #endif + + llvm::Type *arg_type = arg.getType(); unsigned arg_size = TD.getTypeStoreSize(arg_type); + llvm::Type *target_type = arg_type->isIntegerTy() ? + TD.getSmallestLegalIntType(mod->getContext(), arg_size * 8) : + arg_type; + unsigned target_size = TD.getTypeStoreSize(target_type); + if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) { arg_type = llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType(); @@ -324,11 +330,24 @@ 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, + target_size, 0, + module::argument::zero_ext)); break; } + } else { - args.push_back(module::argument(module::argument::scalar, arg_size)); + llvm::AttributeSet attrs = kernel_func->getAttributes(); + enum module::argument::ext_type ext_type = + (attrs.hasAttribute(arg.getArgNo() + 1, + llvm::Attribute::SExt) ? + module::argument::sign_ext : + module::argument::zero_ext); + + args.push_back( + module::argument(module::argument::scalar, arg_size, + target_size, 0, ext_type)); } } |