summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2013-07-21 01:12:10 +0200
committerFrancisco Jerez <currojerez@riseup.net>2013-07-21 19:13:40 +0200
commitf760ea7f551e8a2e5f5057be2a8972fb67bf5491 (patch)
tree255c7935503f32d3d08fb23c718590dbb5aad4a1
parentda46fa90196228afce7b8ff14e7fcf3c33177ac0 (diff)
clover: Extend kernel arguments for differing host and device data types.
Loosely based on a similar patch by Tom Stellard.
-rw-r--r--src/gallium/state_trackers/clover/core/kernel.cpp31
-rw-r--r--src/gallium/state_trackers/clover/llvm/invocation.cpp25
2 files changed, 52 insertions, 4 deletions
diff --git a/src/gallium/state_trackers/clover/core/kernel.cpp b/src/gallium/state_trackers/clover/core/kernel.cpp
index fc4690c0133..e11efd5b1fc 100644
--- a/src/gallium/state_trackers/clover/core/kernel.cpp
+++ b/src/gallium/state_trackers/clover/core/kernel.cpp
@@ -199,6 +199,30 @@ namespace {
std::reverse(v.begin(), v.end());
}
+ bool
+ msb(const std::vector<uint8_t> &s) {
+ if (native_endianness == PIPE_ENDIAN_LITTLE)
+ return s.back() & 0x80;
+ else
+ return s.front() & 0x80;
+ }
+
+ 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 (native_endianness == 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);
+ }
+
template<typename T>
void
insert(T &d, const T &s) {
@@ -244,6 +268,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);
}
@@ -267,7 +292,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);
}
@@ -294,6 +319,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);
@@ -321,6 +347,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);
@@ -350,6 +377,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);
@@ -379,6 +407,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));
}
}