/* This testcase is part of GDB, the GNU debugger.
Copyright 2010-2017 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Contributed by Ken Werner */
/* Simple OpenCL application that executes a kernel on the default device
in a data parallel fashion. The filename of the OpenCL program source
should be specified using the CL_SOURCE define. The name of the kernel
routine is expected to be "testkernel". */
#include
#include
#include
#include
#include "cl_util.h"
#ifndef CL_SOURCE
#error "Please specify the OpenCL source file using the CL_SOURCE define"
#endif
#define STRINGIFY(S) _STRINGIFY(S)
#define _STRINGIFY(S) #S
#define SIZE 16
int
main ()
{
int err, i;
cl_platform_id platform;
cl_device_id device;
cl_context context;
cl_context_properties context_props[3];
cl_command_queue queue;
cl_program program;
cl_kernel kernel;
cl_mem buffer;
size_t len;
const char *program_source = NULL;
char *device_extensions = NULL;
char kernel_build_opts[256];
size_t size = sizeof (cl_int) * SIZE;
const size_t global_work_size[] = {SIZE, 0, 0}; /* size of each dimension */
cl_int *data;
/* In order to see which devices the OpenCL implementation on your platform
provides you may issue a call to the print_clinfo () fuction. */
/* Initialize the data the OpenCl program operates on. */
data = (cl_int*) calloc (1, size);
if (data == NULL)
{
fprintf (stderr, "calloc failed\n");
exit (EXIT_FAILURE);
}
/* Pick the first platform. */
CHK (clGetPlatformIDs (1, &platform, NULL));
/* Get the default device and create context. */
CHK (clGetDeviceIDs (platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, NULL));
context_props[0] = CL_CONTEXT_PLATFORM;
context_props[1] = (cl_context_properties) platform;
context_props[2] = 0;
context = clCreateContext (context_props, 1, &device, NULL, NULL, &err);
CHK_ERR ("clCreateContext", err);
queue = clCreateCommandQueue (context, device, 0, &err);
CHK_ERR ("clCreateCommandQueue", err);
/* Query OpenCL extensions of that device. */
CHK (clGetDeviceInfo (device, CL_DEVICE_EXTENSIONS, 0, NULL, &len));
device_extensions = (char *) malloc (len);
CHK (clGetDeviceInfo (device, CL_DEVICE_EXTENSIONS, len, device_extensions,
NULL));
strcpy (kernel_build_opts, "-Werror -cl-opt-disable");
if (strstr (device_extensions, "cl_khr_fp64") != NULL)
strcpy (kernel_build_opts + strlen (kernel_build_opts),
" -D HAVE_cl_khr_fp64");
if (strstr (device_extensions, "cl_khr_fp16") != NULL)
strcpy (kernel_build_opts + strlen (kernel_build_opts),
" -D HAVE_cl_khr_fp16");
/* Read the OpenCL kernel source into the main memory. */
program_source = read_file (STRINGIFY (CL_SOURCE), &len);
if (program_source == NULL)
{
fprintf (stderr, "file does not exist: %s\n", STRINGIFY (CL_SOURCE));
exit (EXIT_FAILURE);
}
/* Build the OpenCL kernel. */
program = clCreateProgramWithSource (context, 1, &program_source,
&len, &err);
free ((void*) program_source);
CHK_ERR ("clCreateProgramWithSource", err);
err = clBuildProgram (program, 0, NULL, kernel_build_opts, NULL,
NULL);
if (err != CL_SUCCESS)
{
size_t len;
char *clbuild_log = NULL;
CHK (clGetProgramBuildInfo (program, device, CL_PROGRAM_BUILD_LOG, 0,
NULL, &len));
clbuild_log = malloc (len);
if (clbuild_log)
{
CHK (clGetProgramBuildInfo (program, device, CL_PROGRAM_BUILD_LOG,
len, clbuild_log, NULL));
fprintf (stderr, "clBuildProgram failed with:\n%s\n", clbuild_log);
free (clbuild_log);
}
exit (EXIT_FAILURE);
}
/* In some cases it might be handy to save the OpenCL program binaries to do
further analysis on them. In order to do so you may call the following
function: save_program_binaries (program);. */
kernel = clCreateKernel (program, "testkernel", &err);
CHK_ERR ("clCreateKernel", err);
/* Setup the input data for the kernel. */
buffer = clCreateBuffer (context, CL_MEM_USE_HOST_PTR, size, data, &err);
CHK_ERR ("clCreateBuffer", err);
/* Execute the kernel (data parallel). */
CHK (clSetKernelArg (kernel, 0, sizeof (buffer), &buffer));
CHK (clEnqueueNDRangeKernel (queue, kernel, 1, NULL, global_work_size, NULL,
0, NULL, NULL));
/* Fetch the results (blocking). */
CHK (clEnqueueReadBuffer (queue, buffer, CL_TRUE, 0, size, data, 0, NULL,
NULL));
/* Compare the results. */
for (i = 0; i < SIZE; i++)
{
if (data[i] != 0x1)
{
fprintf (stderr, "error: data[%d]: %d != 0x1\n", i, data[i]);
exit (EXIT_FAILURE);
}
}
/* Cleanup. */
CHK (clReleaseMemObject (buffer));
CHK (clReleaseKernel (kernel));
CHK (clReleaseProgram (program));
CHK (clReleaseCommandQueue (queue));
CHK (clReleaseContext (context));
free (data);
return 0;
}