示例#1
0
/**
 * @internal
 *
 * @brief Implementation of ::ccl_dev_container_get_cldevices() for the
 * platform wrapper.
 *
 * @private @memberof ccl_platform
 *
 * @param[in] devcon A ::CCLPlatform wrapper, passed as a ::CCLDevContainer.
 * @param[out] err Return location for a ::CCLErr object, or `NULL` if error
 * reporting is to be ignored.
 * @return A list of `cl_device_id` objects inside a ::CCLWrapperInfo object.
 * */
static CCLWrapperInfo * ccl_platform_get_cldevices(
    CCLDevContainer * devcon, CCLErr ** err) {

    /* Make sure err is NULL or it is not set. */
    g_return_val_if_fail(err == NULL || *err == NULL, NULL);

    /* Make sure devcon is not NULL. */
    g_return_val_if_fail(devcon != NULL, NULL);

    CCLWrapperInfo * info = NULL;

    cl_int ocl_status;

    /* Determine number of devices. */
    ocl_status = clGetDeviceIDs(devcon->base.cl_object,
        CL_DEVICE_TYPE_ALL, 0, NULL, &devcon->num_devices);
    g_if_err_create_goto(*err, CCL_OCL_ERROR,
        CL_SUCCESS != ocl_status, ocl_status, error_handler,
        "%s: get number of devices (OpenCL error %d: %s).",
        CCL_STRD, ocl_status, ccl_err(ocl_status));

    /* Create info object with size in bytes of array of device IDs. */
    info = ccl_wrapper_info_new(
        sizeof(cl_device_id) * devcon->num_devices);

    /* Get existing device IDs. */
    ocl_status = clGetDeviceIDs(devcon->base.cl_object,
        CL_DEVICE_TYPE_ALL, devcon->num_devices, info->value, NULL);
    g_if_err_create_goto(*err, CCL_OCL_ERROR,
        CL_SUCCESS != ocl_status, ocl_status, error_handler,
        "%s: get device IDs (OpenCL error %d: %s).",
        CCL_STRD, ocl_status, ccl_err(ocl_status));

    /* Add device list to info table, so that it will be
     * automatically released. Because the cl_platform_id object
     * doesn't have a CL_PLATFORM_DEVICES parameter, we keep this info
     * referenced has CL_CONTEXT_DEVICES. */
    ccl_wrapper_add_info((CCLWrapper *) devcon, CL_CONTEXT_DEVICES, info);

    /* If we got here, everything is OK. */
    g_assert(err == NULL || *err == NULL);
    goto finish;

error_handler:
    /* If we got here there was an error, verify that it is so. */
    g_assert(err == NULL || *err != NULL);

    /* Free info if it was created. */
    if (info != NULL) ccl_wrapper_info_destroy(info);

finish:

    /* Terminate function. */
    return info;
}
示例#2
0
/**
 * Create a new kernel wrapper object.
 *
 * @public @memberof ccl_kernel
 *
 * @param[in] prg A program wrapper object.
 * @param[in] kernel_name The kernel name.
 * @param[out] err Return location for a ::CCLErr object, or `NULL` if error
 * reporting is to be ignored.
 * @return A new kernel wrapper object.
 * */
CCL_EXPORT
CCLKernel* ccl_kernel_new(
	CCLProgram* prg, const char* kernel_name, CCLErr** err) {

	/* Make sure err is NULL or it is not set. */
	g_return_val_if_fail((err) == NULL || *(err) == NULL, NULL);

	/* Make sure prg is not NULL. */
	g_return_val_if_fail(prg != NULL, NULL);

	/* Make sure kernel_name is not NULL. */
	g_return_val_if_fail(kernel_name != NULL, NULL);

	/* Kernel wrapper object. */
	CCLKernel* krnl = NULL;

	/* OpenCL return status. */
	cl_int ocl_status;

	/* The OpenCL kernel object. */
	cl_kernel kernel = NULL;

	/* Create kernel. */
	kernel = clCreateKernel(ccl_program_unwrap(prg),
		kernel_name, &ocl_status);
	ccl_if_err_create_goto(*err, CCL_OCL_ERROR,
		CL_SUCCESS != ocl_status, ocl_status, error_handler,
		"%s: unable to create kernel (OpenCL error %d: %s).",
		CCL_STRD, ocl_status, ccl_err(ocl_status));

	/* Create kernel wrapper. */
	krnl = ccl_kernel_new_wrap(kernel);

	/* If we got here, everything is OK. */
	g_assert(err == NULL || *err == NULL);
	goto finish;

error_handler:

	/* If we got here there was an error, verify that it is so. */
	g_assert(err == NULL || *err != NULL);

	krnl = NULL;

finish:

	/* Return kernel wrapper. */
	return krnl;

}
示例#3
0
/**
 * Enqueues a command to execute a native C/C++ function not compiled
 * using the OpenCL compiler. This function is a wrapper for the
 * clEnqueueNativeKernel() OpenCL function, the documentation of which
 * provides additional information.
 *
 * @public @memberof ccl_kernel
 *
 * @param[in] cq A command queue wrapper object.
 * @param[in] user_func A pointer to a host-callable user function.
 * @param[in] args A pointer to the args list that `user_func` should be
 * called with.
 * @param[in] cb_args The size in bytes of the args list that args
 * points to.
 * @param[in] num_mos The number of ::CCLMemObj* objects that are passed
 * in `mo_list`.
 * @param[in] mo_list A list of ::CCLMemObj* objects (or `NULL`
 * references), if num_mos > 0.
 * @param[in] args_mem_loc A pointer to appropriate locations that
 * `args` points to where `cl_mem` values (unwrapped from the respective
 * ::CCLMemObj* objects) are stored. Before the user function is
 * executed, the `cl_mem` values are replaced by pointers to global
 * memory.
 * @param[in,out] evt_wait_lst List of events that need to complete
 * before this command can be executed. The list will be cleared and
 * can be reused by client code.
 * @param[out] err Return location for a ::CCLErr object, or `NULL` if error
 * reporting is to be ignored.
 * @return Event wrapper object that identifies this command.
 * */
CCL_EXPORT
CCLEvent* ccl_kernel_enqueue_native(CCLQueue* cq,
	void (CL_CALLBACK * user_func)(void*), void* args, size_t cb_args,
	cl_uint num_mos, CCLMemObj* const* mo_list,
	const void** args_mem_loc, CCLEventWaitList* evt_wait_lst,
	CCLErr** err) {

	/* Make sure cq is not NULL. */
	g_return_val_if_fail(cq != NULL, NULL);
	/* Make sure user_func is not NULL. */
	g_return_val_if_fail(user_func != NULL, NULL);
	/* Make sure that num_mos == 0 AND mo_list != NULL, OR, that
	 * num_mos > 0  AND mo_list != NULL */
	g_return_val_if_fail(((num_mos == 0) && (mo_list == NULL))
		|| ((num_mos > 0) && (mo_list != NULL)), NULL);
	/* Make sure err is NULL or it is not set. */
	g_return_val_if_fail(err == NULL || *err == NULL, NULL);

	/* OpenCL status flag. */
	cl_int ocl_status;
	/* OpenCL event. */
	cl_event event = NULL;
	/* Event wrapper. */
	CCLEvent* evt = NULL;
	/* List of cl_mem objects. */
	cl_mem* mem_list = NULL;

	/* Unwrap memory objects. */
	if (num_mos > 0) {
		mem_list = g_slice_alloc(sizeof(cl_mem) * num_mos);
		for (cl_uint i = 0; i < num_mos; ++i) {
			mem_list[i] = mo_list[i] != NULL
				? ccl_memobj_unwrap(mo_list[i])
				: NULL;
		}
	}

	/* Enqueue kernel. */
	ocl_status = clEnqueueNativeKernel(ccl_queue_unwrap(cq), user_func,
		args, cb_args, num_mos, (const cl_mem*) mem_list, args_mem_loc,
		ccl_event_wait_list_get_num_events(evt_wait_lst),
		ccl_event_wait_list_get_clevents(evt_wait_lst), &event);
	ccl_if_err_create_goto(*err, CCL_OCL_ERROR,
		CL_SUCCESS != ocl_status, ocl_status, error_handler,
		"%s: unable to enqueue native kernel (OpenCL error %d: %s).",
		CCL_STRD, ocl_status, ccl_err(ocl_status));

	/* Wrap event and associate it with the respective command queue.
	 * The event object will be released automatically when the command
	 * queue is released. */
	evt = ccl_queue_produce_event(cq, event);

	/* Clear event wait list. */
	ccl_event_wait_list_clear(evt_wait_lst);

	/* If we got here, everything is OK. */
	g_assert(err == NULL || *err == NULL);
	goto finish;

error_handler:

	/* If we got here there was an error, verify that it is so. */
	g_assert(err == NULL || *err != NULL);

finish:

	/* Release temporary cl_mem list. */
	if (num_mos > 0)
		g_slice_free1(sizeof(cl_mem) * num_mos, mem_list);

	/* Return event wrapper. */
	return evt;

}
示例#4
0
/**
 * Enqueues a kernel for execution on a device.
 *
 * Internally, this function calls the clSetKernelArg() OpenCL function
 * for each argument defined with the ::ccl_kernel_set_arg() function,
 * and the executes the kernel using the clEnqueueNDRangeKernel() OpenCL
 * function.
 *
 * @warning This function is not thread-safe. For multi-threaded
 * access to the same kernel function, create multiple instances of
 * a kernel wrapper for the given kernel function with
 * ::ccl_kernel_new(), one for each thread.
 *
 * @public @memberof ccl_kernel
 *
 * @param[in] krnl A kernel wrapper object.
 * @param[in] cq A command queue wrapper object.
 * @param[in] work_dim The number of dimensions used to specify the
 * global work-items and work-items in the work-group.
 * @param[in] global_work_offset Can be used to specify an array of
 * `work_dim` unsigned values that describe the offset used to calculate
 * the global ID of a work-item.
 * @param[in] global_work_size An array of `work_dim` unsigned values
 * that describe the number of global work-items in `work_dim`
 * dimensions that will execute the kernel function.
 * @param[in] local_work_size An array of `work_dim` unsigned values
 * that describe the number of work-items that make up a work-group that
 * will execute the specified kernel.
 * @param[in,out] evt_wait_lst List of events that need to complete
 * before this command can be executed. The list will be cleared and
 * can be reused by client code.
 * @param[out] err Return location for a ::CCLErr object, or `NULL` if error
 * reporting is to be ignored.
 * @return Event wrapper object that identifies this command.
 * */
CCL_EXPORT
CCLEvent* ccl_kernel_enqueue_ndrange(CCLKernel* krnl, CCLQueue* cq,
	cl_uint work_dim, const size_t* global_work_offset,
	const size_t* global_work_size, const size_t* local_work_size,
	CCLEventWaitList* evt_wait_lst, CCLErr** err) {

	/* Make sure krnl is not NULL. */
	g_return_val_if_fail(krnl != NULL, NULL);
	/* Make sure cq is not NULL. */
	g_return_val_if_fail(cq != NULL, NULL);
	/* Make sure err is NULL or it is not set. */
	g_return_val_if_fail(err == NULL || *err == NULL, NULL);

	/* OpenCL status flag. */
	cl_int ocl_status;

	/* OpenCL event. */
	cl_event event;
	/* Event wrapper. */
	CCLEvent* evt;

	/* Iterator for table of kernel arguments. */
	GHashTableIter iter;
	gpointer arg_index_ptr, arg_ptr;

	/* Set pending kernel arguments. */
	if (krnl->args != NULL) {
		g_hash_table_iter_init(&iter, krnl->args);
		while (g_hash_table_iter_next(&iter, &arg_index_ptr, &arg_ptr)) {
			cl_uint arg_index = GPOINTER_TO_UINT(arg_index_ptr);
			CCLArg* arg = (CCLArg*) arg_ptr;
			ocl_status = clSetKernelArg(ccl_kernel_unwrap(krnl), arg_index,
				ccl_arg_size(arg), ccl_arg_value(arg));
			ccl_if_err_create_goto(*err, CCL_OCL_ERROR,
				CL_SUCCESS != ocl_status, ocl_status, error_handler,
				"%s: unable to set kernel arg %d (OpenCL error %d: %s).",
				CCL_STRD, arg_index, ocl_status, ccl_err(ocl_status));
			g_hash_table_iter_remove(&iter);
		}
	}

	/* Run kernel. */
	ocl_status = clEnqueueNDRangeKernel(ccl_queue_unwrap(cq),
		ccl_kernel_unwrap(krnl), work_dim, global_work_offset,
		global_work_size, local_work_size,
		ccl_event_wait_list_get_num_events(evt_wait_lst),
		ccl_event_wait_list_get_clevents(evt_wait_lst), &event);
	ccl_if_err_create_goto(*err, CCL_OCL_ERROR,
		CL_SUCCESS != ocl_status, ocl_status, error_handler,
		"%s: unable to enqueue kernel (OpenCL error %d: %s).",
		CCL_STRD, ocl_status, ccl_err(ocl_status));

	/* Wrap event and associate it with the respective command queue.
	 * The event object will be released automatically when the command
	 * queue is released. */
	evt = ccl_queue_produce_event(cq, event);

	/* Clear event wait list. */
	ccl_event_wait_list_clear(evt_wait_lst);

	/* If we got here, everything is OK. */
	g_assert(err == NULL || *err == NULL);
	goto finish;

error_handler:

	/* If we got here there was an error, verify that it is so. */
	g_assert(err == NULL || *err != NULL);

	/* An error occurred, return NULL to signal it. */
	evt = NULL;

finish:

	/* Return evt. */
	return evt;

}
示例#5
0
/**
 * Create a new sampler wrapper object using a list of properties.
 *
 * If a supported property is not specified, a default value is used.
 * Some valid properties are `CL_SAMPLER_NORMALIZED_COORDS` (default
 * value is `CL_TRUE`), `CL_SAMPLER_ADDRESSING_MODE` (default value is
 * `CL_ADDRESS_CLAMP`) and `CL_SAMPLER_FILTER_MODE` (default value is
 * `CL_FILTER_NEAREST`).
 *
 * This function mimicks the style of the OpenCL 2.0 sampler
 * constructor, clCreateSamplerWithProperties(), but can be used with
 * any version of OpenCL. Thus, The underlying OpenCL sampler object is
 * created using:
 *
 * * clCreateSampler() - for platforms with OpenCL version <= 1.2
 * * clCreateSamplerWithProperties() - for platforms with OpenCL version
 * >= 2.0.
 *
 * @public @memberof ccl_sampler
 *
 * @param[in] ctx A context wrapper object.
 * @param[in] sampler_properties A list of sampler property names and
 * their corresponding values. Each sampler property name is immediately
 * followed by the corresponding desired value. The list is terminated
 * with 0. If a supported property is not specified, its default value
 * will be used. If `NULL`, default values for supported sampler
 * properties will be used.
 * @param[out] err Return location for a ::CCLErr object, or `NULL` if error
 * reporting is to be ignored.
 * @return A new sampler wrapper object or `NULL` if an error occurs.
 * */
CCL_EXPORT
CCLSampler* ccl_sampler_new_full(CCLContext* ctx,
	const cl_sampler_properties *sampler_properties, CCLErr** err) {

	/* Make sure err is NULL or it is not set. */
	g_return_val_if_fail((err) == NULL || *(err) == NULL, NULL);
	/* Make sure ctx is not NULL. */
	g_return_val_if_fail(ctx != NULL, NULL);

	/* New sampler wrapper object to create. */
	CCLSampler* smplr = NULL;
	/* OpenCL sampler object to create and wrap. */
	cl_sampler sampler;
	/* OpenCL function status. */
	cl_int ocl_status;

#ifdef CL_VERSION_2_0

	/* OpenCL platform version. */
	double ocl_ver;
	/* Internal error handling object. */
	CCLErr* err_internal = NULL;

	/* Get context platform version. */
	ocl_ver = ccl_context_get_opencl_version(ctx, &err_internal);
	ccl_if_err_propagate_goto(err, err_internal, error_handler);

	/* Create the OpenCL sampler object. */
	if (ocl_ver >= 200) {
		/* Platform is OpenCL >= 2.0, use "new" API. */
		sampler = clCreateSamplerWithProperties(
			ccl_context_unwrap(ctx), sampler_properties, &ocl_status);
	} else {
		/* Platform is OpenCL <= 1.2, use "old" API. */
		struct ccl_sampler_basic_properties sbp =
			ccl_sampler_get_basic_properties(sampler_properties);
		CCL_BEGIN_IGNORE_DEPRECATIONS
		sampler = clCreateSampler(ccl_context_unwrap(ctx),
			sbp.normalized_coords, sbp.addressing_mode, sbp.filter_mode,
			&ocl_status);
		CCL_END_IGNORE_DEPRECATIONS
	}

#else

	/* Create OpenCL sampler object. */
	struct ccl_sampler_basic_properties sbp =
		ccl_sampler_get_basic_properties(sampler_properties);
	sampler = clCreateSampler(ccl_context_unwrap(ctx),
		sbp.normalized_coords, sbp.addressing_mode, sbp.filter_mode,
		&ocl_status);

#endif

	/* Check for errors. */
	ccl_if_err_create_goto(*err, CCL_OCL_ERROR,
		CL_SUCCESS != ocl_status, ocl_status, error_handler,
		"%s: unable to create sampler (OpenCL error %d: %s).",
		CCL_STRD, ocl_status, ccl_err(ocl_status));

	/* Create sampler wrapper. */
	smplr = ccl_sampler_new_wrap(sampler);

	/* If we got here, everything is OK. */
	g_assert(err == NULL || *err == NULL);
	goto finish;

error_handler:

	/* If we got here there was an error, verify that it is so. */
	g_assert(err == NULL || *err != NULL);

finish:

	/* Return sampler wrapper. */
	return smplr;


}