clover: Clean up property query functions by using a new property_buffer helper class.
Tested-by: Tom Stellard <thomas.stellard@amd.com>
This commit is contained in:
@@ -33,6 +33,7 @@ CPP_SOURCES := \
|
||||
core/event.cpp \
|
||||
core/program.hpp \
|
||||
core/program.cpp \
|
||||
core/property.hpp \
|
||||
core/kernel.hpp \
|
||||
core/kernel.cpp \
|
||||
core/module.hpp \
|
||||
|
@@ -103,25 +103,35 @@ clReleaseContext(cl_context ctx) {
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetContextInfo(cl_context ctx, cl_context_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!ctx)
|
||||
return CL_INVALID_CONTEXT;
|
||||
|
||||
switch (param) {
|
||||
case CL_CONTEXT_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, ctx->ref_count());
|
||||
buf.as_scalar<cl_uint>() = ctx->ref_count();
|
||||
break;
|
||||
|
||||
case CL_CONTEXT_NUM_DEVICES:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, ctx->devs.size());
|
||||
buf.as_scalar<cl_uint>() = ctx->devs.size();
|
||||
break;
|
||||
|
||||
case CL_CONTEXT_DEVICES:
|
||||
return vector_property<cl_device_id>(buf, size, size_ret, ctx->devs);
|
||||
buf.as_vector<cl_device_id>() = ctx->devs;
|
||||
break;
|
||||
|
||||
case CL_CONTEXT_PROPERTIES:
|
||||
return vector_property<cl_context_properties>(buf, size, size_ret,
|
||||
ctx->props());
|
||||
buf.as_vector<cl_context_properties>() = ctx->props();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
@@ -60,204 +60,245 @@ clGetDeviceIDs(cl_platform_id platform, cl_device_type device_type,
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetDeviceInfo(cl_device_id dev, cl_device_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!dev)
|
||||
return CL_INVALID_DEVICE;
|
||||
|
||||
switch (param) {
|
||||
case CL_DEVICE_TYPE:
|
||||
return scalar_property<cl_device_type>(buf, size, size_ret, dev->type());
|
||||
buf.as_scalar<cl_device_type>() = dev->type();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_VENDOR_ID:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, dev->vendor_id());
|
||||
buf.as_scalar<cl_uint>() = dev->vendor_id();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_COMPUTE_UNITS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 1);
|
||||
buf.as_scalar<cl_uint>() = 1;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
dev->max_block_size().size());
|
||||
buf.as_scalar<cl_uint>() = dev->max_block_size().size();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_WORK_ITEM_SIZES:
|
||||
return vector_property<size_t>(buf, size, size_ret,
|
||||
dev->max_block_size());
|
||||
buf.as_vector<size_t>() = dev->max_block_size();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_WORK_GROUP_SIZE:
|
||||
return scalar_property<size_t>(buf, size, size_ret,
|
||||
dev->max_threads_per_block());
|
||||
buf.as_scalar<size_t>() = dev->max_threads_per_block();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 16);
|
||||
buf.as_scalar<cl_uint>() = 16;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 8);
|
||||
buf.as_scalar<cl_uint>() = 8;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 4);
|
||||
buf.as_scalar<cl_uint>() = 4;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 2);
|
||||
buf.as_scalar<cl_uint>() = 2;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 4);
|
||||
buf.as_scalar<cl_uint>() = 4;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 2);
|
||||
buf.as_scalar<cl_uint>() = 2;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<cl_uint>() = 0;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_CLOCK_FREQUENCY:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<cl_uint>() = 0;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_ADDRESS_BITS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 32);
|
||||
buf.as_scalar<cl_uint>() = 32;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_READ_IMAGE_ARGS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
dev->max_images_read());
|
||||
buf.as_scalar<cl_uint>() = dev->max_images_read();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
dev->max_images_write());
|
||||
buf.as_scalar<cl_uint>() = dev->max_images_write();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret,
|
||||
dev->max_mem_alloc_size());
|
||||
buf.as_scalar<cl_ulong>() = dev->max_mem_alloc_size();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_IMAGE2D_MAX_WIDTH:
|
||||
case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
|
||||
return scalar_property<size_t>(buf, size, size_ret,
|
||||
1 << dev->max_image_levels_2d());
|
||||
buf.as_scalar<size_t>() = 1 << dev->max_image_levels_2d();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_IMAGE3D_MAX_WIDTH:
|
||||
case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
|
||||
case CL_DEVICE_IMAGE3D_MAX_DEPTH:
|
||||
return scalar_property<size_t>(buf, size, size_ret,
|
||||
1 << dev->max_image_levels_3d());
|
||||
buf.as_scalar<size_t>() = 1 << dev->max_image_levels_3d();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_IMAGE_SUPPORT:
|
||||
return scalar_property<cl_bool>(buf, size, size_ret, CL_TRUE);
|
||||
buf.as_scalar<cl_bool>() = CL_TRUE;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_PARAMETER_SIZE:
|
||||
return scalar_property<size_t>(buf, size, size_ret,
|
||||
dev->max_mem_input());
|
||||
buf.as_scalar<size_t>() = dev->max_mem_input();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_SAMPLERS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
dev->max_samplers());
|
||||
buf.as_scalar<cl_uint>() = dev->max_samplers();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MEM_BASE_ADDR_ALIGN:
|
||||
case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 128);
|
||||
buf.as_scalar<cl_uint>() = 128;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_SINGLE_FP_CONFIG:
|
||||
return scalar_property<cl_device_fp_config>(buf, size, size_ret,
|
||||
CL_FP_DENORM | CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST);
|
||||
buf.as_scalar<cl_device_fp_config>() =
|
||||
CL_FP_DENORM | CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
|
||||
return scalar_property<cl_device_mem_cache_type>(buf, size, size_ret,
|
||||
CL_NONE);
|
||||
buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<cl_uint>() = 0;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<cl_ulong>() = 0;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_GLOBAL_MEM_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret,
|
||||
dev->max_mem_global());
|
||||
buf.as_scalar<cl_ulong>() = dev->max_mem_global();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret,
|
||||
dev->max_const_buffer_size());
|
||||
buf.as_scalar<cl_ulong>() = dev->max_const_buffer_size();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_MAX_CONSTANT_ARGS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
dev->max_const_buffers());
|
||||
buf.as_scalar<cl_uint>() = dev->max_const_buffers();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_LOCAL_MEM_TYPE:
|
||||
return scalar_property<cl_device_local_mem_type>(buf, size, size_ret,
|
||||
CL_LOCAL);
|
||||
buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_LOCAL_MEM_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret,
|
||||
dev->max_mem_local());
|
||||
buf.as_scalar<cl_ulong>() = dev->max_mem_local();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
|
||||
return scalar_property<cl_bool>(buf, size, size_ret, CL_FALSE);
|
||||
buf.as_scalar<cl_bool>() = CL_FALSE;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
|
||||
return scalar_property<size_t>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<size_t>() = 0;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_ENDIAN_LITTLE:
|
||||
return scalar_property<cl_bool>(buf, size, size_ret,
|
||||
dev->endianness() == PIPE_ENDIAN_LITTLE);
|
||||
buf.as_scalar<cl_bool>() = (dev->endianness() == PIPE_ENDIAN_LITTLE);
|
||||
break;
|
||||
|
||||
case CL_DEVICE_AVAILABLE:
|
||||
case CL_DEVICE_COMPILER_AVAILABLE:
|
||||
return scalar_property<cl_bool>(buf, size, size_ret, CL_TRUE);
|
||||
buf.as_scalar<cl_bool>() = CL_TRUE;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_EXECUTION_CAPABILITIES:
|
||||
return scalar_property<cl_device_exec_capabilities>(buf, size, size_ret,
|
||||
CL_EXEC_KERNEL);
|
||||
buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_QUEUE_PROPERTIES:
|
||||
return scalar_property<cl_command_queue_properties>(buf, size, size_ret,
|
||||
CL_QUEUE_PROFILING_ENABLE);
|
||||
buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NAME:
|
||||
return string_property(buf, size, size_ret, dev->device_name());
|
||||
buf.as_string() = dev->device_name();
|
||||
break;
|
||||
|
||||
case CL_DEVICE_VENDOR:
|
||||
return string_property(buf, size, size_ret, dev->vendor_name());
|
||||
buf.as_string() = dev->vendor_name();
|
||||
break;
|
||||
|
||||
case CL_DRIVER_VERSION:
|
||||
return string_property(buf, size, size_ret, PACKAGE_VERSION);
|
||||
buf.as_string() = PACKAGE_VERSION;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PROFILE:
|
||||
return string_property(buf, size, size_ret, "FULL_PROFILE");
|
||||
buf.as_string() = "FULL_PROFILE";
|
||||
break;
|
||||
|
||||
case CL_DEVICE_VERSION:
|
||||
return string_property(buf, size, size_ret,
|
||||
"OpenCL 1.1 MESA " PACKAGE_VERSION);
|
||||
buf.as_string() = "OpenCL 1.1 MESA " PACKAGE_VERSION;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_EXTENSIONS:
|
||||
return string_property(buf, size, size_ret, "");
|
||||
buf.as_string() = "";
|
||||
break;
|
||||
|
||||
case CL_DEVICE_PLATFORM:
|
||||
return scalar_property<cl_platform_id>(buf, size, size_ret,
|
||||
&dev->platform);
|
||||
buf.as_scalar<cl_platform_id>() = &dev->platform;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_HOST_UNIFIED_MEMORY:
|
||||
return scalar_property<cl_bool>(buf, size, size_ret, CL_TRUE);
|
||||
buf.as_scalar<cl_bool>() = CL_TRUE;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 16);
|
||||
buf.as_scalar<cl_uint>() = 16;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 8);
|
||||
buf.as_scalar<cl_uint>() = 8;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 4);
|
||||
buf.as_scalar<cl_uint>() = 4;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 2);
|
||||
buf.as_scalar<cl_uint>() = 2;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 4);
|
||||
buf.as_scalar<cl_uint>() = 4;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 2);
|
||||
buf.as_scalar<cl_uint>() = 2;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<cl_uint>() = 0;
|
||||
break;
|
||||
|
||||
case CL_DEVICE_OPENCL_C_VERSION:
|
||||
return string_property(buf, size, size_ret, "OpenCL C 1.1");
|
||||
buf.as_string() = "OpenCL C 1.1";
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
@@ -89,29 +89,41 @@ clWaitForEvents(cl_uint num_evs, const cl_event *evs) try {
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetEventInfo(cl_event ev, cl_event_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!ev)
|
||||
return CL_INVALID_EVENT;
|
||||
|
||||
switch (param) {
|
||||
case CL_EVENT_COMMAND_QUEUE:
|
||||
return scalar_property<cl_command_queue>(buf, size, size_ret, ev->queue());
|
||||
buf.as_scalar<cl_command_queue>() = ev->queue();
|
||||
break;
|
||||
|
||||
case CL_EVENT_CONTEXT:
|
||||
return scalar_property<cl_context>(buf, size, size_ret, &ev->ctx);
|
||||
buf.as_scalar<cl_context>() = &ev->ctx;
|
||||
break;
|
||||
|
||||
case CL_EVENT_COMMAND_TYPE:
|
||||
return scalar_property<cl_command_type>(buf, size, size_ret, ev->command());
|
||||
buf.as_scalar<cl_command_type>() = ev->command();
|
||||
break;
|
||||
|
||||
case CL_EVENT_COMMAND_EXECUTION_STATUS:
|
||||
return scalar_property<cl_int>(buf, size, size_ret, ev->status());
|
||||
buf.as_scalar<cl_int>() = ev->status();
|
||||
break;
|
||||
|
||||
case CL_EVENT_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, ev->ref_count());
|
||||
buf.as_scalar<cl_uint>() = ev->ref_count();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
PUBLIC cl_int
|
||||
@@ -216,7 +228,8 @@ clEnqueueWaitForEvents(cl_command_queue q, cl_uint num_evs,
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetEventProfilingInfo(cl_event ev, cl_profiling_info param,
|
||||
size_t size, void *buf, size_t *size_ret) try {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
hard_event *hev = dynamic_cast<hard_event *>(ev);
|
||||
|
||||
if (!ev)
|
||||
@@ -227,21 +240,27 @@ clGetEventProfilingInfo(cl_event ev, cl_profiling_info param,
|
||||
|
||||
switch (param) {
|
||||
case CL_PROFILING_COMMAND_QUEUED:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret, hev->time_queued());
|
||||
buf.as_scalar<cl_ulong>() = hev->time_queued();
|
||||
break;
|
||||
|
||||
case CL_PROFILING_COMMAND_SUBMIT:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret, hev->time_submit());
|
||||
buf.as_scalar<cl_ulong>() = hev->time_submit();
|
||||
break;
|
||||
|
||||
case CL_PROFILING_COMMAND_START:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret, hev->time_start());
|
||||
buf.as_scalar<cl_ulong>() = hev->time_start();
|
||||
break;
|
||||
|
||||
case CL_PROFILING_COMMAND_END:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret, hev->time_end());
|
||||
buf.as_scalar<cl_ulong>() = hev->time_end();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (lazy<cl_ulong>::undefined_error &e) {
|
||||
return CL_PROFILING_INFO_NOT_AVAILABLE;
|
||||
|
||||
|
@@ -118,39 +118,49 @@ clSetKernelArg(cl_kernel kern, cl_uint idx, size_t size,
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetKernelInfo(cl_kernel kern, cl_kernel_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!kern)
|
||||
return CL_INVALID_KERNEL;
|
||||
|
||||
switch (param) {
|
||||
case CL_KERNEL_FUNCTION_NAME:
|
||||
return string_property(buf, size, size_ret, kern->name());
|
||||
buf.as_string() = kern->name();
|
||||
break;
|
||||
|
||||
case CL_KERNEL_NUM_ARGS:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
kern->args.size());
|
||||
buf.as_scalar<cl_uint>() = kern->args.size();
|
||||
break;
|
||||
|
||||
case CL_KERNEL_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
kern->ref_count());
|
||||
buf.as_scalar<cl_uint>() = kern->ref_count();
|
||||
break;
|
||||
|
||||
case CL_KERNEL_CONTEXT:
|
||||
return scalar_property<cl_context>(buf, size, size_ret,
|
||||
&kern->prog.ctx);
|
||||
buf.as_scalar<cl_context>() = &kern->prog.ctx;
|
||||
break;
|
||||
|
||||
case CL_KERNEL_PROGRAM:
|
||||
return scalar_property<cl_program>(buf, size, size_ret,
|
||||
&kern->prog);
|
||||
buf.as_scalar<cl_program>() = &kern->prog;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetKernelWorkGroupInfo(cl_kernel kern, cl_device_id dev,
|
||||
cl_kernel_work_group_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!kern)
|
||||
return CL_INVALID_KERNEL;
|
||||
|
||||
@@ -160,27 +170,33 @@ clGetKernelWorkGroupInfo(cl_kernel kern, cl_device_id dev,
|
||||
|
||||
switch (param) {
|
||||
case CL_KERNEL_WORK_GROUP_SIZE:
|
||||
return scalar_property<size_t>(buf, size, size_ret,
|
||||
kern->max_block_size());
|
||||
buf.as_scalar<size_t>() = kern->max_block_size();
|
||||
break;
|
||||
|
||||
case CL_KERNEL_COMPILE_WORK_GROUP_SIZE:
|
||||
return vector_property<size_t>(buf, size, size_ret,
|
||||
kern->block_size());
|
||||
buf.as_vector<size_t>() = kern->block_size();
|
||||
break;
|
||||
|
||||
case CL_KERNEL_LOCAL_MEM_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret,
|
||||
kern->mem_local());
|
||||
buf.as_scalar<cl_ulong>() = kern->mem_local();
|
||||
break;
|
||||
|
||||
case CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE:
|
||||
return scalar_property<size_t>(buf, size, size_ret, 1);
|
||||
buf.as_scalar<size_t>() = 1;
|
||||
break;
|
||||
|
||||
case CL_KERNEL_PRIVATE_MEM_SIZE:
|
||||
return scalar_property<cl_ulong>(buf, size, size_ret,
|
||||
kern->mem_private());
|
||||
buf.as_scalar<cl_ulong>() = kern->mem_private();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@@ -192,81 +192,107 @@ clGetSupportedImageFormats(cl_context ctx, cl_mem_flags flags,
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetMemObjectInfo(cl_mem obj, cl_mem_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!obj)
|
||||
return CL_INVALID_MEM_OBJECT;
|
||||
|
||||
switch (param) {
|
||||
case CL_MEM_TYPE:
|
||||
return scalar_property<cl_mem_object_type>(buf, size, size_ret,
|
||||
obj->type());
|
||||
buf.as_scalar<cl_mem_object_type>() = obj->type();
|
||||
break;
|
||||
|
||||
case CL_MEM_FLAGS:
|
||||
return scalar_property<cl_mem_flags>(buf, size, size_ret, obj->flags());
|
||||
buf.as_scalar<cl_mem_flags>() = obj->flags();
|
||||
break;
|
||||
|
||||
case CL_MEM_SIZE:
|
||||
return scalar_property<size_t>(buf, size, size_ret, obj->size());
|
||||
buf.as_scalar<size_t>() = obj->size();
|
||||
break;
|
||||
|
||||
case CL_MEM_HOST_PTR:
|
||||
return scalar_property<void *>(buf, size, size_ret, obj->host_ptr());
|
||||
buf.as_scalar<void *>() = obj->host_ptr();
|
||||
break;
|
||||
|
||||
case CL_MEM_MAP_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<cl_uint>() = 0;
|
||||
break;
|
||||
|
||||
case CL_MEM_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, obj->ref_count());
|
||||
buf.as_scalar<cl_uint>() = obj->ref_count();
|
||||
break;
|
||||
|
||||
case CL_MEM_CONTEXT:
|
||||
return scalar_property<cl_context>(buf, size, size_ret, &obj->ctx);
|
||||
buf.as_scalar<cl_context>() = &obj->ctx;
|
||||
break;
|
||||
|
||||
case CL_MEM_ASSOCIATED_MEMOBJECT: {
|
||||
sub_buffer *sub = dynamic_cast<sub_buffer *>(obj);
|
||||
return scalar_property<cl_mem>(buf, size, size_ret,
|
||||
(sub ? &sub->parent : NULL));
|
||||
buf.as_scalar<cl_mem>() = (sub ? &sub->parent : NULL);
|
||||
break;
|
||||
}
|
||||
case CL_MEM_OFFSET: {
|
||||
sub_buffer *sub = dynamic_cast<sub_buffer *>(obj);
|
||||
return scalar_property<size_t>(buf, size, size_ret,
|
||||
(sub ? sub->offset() : 0));
|
||||
buf.as_scalar<size_t>() = (sub ? sub->offset() : 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetImageInfo(cl_mem obj, cl_image_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
image *img = dynamic_cast<image *>(obj);
|
||||
|
||||
if (!img)
|
||||
return CL_INVALID_MEM_OBJECT;
|
||||
|
||||
switch (param) {
|
||||
case CL_IMAGE_FORMAT:
|
||||
return scalar_property<cl_image_format>(buf, size, size_ret,
|
||||
img->format());
|
||||
buf.as_scalar<cl_image_format>() = img->format();
|
||||
break;
|
||||
|
||||
case CL_IMAGE_ELEMENT_SIZE:
|
||||
return scalar_property<size_t>(buf, size, size_ret, 0);
|
||||
buf.as_scalar<size_t>() = 0;
|
||||
break;
|
||||
|
||||
case CL_IMAGE_ROW_PITCH:
|
||||
return scalar_property<size_t>(buf, size, size_ret, img->row_pitch());
|
||||
buf.as_scalar<size_t>() = img->row_pitch();
|
||||
break;
|
||||
|
||||
case CL_IMAGE_SLICE_PITCH:
|
||||
return scalar_property<size_t>(buf, size, size_ret, img->slice_pitch());
|
||||
buf.as_scalar<size_t>() = img->slice_pitch();
|
||||
break;
|
||||
|
||||
case CL_IMAGE_WIDTH:
|
||||
return scalar_property<size_t>(buf, size, size_ret, img->width());
|
||||
buf.as_scalar<size_t>() = img->width();
|
||||
break;
|
||||
|
||||
case CL_IMAGE_HEIGHT:
|
||||
return scalar_property<size_t>(buf, size, size_ret, img->height());
|
||||
buf.as_scalar<size_t>() = img->height();
|
||||
break;
|
||||
|
||||
case CL_IMAGE_DEPTH:
|
||||
return scalar_property<size_t>(buf, size, size_ret, img->depth());
|
||||
buf.as_scalar<size_t>() = img->depth();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
PUBLIC cl_int
|
||||
|
@@ -46,28 +46,39 @@ clGetPlatformIDs(cl_uint num_entries, cl_platform_id *platforms,
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetPlatformInfo(cl_platform_id platform, cl_platform_info param_name,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (platform != &_clover_platform)
|
||||
return CL_INVALID_PLATFORM;
|
||||
|
||||
switch (param_name) {
|
||||
case CL_PLATFORM_PROFILE:
|
||||
return string_property(buf, size, size_ret, "FULL_PROFILE");
|
||||
buf.as_string() = "FULL_PROFILE";
|
||||
break;
|
||||
|
||||
case CL_PLATFORM_VERSION:
|
||||
return string_property(buf, size, size_ret,
|
||||
"OpenCL 1.1 MESA " PACKAGE_VERSION);
|
||||
buf.as_string() = "OpenCL 1.1 MESA " PACKAGE_VERSION;
|
||||
break;
|
||||
|
||||
case CL_PLATFORM_NAME:
|
||||
return string_property(buf, size, size_ret, "Default");
|
||||
buf.as_string() = "Default";
|
||||
break;
|
||||
|
||||
case CL_PLATFORM_VENDOR:
|
||||
return string_property(buf, size, size_ret, "Mesa");
|
||||
buf.as_string() = "Mesa";
|
||||
break;
|
||||
|
||||
case CL_PLATFORM_EXTENSIONS:
|
||||
return string_property(buf, size, size_ret, "");
|
||||
buf.as_string() = "";
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
@@ -166,62 +166,71 @@ clUnloadCompiler() {
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetProgramInfo(cl_program prog, cl_program_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!prog)
|
||||
return CL_INVALID_PROGRAM;
|
||||
|
||||
switch (param) {
|
||||
case CL_PROGRAM_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
prog->ref_count());
|
||||
buf.as_scalar<cl_uint>() = prog->ref_count();
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_CONTEXT:
|
||||
return scalar_property<cl_context>(buf, size, size_ret,
|
||||
&prog->ctx);
|
||||
buf.as_scalar<cl_context>() = &prog->ctx;
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_NUM_DEVICES:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret,
|
||||
prog->binaries().size());
|
||||
buf.as_scalar<cl_uint>() = prog->binaries().size();
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_DEVICES:
|
||||
return vector_property<cl_device_id>(
|
||||
buf, size, size_ret,
|
||||
map(keys(), prog->binaries()));
|
||||
buf.as_vector<cl_device_id>() = map(keys(), prog->binaries());
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_SOURCE:
|
||||
return string_property(buf, size, size_ret, prog->source());
|
||||
buf.as_string() = prog->source();
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_SIZES:
|
||||
return vector_property<size_t>(
|
||||
buf, size, size_ret,
|
||||
buf.as_vector<size_t>() =
|
||||
map([](const std::pair<device *, module> &ent) {
|
||||
compat::ostream::buffer_t bin;
|
||||
compat::ostream s(bin);
|
||||
ent.second.serialize(s);
|
||||
return bin.size();
|
||||
},
|
||||
prog->binaries()));
|
||||
prog->binaries());
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARIES:
|
||||
return matrix_property<unsigned char>(
|
||||
buf, size, size_ret,
|
||||
buf.as_matrix<unsigned char>() =
|
||||
map([](const std::pair<device *, module> &ent) {
|
||||
compat::ostream::buffer_t bin;
|
||||
compat::ostream s(bin);
|
||||
ent.second.serialize(s);
|
||||
return bin;
|
||||
},
|
||||
prog->binaries()));
|
||||
prog->binaries());
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetProgramBuildInfo(cl_program prog, cl_device_id dev,
|
||||
cl_program_build_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!prog)
|
||||
return CL_INVALID_PROGRAM;
|
||||
|
||||
@@ -230,16 +239,23 @@ clGetProgramBuildInfo(cl_program prog, cl_device_id dev,
|
||||
|
||||
switch (param) {
|
||||
case CL_PROGRAM_BUILD_STATUS:
|
||||
return scalar_property<cl_build_status>(buf, size, size_ret,
|
||||
prog->build_status(dev));
|
||||
buf.as_scalar<cl_build_status>() = prog->build_status(dev);
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BUILD_OPTIONS:
|
||||
return string_property(buf, size, size_ret, prog->build_opts(dev));
|
||||
buf.as_string() = prog->build_opts(dev);
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BUILD_LOG:
|
||||
return string_property(buf, size, size_ret, prog->build_log(dev));
|
||||
buf.as_string() = prog->build_log(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
@@ -69,27 +69,37 @@ clReleaseCommandQueue(cl_command_queue q) {
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetCommandQueueInfo(cl_command_queue q, cl_command_queue_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!q)
|
||||
return CL_INVALID_COMMAND_QUEUE;
|
||||
|
||||
switch (param) {
|
||||
case CL_QUEUE_CONTEXT:
|
||||
return scalar_property<cl_context>(buf, size, size_ret, &q->ctx);
|
||||
buf.as_scalar<cl_context>() = &q->ctx;
|
||||
break;
|
||||
|
||||
case CL_QUEUE_DEVICE:
|
||||
return scalar_property<cl_device_id>(buf, size, size_ret, &q->dev);
|
||||
buf.as_scalar<cl_device_id>() = &q->dev;
|
||||
break;
|
||||
|
||||
case CL_QUEUE_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, q->ref_count());
|
||||
buf.as_scalar<cl_uint>() = q->ref_count();
|
||||
break;
|
||||
|
||||
case CL_QUEUE_PROPERTIES:
|
||||
return scalar_property<cl_command_queue_properties>(buf, size, size_ret,
|
||||
q->props());
|
||||
buf.as_scalar<cl_command_queue_properties>() = q->props();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
||||
PUBLIC cl_int
|
||||
|
@@ -62,29 +62,39 @@ clReleaseSampler(cl_sampler s) {
|
||||
|
||||
PUBLIC cl_int
|
||||
clGetSamplerInfo(cl_sampler s, cl_sampler_info param,
|
||||
size_t size, void *buf, size_t *size_ret) {
|
||||
size_t size, void *r_buf, size_t *r_size) try {
|
||||
property_buffer buf { r_buf, size, r_size };
|
||||
|
||||
if (!s)
|
||||
throw error(CL_INVALID_SAMPLER);
|
||||
|
||||
switch (param) {
|
||||
case CL_SAMPLER_REFERENCE_COUNT:
|
||||
return scalar_property<cl_uint>(buf, size, size_ret, s->ref_count());
|
||||
buf.as_scalar<cl_uint>() = s->ref_count();
|
||||
break;
|
||||
|
||||
case CL_SAMPLER_CONTEXT:
|
||||
return scalar_property<cl_context>(buf, size, size_ret, &s->ctx);
|
||||
buf.as_scalar<cl_context>() = &s->ctx;
|
||||
break;
|
||||
|
||||
case CL_SAMPLER_NORMALIZED_COORDS:
|
||||
return scalar_property<cl_bool>(buf, size, size_ret, s->norm_mode());
|
||||
buf.as_scalar<cl_bool>() = s->norm_mode();
|
||||
break;
|
||||
|
||||
case CL_SAMPLER_ADDRESSING_MODE:
|
||||
return scalar_property<cl_addressing_mode>(buf, size, size_ret,
|
||||
s->addr_mode());
|
||||
buf.as_scalar<cl_addressing_mode>() = s->addr_mode();
|
||||
break;
|
||||
|
||||
case CL_SAMPLER_FILTER_MODE:
|
||||
return scalar_property<cl_filter_mode>(buf, size, size_ret,
|
||||
s->filter_mode());
|
||||
buf.as_scalar<cl_filter_mode>() = s->filter_mode();
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_VALUE;
|
||||
throw error(CL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
|
||||
} catch (error &e) {
|
||||
return e.get();
|
||||
}
|
||||
|
@@ -29,80 +29,11 @@
|
||||
#include <map>
|
||||
|
||||
#include "core/base.hpp"
|
||||
#include "core/property.hpp"
|
||||
#include "util/algorithm.hpp"
|
||||
#include "pipe/p_compiler.h"
|
||||
|
||||
namespace clover {
|
||||
///
|
||||
/// Return a matrix (a container of containers) in \a buf with
|
||||
/// argument and bounds checking. Intended to be used by
|
||||
/// implementations of \a clGetXXXInfo().
|
||||
///
|
||||
template<typename T, typename V>
|
||||
cl_int
|
||||
matrix_property(void *buf, size_t size, size_t *size_ret, const V& v) {
|
||||
if (buf && size < sizeof(T *) * v.size())
|
||||
return CL_INVALID_VALUE;
|
||||
|
||||
if (size_ret)
|
||||
*size_ret = sizeof(T *) * v.size();
|
||||
|
||||
if (buf)
|
||||
for_each([](typename V::value_type src, T *dst) {
|
||||
if (dst)
|
||||
copy(src, dst);
|
||||
},
|
||||
v, range((T **)buf, v.size()));
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
///
|
||||
/// Return a vector in \a buf with argument and bounds checking.
|
||||
/// Intended to be used by implementations of \a clGetXXXInfo().
|
||||
///
|
||||
template<typename T, typename V>
|
||||
cl_int
|
||||
vector_property(void *buf, size_t size, size_t *size_ret, const V& v) {
|
||||
if (buf && size < sizeof(T) * v.size())
|
||||
return CL_INVALID_VALUE;
|
||||
|
||||
if (size_ret)
|
||||
*size_ret = sizeof(T) * v.size();
|
||||
if (buf)
|
||||
copy(v, (T *)buf);
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
///
|
||||
/// Return a scalar in \a buf with argument and bounds checking.
|
||||
/// Intended to be used by implementations of \a clGetXXXInfo().
|
||||
///
|
||||
template<typename T>
|
||||
cl_int
|
||||
scalar_property(void *buf, size_t size, size_t *size_ret, T v) {
|
||||
return vector_property<T>(buf, size, size_ret, std::vector<T>(1, v));
|
||||
}
|
||||
|
||||
///
|
||||
/// Return a string in \a buf with argument and bounds checking.
|
||||
/// Intended to be used by implementations of \a clGetXXXInfo().
|
||||
///
|
||||
inline cl_int
|
||||
string_property(void *buf, size_t size, size_t *size_ret,
|
||||
const std::string &v) {
|
||||
if (buf && size < v.size() + 1)
|
||||
return CL_INVALID_VALUE;
|
||||
|
||||
if (size_ret)
|
||||
*size_ret = v.size() + 1;
|
||||
if (buf)
|
||||
std::strcpy((char *)buf, v.c_str());
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
///
|
||||
/// Convert a NULL-terminated property list into an std::map.
|
||||
///
|
||||
|
193
src/gallium/state_trackers/clover/core/property.hpp
Normal file
193
src/gallium/state_trackers/clover/core/property.hpp
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_CORE_PROPERTY_HPP
|
||||
#define CLOVER_CORE_PROPERTY_HPP
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "util/range.hpp"
|
||||
#include "util/algorithm.hpp"
|
||||
|
||||
namespace clover {
|
||||
class property_buffer;
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
class property_scalar {
|
||||
public:
|
||||
property_scalar(property_buffer &buf) : buf(buf) {
|
||||
}
|
||||
|
||||
inline property_scalar &
|
||||
operator=(const T &x);
|
||||
|
||||
private:
|
||||
property_buffer &buf;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class property_vector {
|
||||
public:
|
||||
property_vector(property_buffer &buf) : buf(buf) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline property_vector &
|
||||
operator=(const S &v);
|
||||
|
||||
private:
|
||||
property_buffer &buf;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class property_matrix {
|
||||
public:
|
||||
property_matrix(property_buffer &buf) : buf(buf) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
inline property_matrix &
|
||||
operator=(const S &v);
|
||||
|
||||
private:
|
||||
property_buffer &buf;
|
||||
};
|
||||
|
||||
class property_string {
|
||||
public:
|
||||
property_string(property_buffer &buf) : buf(buf) {
|
||||
}
|
||||
|
||||
inline property_string &
|
||||
operator=(const std::string &v);
|
||||
|
||||
private:
|
||||
property_buffer &buf;
|
||||
};
|
||||
};
|
||||
|
||||
///
|
||||
/// Return value buffer used by the CL property query functions.
|
||||
///
|
||||
class property_buffer {
|
||||
public:
|
||||
property_buffer(void *r_buf, size_t size, size_t *r_size) :
|
||||
r_buf(r_buf), size(size), r_size(r_size) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
detail::property_scalar<T>
|
||||
as_scalar() {
|
||||
return { *this };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
detail::property_vector<T>
|
||||
as_vector() {
|
||||
return { *this };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
detail::property_matrix<T>
|
||||
as_matrix() {
|
||||
return { *this };
|
||||
}
|
||||
|
||||
detail::property_string
|
||||
as_string() {
|
||||
return { *this };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
iterator_range<T *>
|
||||
allocate(size_t n) {
|
||||
if (r_buf && size < n * sizeof(T))
|
||||
throw error(CL_INVALID_VALUE);
|
||||
|
||||
if (r_size)
|
||||
*r_size = n * sizeof(T);
|
||||
|
||||
if (r_buf)
|
||||
return range((T *)r_buf, n);
|
||||
else
|
||||
return { };
|
||||
}
|
||||
|
||||
private:
|
||||
void *const r_buf;
|
||||
const size_t size;
|
||||
size_t *const r_size;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
inline property_scalar<T> &
|
||||
property_scalar<T>::operator=(const T &x) {
|
||||
auto r = buf.allocate<T>(1);
|
||||
|
||||
if (!r.empty())
|
||||
r.front() = x;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename S>
|
||||
inline property_vector<T> &
|
||||
property_vector<T>::operator=(const S &v) {
|
||||
auto r = buf.allocate<T>(v.size());
|
||||
|
||||
if (!r.empty())
|
||||
copy(v, r.begin());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename S>
|
||||
inline property_matrix<T> &
|
||||
property_matrix<T>::operator=(const S &v) {
|
||||
auto r = buf.allocate<T *>(v.size());
|
||||
|
||||
if (!r.empty())
|
||||
for_each([](typename S::value_type src, T *dst) {
|
||||
if (dst)
|
||||
copy(src, dst);
|
||||
}, v, r);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline property_string &
|
||||
property_string::operator=(const std::string &v) {
|
||||
auto r = buf.allocate<char>(v.size() + 1);
|
||||
|
||||
if (!r.empty())
|
||||
copy(range(v.begin(), r.size()), r.begin());
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user