| /* This testcase is part of GDB, the GNU debugger. |
| |
| Copyright 2010, 2011 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 <http://www.gnu.org/licenses/>. |
| |
| Contributed by Ken Werner <ken.werner@de.ibm.com> */ |
| |
| /* 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 <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <CL/cl.h> |
| #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; |
| } |