/* This testcase is part of GDB, the GNU debugger. Copyright 2010-2020 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; }