/* 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;
}
