| /* |
| * cl_kernel.cpp - CL kernel |
| * |
| * Copyright (c) 2015 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| * Author: Wind Yuan <feng.yuan@intel.com> |
| */ |
| |
| #include "cl_kernel.h" |
| #include "cl_context.h" |
| #include "cl_device.h" |
| |
| #define XCAM_CL_KERNEL_DEFAULT_WORK_DIM 2 |
| #define XCAM_CL_KERNEL_DEFAULT_LOCAL_WORK_SIZE 1 |
| |
| namespace XCam { |
| |
| CLKernel::CLKernel(SmartPtr<CLContext> &context, const char *name) |
| : _name (NULL) |
| , _kernel_id (NULL) |
| , _context (context) |
| , _work_dim (0) |
| { |
| XCAM_ASSERT (context.ptr ()); |
| XCAM_ASSERT (name); |
| |
| if (name) |
| _name = strdup (name); |
| |
| set_default_work_size (); |
| } |
| |
| CLKernel::~CLKernel () |
| { |
| destroy (); |
| if (_name) |
| xcam_free (_name); |
| } |
| |
| void |
| CLKernel::destroy () |
| { |
| _context->destroy_kernel_id (_kernel_id); |
| } |
| |
| XCamReturn |
| CLKernel::load_from_source (const char *source, size_t length) |
| { |
| cl_kernel new_kernel_id = NULL; |
| |
| XCAM_ASSERT (source); |
| if (!source) { |
| XCAM_LOG_WARNING ("kernel:%s source empty", XCAM_STR (_name)); |
| return XCAM_RETURN_ERROR_PARAM; |
| } |
| |
| if (_kernel_id) { |
| XCAM_LOG_WARNING ("kernel:%s already build yet", XCAM_STR (_name)); |
| return XCAM_RETURN_ERROR_PARAM; |
| } |
| |
| XCAM_ASSERT (_context.ptr ()); |
| |
| if (length == 0) |
| length = strlen (source); |
| |
| new_kernel_id = |
| _context->generate_kernel_id ( |
| this, |
| (const uint8_t *)source, length, |
| CLContext::KERNEL_BUILD_SOURCE); |
| XCAM_FAIL_RETURN( |
| WARNING, |
| new_kernel_id != NULL, |
| XCAM_RETURN_ERROR_CL, |
| "cl kernel(%s) load from source failed", XCAM_STR (_name)); |
| |
| _kernel_id = new_kernel_id; |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| CLKernel::load_from_binary (const uint8_t *binary, size_t length) |
| { |
| cl_kernel new_kernel_id = NULL; |
| |
| XCAM_ASSERT (binary); |
| if (!binary || !length) { |
| XCAM_LOG_WARNING ("kernel:%s binary empty", XCAM_STR (_name)); |
| return XCAM_RETURN_ERROR_PARAM; |
| } |
| |
| if (_kernel_id) { |
| XCAM_LOG_WARNING ("kernel:%s already build yet", XCAM_STR (_name)); |
| return XCAM_RETURN_ERROR_PARAM; |
| } |
| |
| XCAM_ASSERT (_context.ptr ()); |
| |
| new_kernel_id = |
| _context->generate_kernel_id ( |
| this, |
| binary, length, |
| CLContext::KERNEL_BUILD_BINARY); |
| XCAM_FAIL_RETURN( |
| WARNING, |
| new_kernel_id != NULL, |
| XCAM_RETURN_ERROR_CL, |
| "cl kernel(%s) load from binary failed", XCAM_STR (_name)); |
| |
| _kernel_id = new_kernel_id; |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| CLKernel::set_argument (uint32_t arg_i, void *arg_addr, uint32_t arg_size) |
| { |
| cl_int error_code = clSetKernelArg (_kernel_id, arg_i, arg_size, arg_addr); |
| if (error_code != CL_SUCCESS) { |
| XCAM_LOG_DEBUG ("kernel(%s) set arg_i(%d) failed", _name, arg_i); |
| return XCAM_RETURN_ERROR_CL; |
| } |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| XCamReturn |
| CLKernel::set_work_size (uint32_t dim, size_t *global, size_t *local) |
| { |
| uint32_t i = 0; |
| uint32_t work_group_size = 1; |
| const CLDevieInfo &dev_info = CLDevice::instance ()->get_device_info (); |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| dim <= dev_info.max_work_item_dims, |
| XCAM_RETURN_ERROR_PARAM, |
| "kernel(%s) work dims(%d) greater than device max dims(%d)", |
| _name, dim, dev_info.max_work_item_dims); |
| |
| for (i = 0; i < dim; ++i) { |
| work_group_size *= local [i]; |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| local [i] <= dev_info.max_work_item_sizes [i], |
| XCAM_RETURN_ERROR_PARAM, |
| "kernel(%s) work item(%d) size:%d is greater than device max work item size(%d)", |
| _name, i, local [i], dev_info.max_work_item_sizes [i]); |
| } |
| |
| XCAM_FAIL_RETURN ( |
| WARNING, |
| work_group_size <= dev_info.max_work_group_size, |
| XCAM_RETURN_ERROR_PARAM, |
| "kernel(%s) work-group-size:%d is greater than device max work-group-size(%d)", |
| _name, work_group_size, dev_info.max_work_group_size); |
| |
| _work_dim = dim; |
| for (i = 0; i < dim; ++i) { |
| _global_work_size [i] = global [i]; |
| _local_work_size [i] = local [i]; |
| } |
| |
| return XCAM_RETURN_NO_ERROR; |
| } |
| |
| void |
| CLKernel::set_default_work_size () |
| { |
| _work_dim = XCAM_CL_KERNEL_DEFAULT_WORK_DIM; |
| for (uint32_t i = 0; i < _work_dim; ++i) { |
| //_global_work_size [i] = XCAM_CL_KERNEL_DEFAULT_GLOBAL_WORK_SIZE; |
| _local_work_size [i] = XCAM_CL_KERNEL_DEFAULT_LOCAL_WORK_SIZE; |
| } |
| } |
| |
| XCamReturn |
| CLKernel::execute ( |
| const cl_event *events_wait, |
| uint32_t num_of_events_wait, |
| cl_event *event_out) |
| { |
| XCAM_ASSERT (_context.ptr ()); |
| return _context->execute_kernel (this, NULL, events_wait, num_of_events_wait, event_out); |
| } |
| |
| }; |