Files
pip/libs/opencl/piopencl.cpp
peri4 caa7880cc4 get rid of piForeach
apply some code analyzer recommendations
ICU flag now check if libicu exists
prepare for more accurate growth of containers (limited PoT, then constantly increase size)
2024-11-20 20:01:47 +03:00

738 lines
21 KiB
C++

#include "piopencl.h"
#include "piresources.h"
#include "pitranslator.h"
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#define CL_TARGET_OPENCL_VERSION 120
#ifdef MAC_OS
# include "cl.h"
#else
# include "CL/cl.h"
#endif
PRIVATE_DEFINITION_START(PIOpenCL::Context)
cl_context context;
cl_command_queue queue;
PIVector<cl_device_id> devices;
PIString complex_src;
PRIVATE_DEFINITION_END(PIOpenCL::Context)
PRIVATE_DEFINITION_START(PIOpenCL::Buffer)
cl_mem buffer;
PRIVATE_DEFINITION_END(PIOpenCL::Buffer)
PRIVATE_DEFINITION_START(PIOpenCL::Program)
cl_program program;
PRIVATE_DEFINITION_END(PIOpenCL::Program)
PRIVATE_DEFINITION_START(PIOpenCL::Kernel)
cl_kernel kernel;
PRIVATE_DEFINITION_END(PIOpenCL::Kernel)
void PIOpenCL::init() {
Initializer::instance();
}
const PIVector<PIOpenCL::Platform> & PIOpenCL::platforms() {
return Initializer::instance()->platforms_;
}
const PIVector<PIOpenCL::Device> PIOpenCL::devices() {
PIVector<PIOpenCL::Device> ret;
PIVector<PIOpenCL::Platform> pl = platforms();
for (const auto & p: pl)
ret << p.devices;
return ret;
}
PIOpenCL::Device PIOpenCL::deviceByID(void * id) {
PIVector<PIOpenCL::Platform> pl = platforms();
for (const auto & p: pl) {
for (const auto & d: p.devices) {
if (d.id == id) return d;
}
}
return Device();
}
PIOpenCL::Initializer::Initializer() {
inited_ = false;
}
PIOpenCL::Initializer * PIOpenCL::Initializer::instance() {
static PIOpenCL::Initializer * ret = new PIOpenCL::Initializer();
ret->init();
return ret;
}
void PIOpenCL::Initializer::init() {
if (inited_) return;
inited_ = true;
piCout << "init OpenCL";
platforms_.clear();
const int max_size = 256;
cl_platform_id cl_platforms[max_size];
char buffer[10240];
cl_int ret = 0;
cl_uint plat_num = 0;
ret = clGetPlatformIDs(max_size, cl_platforms, &plat_num);
if (ret != 0) {
piCout << "[PIOpenCL]"
<< "Error: OpenCL platforms not found!"_tr("PIOpenCL");
return;
}
for (uint i = 0; i < plat_num; i++) {
Platform p;
p.id = cl_platforms[i];
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_NAME, sizeof(buffer), buffer, 0);
p.name = buffer;
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_VENDOR, sizeof(buffer), buffer, 0);
p.vendor = buffer;
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_PROFILE, sizeof(buffer), buffer, 0);
p.profile = buffer;
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_VERSION, sizeof(buffer), buffer, 0);
p.version = buffer;
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_EXTENSIONS, sizeof(buffer), buffer, 0);
p.extensions = PIString(buffer).trim().split(" ");
uint dev_num = 0;
cl_device_id cl_devices[max_size];
ret = clGetDeviceIDs(cl_platforms[i], CL_DEVICE_TYPE_ALL, max_size, cl_devices, &dev_num);
if (ret == 0) {
// piCout << "[OpenCLBlock] OpenCL cl_devices on platform" + PIString::fromNumber(i) + "found:" << dev_num;
for (uint j = 0; j < dev_num; j++) {
uint buf_uint = 0;
ullong buf_ulong = 0;
Device d;
d.id = cl_devices[j];
d.platform_id = p.id;
clGetDeviceInfo(cl_devices[j], CL_DEVICE_NAME, sizeof(buffer), buffer, 0);
d.name = buffer;
clGetDeviceInfo(cl_devices[j], CL_DEVICE_VENDOR, sizeof(buffer), buffer, 0);
d.vendor = buffer;
clGetDeviceInfo(cl_devices[j], CL_DEVICE_VERSION, sizeof(buffer), buffer, 0);
d.device_version = buffer;
clGetDeviceInfo(cl_devices[j], CL_DRIVER_VERSION, sizeof(buffer), buffer, 0);
d.driver_version = buffer;
clGetDeviceInfo(cl_devices[j], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buf_uint), &buf_uint, 0);
d.max_compute_units = buf_uint;
clGetDeviceInfo(cl_devices[j], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buf_uint), &buf_uint, 0);
d.max_clock_frequency = buf_uint;
clGetDeviceInfo(cl_devices[j], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buf_ulong), &buf_ulong, 0);
d.max_memory_size = buf_ulong;
p.devices << d;
}
}
platforms_ << p;
}
}
PIOpenCL::Context::Context() {
PRIVATE->complex_src = PIString::fromUTF8(PIResources::get("3rd/clcomplex.h")) + "\n";
zero();
}
PIOpenCL::Context::~Context() {
piCout << "destroy context" << this;
deletePrograms();
deleteBuffers();
if (PRIVATE->queue) clReleaseCommandQueue(PRIVATE->queue);
if (PRIVATE->context) clReleaseContext(PRIVATE->context);
zero();
}
void * PIOpenCL::Context::handle() {
return PRIVATE->context;
}
void * PIOpenCL::Context::queue() {
return PRIVATE->queue;
}
void PIOpenCL::Context::zero() {
programs_.clear();
buffers_.clear();
PRIVATE->context = 0;
PRIVATE->queue = 0;
PRIVATE->devices.clear();
}
void PIOpenCL::Context::deletePrograms() {
piCout << "context: delete" << programs_.size() << "programs";
PIVector<Program *> ptdl = programs_;
programs_.clear();
for (auto * p: ptdl) {
if (p) delete p;
}
}
void PIOpenCL::Context::deleteBuffers() {
piCout << "context: delete" << buffers_.size() << "buffers";
PIVector<Buffer *> btdl = buffers_;
buffers_.clear();
for (auto * b: btdl) {
if (b) delete b;
}
}
PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) {
if (dl.isEmpty()) return 0;
Context * rc = 0;
PIVector<cl_device_id> cldl;
for (int i = 0; i < dl.size_s(); ++i)
if (dl[i].isValid()) cldl << (cl_device_id)dl[i].id;
// piCout << "create for" << dl[0].name << "...";
cl_int ret = 0;
cl_context con = clCreateContext(0, cldl.size_s(), cldl.data(), 0, 0, &ret);
if (ret != 0) {
piCout << "[PIOpenCL::Context]"
<< "clCreateContext error" << ret;
return 0;
}
cl_command_queue comq = clCreateCommandQueue(con, cldl[0], 0, &ret);
if (ret != 0) {
piCout << "[PIOpenCL::Context]"
<< "clCreateCommandQueue error" << ret;
return 0;
}
piCout << "create done for" << dl[0].name;
rc = new Context();
rc->PRIVATEWB->context = con;
rc->PRIVATEWB->queue = comq;
rc->PRIVATEWB->devices = cldl;
return rc;
}
PIOpenCL::Context * PIOpenCL::Context::create(const PIString & part_name) {
PIString pn = part_name.toLowerCase();
PIVector<Device> dl = PIOpenCL::devices();
for (const auto & d: dl) {
if (d.displayText().toLowerCase().contains(pn)) return create(d);
}
return 0;
}
PIOpenCL::Program * PIOpenCL::Context::createProgram(const PIString & source, const PIStringList & args, PIString * error) {
if (error) error->clear();
if (source.isEmpty()) {
if (error) (*error) = "Empty program!";
return 0;
}
PIString src_text = PRIVATE->complex_src + source;
const char * csrc = src_text.dataAscii();
size_t src_size = src_text.size();
cl_int ret = 0;
cl_program prog = clCreateProgramWithSource(PRIVATE->context, 1, &csrc, &src_size, &ret);
if (ret != 0) {
piCout << "[PIOpenCL::Context]"
<< "clCreateProgramWithSource error" << ret;
if (error) (*error) += "clCreateProgramWithSource error " + PIString::fromNumber(ret);
return 0;
}
PIString carg = (PIStringList(args) << "-cl-kernel-arg-info").join(' ');
ret = clBuildProgram(prog, 0, 0, carg.dataAscii(), 0, 0);
char buffer[10240];
clGetProgramBuildInfo(prog, PRIVATE->devices[0], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, 0);
if (ret != 0) {
clReleaseProgram(prog);
piCout << "[PIOpenCL::Context]"
<< "clBuildProgram error" << ret; // << ":" << buffer;
if (error) (*error) = buffer;
return 0;
}
size_t uret = 0;
ret = clGetProgramInfo(prog, CL_PROGRAM_NUM_KERNELS, sizeof(uret), &uret, 0);
if (ret != 0) {
clReleaseProgram(prog);
piCout << "[PIOpenCL::Context]"
<< "clGetProgramInfo error" << ret;
if (error) (*error) = "Can`t retrieve CL_PROGRAM_NUM_KERNELS";
return 0;
}
const int ccnt = 10240;
char knames[ccnt];
ret = clGetProgramInfo(prog, CL_PROGRAM_KERNEL_NAMES, ccnt, knames, 0);
if (ret != 0) {
clReleaseProgram(prog);
piCout << "[PIOpenCL::Context]"
<< "clGetProgramInfo error" << ret;
if (error) (*error) = "Can`t retrieve CL_PROGRAM_KERNEL_NAMES";
return 0;
}
PIStringList knl = PIString(knames).trim().split(";");
PIVector<void *> kerns;
for (const auto & k: knl) {
cl_kernel kern = clCreateKernel(prog, k.dataAscii(), &ret);
if (ret != 0) {
piCout << "[PIOpenCL::Context]"
<< "clCreateKernel" << k << "error" << ret;
if (error) (*error) += "clCreateKernel(\"" + k + "\") error " + ret;
for (auto * _k: kerns)
clReleaseKernel((cl_kernel)_k);
clReleaseProgram(prog);
return 0;
}
kerns << kern;
}
// piCout << knl << kerns;
Program * rp = new Program();
rp->context_ = this;
rp->source_ = source;
rp->PRIVATEWB->program = prog;
if (!rp->initKernels(kerns)) {
delete rp;
return 0;
}
programs_ << rp;
return rp;
}
PIOpenCL::Buffer * PIOpenCL::Context::createBuffer(PIOpenCL::Direction dir, void * container, int type, PIByteArray def, uint elements) {
Buffer * ret = new Buffer();
ret->context_ = this;
ret->dir = dir;
ret->type = (Buffer::Container)type;
ret->container = container;
ret->def = def;
ret->elements = elements;
if (!ret->init()) {
delete ret;
return 0;
}
buffers_ << ret;
return ret;
}
PIOpenCL::Buffer::Buffer() {
zero();
}
PIOpenCL::Buffer::~Buffer() {
if (context_) context_->buffers_.removeAll(this);
if (PRIVATE->buffer) clReleaseMemObject(PRIVATE->buffer);
zero();
}
void * PIOpenCL::Buffer::handle() {
return PRIVATE->buffer;
}
void PIOpenCL::Buffer::zero() {
type = cNone;
container = 0;
elements = 0;
PRIVATE->buffer = 0;
}
bool PIOpenCL::Buffer::init() {
cl_int ret = 0;
cl_mem_flags f = container ? CL_MEM_COPY_HOST_PTR : 0;
switch (dir) {
case Input: f |= CL_MEM_READ_ONLY; break;
case Output: f |= CL_MEM_WRITE_ONLY; break;
case InputOutput: f |= CL_MEM_READ_WRITE; break;
default: break;
}
PRIVATE->buffer = clCreateBuffer(context_->PRIVATEWB->context, f, elements * def.size(), container ? containerData() : 0, &ret);
if (ret != 0) {
piCout << "[PIOpenCL::Buffer]"
<< "clCreateBuffer error" << ret;
return false;
}
return true;
}
void * PIOpenCL::Buffer::containerData() {
if (type == cNone || !container) return 0;
switch (type) {
case cVector: return ((PIVector<uchar> *)container)->data();
case cDeque: return ((PIDeque<uchar> *)container)->data();
case cVector2D: return ((PIVector2D<uchar> *)container)->data();
default: break;
}
return 0;
}
void PIOpenCL::Buffer::clear() {
if (!PRIVATE->buffer) return;
if (def.isEmpty() || elements == 0) return;
cl_int ret =
clEnqueueFillBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, def.data(), def.size_s(), 0, elements * def.size(), 0, 0, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Buffer]"
<< "clEnqueueFillBuffer error" << ret;
}
}
void PIOpenCL::Buffer::copyToContainer() {
if (!PRIVATE->buffer || !container) return;
copyTo(containerData());
}
void PIOpenCL::Buffer::copyTo(void * data) {
if (!PRIVATE->buffer) return;
cl_int ret = clEnqueueReadBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, 0, elements * def.size(), data, 0, 0, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Buffer]"
<< "clEnqueueReadBuffer error" << ret;
}
}
void PIOpenCL::Buffer::copyTo(void * data, int elements_count, int elements_offset) {
if (!PRIVATE->buffer) return;
cl_int ret = clEnqueueReadBuffer(context_->PRIVATEWB->queue,
PRIVATE->buffer,
CL_TRUE,
elements_offset * def.size(),
elements_count * def.size(),
data,
0,
0,
0);
if (ret != 0) {
piCout << "[PIOpenCL::Buffer]"
<< "clEnqueueReadBuffer error" << ret;
}
}
void PIOpenCL::Buffer::copyFromContainer() {
if (!PRIVATE->buffer || !container) return;
copyFrom(containerData());
}
void PIOpenCL::Buffer::copyFrom(void * data) {
if (!PRIVATE->buffer) return;
cl_int ret = clEnqueueWriteBuffer(context_->PRIVATEWB->queue, PRIVATE->buffer, CL_TRUE, 0, elements * def.size(), data, 0, 0, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Buffer]"
<< "clEnqueueWriteBuffer error" << ret;
}
}
void PIOpenCL::Buffer::copyFrom(void * data, int elements_count, int elements_offset) {
if (!PRIVATE->buffer) return;
cl_int ret = clEnqueueWriteBuffer(context_->PRIVATEWB->queue,
PRIVATE->buffer,
CL_TRUE,
elements_offset * def.size(),
elements_count * def.size(),
data,
0,
0,
0);
if (ret != 0) {
piCout << "[PIOpenCL::Buffer]"
<< "clEnqueueWriteBuffer error" << ret;
}
}
PIOpenCL::Program::Program() {
// piCout << "new program" << this;
zero();
}
PIOpenCL::Program::~Program() {
// piCout << "destroy program" << this;
if (context_) context_->programs_.removeAll(this);
for (auto * k: kernels_)
delete k;
if (PRIVATE->program) clReleaseProgram(PRIVATE->program);
zero();
}
void PIOpenCL::Program::zero() {
context_ = 0;
kernels_.clear();
PRIVATE->program = 0;
}
bool PIOpenCL::Program::initKernels(PIVector<void *> kerns) {
for (auto * _k: kerns) {
cl_kernel k = (cl_kernel)_k;
// piCout << "init kernel" << k;
Kernel * kern = new Kernel();
kern->context_ = context_;
kern->program_ = this;
kern->PRIVATEWB->kernel = k;
if (kern->init())
kernels_ << kern;
else
delete kern;
}
return !kernels_.isEmpty();
}
bool PIOpenCL::Kernel::execute() {
if (dims.isEmpty()) {
piCout << "[PIOpenCL::Kernel]"
<< "Error: empty range"_tr("PIOpenCL");
return false;
}
cl_int ret = clEnqueueNDRangeKernel(context_->PRIVATEWB->queue, PRIVATE->kernel, dims.size(), 0, dims.data(), 0, 0, 0, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clEnqueueNDRangeKernel error" << ret;
return false;
}
return true;
}
void PIOpenCL::Kernel::waitForFinish() {
clFinish(context_->PRIVATEWB->queue);
}
void PIOpenCL::Kernel::setExecuteRanges(const PIVector<int> & ranges) {
dims = ranges.toType<size_t>();
}
PIOpenCL::Kernel::Kernel() {
zero();
// piCout << "new Kernel" << this;
}
PIOpenCL::Kernel::~Kernel() {
// piCout << "del Kernel" << this;
if (PRIVATE->kernel) clReleaseKernel(PRIVATE->kernel);
}
void PIOpenCL::Kernel::zero() {
PRIVATE->kernel = 0;
}
bool PIOpenCL::Kernel::init() {
char kname[1024];
memset(kname, 0, 1024);
cl_int ret = 0;
ret = clGetKernelInfo(PRIVATE->kernel, CL_KERNEL_FUNCTION_NAME, 1024, kname, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelInfo(CL_KERNEL_FUNCTION_NAME) error" << ret;
return false;
}
name_ = kname;
cl_uint na = 0;
ret = clGetKernelInfo(PRIVATE->kernel, CL_KERNEL_NUM_ARGS, sizeof(na), &na, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelInfo(CL_KERNEL_NUM_ARGS) error" << ret;
return false;
}
for (cl_uint i = 0; i < na; ++i) {
KernelArg ka;
ka.init(PRIVATE->kernel, i);
args_ << ka;
}
// piCout << "kname" << kname << na;
return true;
}
template<typename T>
void setArgV(cl_kernel k, int index, T v) {
// piCout << "setArgV" << k << index <<sizeof(v)<< v;
clSetKernelArg(k, index, sizeof(v), &v);
}
bool PIOpenCL::Kernel::setArgValueS(int index, const PIVariant & value) {
if (index < 0 || index >= args_.size_s()) {
piCout << "[PIOpenCL::Kernel]"
<< "setArgValue invalid index %1"_tr("PIOpenCL").arg(index);
return false;
}
KernelArg & ka(args_[index]);
if (ka.dims > 0) {
piCout << "[PIOpenCL::Kernel]"
<< "setArgValue set scalar to \"%1 %2\""_tr("PIOpenCL").arg(ka.type_name).arg(ka.arg_name);
return false;
}
switch (ka.arg_type) {
case Char: setArgV(PRIVATE->kernel, index, (cl_char)(value.toInt())); break;
case UChar: setArgV(PRIVATE->kernel, index, (cl_uchar)(value.toInt())); break;
case Short: setArgV(PRIVATE->kernel, index, (cl_short)(value.toInt())); break;
case UShort: setArgV(PRIVATE->kernel, index, (cl_ushort)(value.toInt())); break;
case Int: setArgV(PRIVATE->kernel, index, (cl_int)(value.toInt())); break;
case UInt: setArgV(PRIVATE->kernel, index, (cl_uint)(value.toInt())); break;
case Long: setArgV(PRIVATE->kernel, index, (cl_long)(value.toLLong())); break;
case ULong: setArgV(PRIVATE->kernel, index, (cl_ulong)(value.toLLong())); break;
case Float: setArgV(PRIVATE->kernel, index, (cl_float)(value.toFloat())); break;
case Double: setArgV(PRIVATE->kernel, index, (cl_double)(value.toDouble())); break;
default: break;
}
return true;
}
bool PIOpenCL::Kernel::bindArgValue(int index, Buffer * buffer) {
if (!buffer) return false;
if (index < 0 || index >= args_.size_s()) {
piCout << "[PIOpenCL::Kernel]"
<< "bindArgValue invalid index %1"_tr("PIOpenCL").arg(index);
return false;
}
KernelArg & ka(args_[index]);
if (ka.dims <= 0) {
piCout << "[PIOpenCL::Kernel]"
<< "bindArgValue set buffer to \"%1 %2\""_tr("PIOpenCL").arg(ka.type_name).arg(ka.arg_name);
return false;
}
clSetKernelArg(PRIVATE->kernel, index, sizeof(buffer->PRIVATEWB->buffer), &(buffer->PRIVATEWB->buffer));
return true;
}
int PIOpenCL::Kernel::argIndex(const PIString & an) const {
for (int i = 0; i < args_.size_s(); ++i)
if (args_[i].arg_name == an) return i;
return -1;
}
PIOpenCL::KernelArg PIOpenCL::Kernel::argByName(const PIString & an) const {
for (const auto & a: args_)
if (a.arg_name == an) return a;
return KernelArg();
}
PIOpenCL::KernelArg::KernelArg() {
address_qualifier = AddressGlobal;
access_qualifier = AccessNone;
type_qualifier = TypeNone;
is_pointer = false;
arg_type = Float;
dims = 1;
}
void PIOpenCL::KernelArg::init(void * _k, uint index) {
cl_kernel k = (cl_kernel)_k;
cl_int ret = 0;
char nm[1024];
memset(nm, 0, 1024);
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_TYPE_NAME, 1024, nm, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelArgInfo(CL_KERNEL_ARG_TYPE_NAME) error" << ret;
}
type_name = nm;
memset(nm, 0, 1024);
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_NAME, 1024, nm, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelArgInfo(CL_KERNEL_ARG_NAME) error" << ret;
}
arg_name = nm;
cl_kernel_arg_address_qualifier addq = 0;
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_ADDRESS_QUALIFIER, sizeof(addq), &addq, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelArgInfo(CL_KERNEL_ARG_ADDRESS_QUALIFIER) error" << ret;
}
switch (addq) {
case CL_KERNEL_ARG_ADDRESS_GLOBAL: address_qualifier = AddressGlobal; break;
case CL_KERNEL_ARG_ADDRESS_LOCAL: address_qualifier = AddressLocal; break;
case CL_KERNEL_ARG_ADDRESS_CONSTANT: address_qualifier = AddressConstant; break;
case CL_KERNEL_ARG_ADDRESS_PRIVATE: address_qualifier = AddressPrivate; break;
}
cl_kernel_arg_access_qualifier accq = 0;
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_ACCESS_QUALIFIER, sizeof(accq), &accq, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelArgInfo(CL_KERNEL_ARG_ACCESS_QUALIFIER) error" << ret;
}
switch (accq) {
case CL_KERNEL_ARG_ACCESS_READ_ONLY: access_qualifier = AccessReadOnly; break;
case CL_KERNEL_ARG_ACCESS_WRITE_ONLY: access_qualifier = AccessWriteOnly; break;
case CL_KERNEL_ARG_ACCESS_READ_WRITE: access_qualifier = AccessReadWrite; break;
case CL_KERNEL_ARG_ACCESS_NONE: access_qualifier = AccessNone; break;
}
cl_kernel_arg_type_qualifier tq = 0;
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof(tq), &tq, 0);
if (ret != 0) {
piCout << "[PIOpenCL::Kernel]"
<< "clGetKernelArgInfo(CL_KERNEL_ARG_TYPE_QUALIFIER) error" << ret;
}
switch (tq) {
case CL_KERNEL_ARG_TYPE_CONST: type_qualifier = TypeConst; break;
case CL_KERNEL_ARG_TYPE_RESTRICT: type_qualifier = TypeRestrict; break;
case CL_KERNEL_ARG_TYPE_VOLATILE: type_qualifier = TypeVolatile; break;
case CL_KERNEL_ARG_TYPE_NONE: type_qualifier = TypeNone; break;
}
is_pointer = false;
base_type_name = type_name;
base_type_name.removeAll("__global");
dims = piMaxi(0, base_type_name.entries('*') + base_type_name.entries('['));
base_type_name.removeAll('*');
while (base_type_name.contains('[')) {
int i = base_type_name.find('[');
base_type_name.remove(i, base_type_name.find(']') - i + 1);
}
if (base_type_name == "char") arg_type = Char;
if (base_type_name == "uchar") arg_type = UChar;
if (base_type_name == "short") arg_type = Short;
if (base_type_name == "ushort") arg_type = UShort;
if (base_type_name == "int") arg_type = Int;
if (base_type_name == "uint") arg_type = UInt;
if (base_type_name == "long") arg_type = Long;
if (base_type_name == "ulong") arg_type = ULong;
if (base_type_name == "float") arg_type = Float;
if (base_type_name == "double") arg_type = Double;
// piCout << type_name << base_type_name;
}
PICout operator<<(PICout s, const PIOpenCL::KernelArg & v) {
s.setControls(0);
s << "Arg(" << v.base_type_name << " " << v.arg_name << " (addr=" << v.address_qualifier << ",acc=" << v.access_qualifier
<< ",typ=" << v.type_qualifier << ",dims=" << v.dims << "))";
s.restoreControls();
return s;
}