Commit | Line | Data |
---|---|---|
f4b8a18d KW |
1 | /* This testcase is part of GDB, the GNU debugger. |
2 | ||
32d0add0 | 3 | Copyright 2010-2015 Free Software Foundation, Inc. |
f4b8a18d KW |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 3 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | ||
18 | Contributed by Ken Werner <ken.werner@de.ibm.com> */ | |
19 | ||
20 | /* Simple OpenCL application that executes a kernel on the default device | |
21 | in a data parallel fashion. The filename of the OpenCL program source | |
22 | should be specified using the CL_SOURCE define. The name of the kernel | |
23 | routine is expected to be "testkernel". */ | |
24 | ||
25 | #include <stdlib.h> | |
26 | #include <stdio.h> | |
27 | #include <string.h> | |
28 | #include <CL/cl.h> | |
29 | #include "cl_util.h" | |
30 | ||
31 | #ifndef CL_SOURCE | |
32 | #error "Please specify the OpenCL source file using the CL_SOURCE define" | |
33 | #endif | |
34 | ||
35 | #define STRINGIFY(S) _STRINGIFY(S) | |
36 | #define _STRINGIFY(S) #S | |
37 | ||
38 | #define SIZE 16 | |
39 | ||
40 | int | |
41 | main () | |
42 | { | |
43 | int err, i; | |
44 | cl_platform_id platform; | |
45 | cl_device_id device; | |
46 | cl_context context; | |
47 | cl_context_properties context_props[3]; | |
48 | cl_command_queue queue; | |
49 | cl_program program; | |
50 | cl_kernel kernel; | |
51 | cl_mem buffer; | |
52 | ||
53 | size_t len; | |
54 | const char *program_source = NULL; | |
55 | char *device_extensions = NULL; | |
56 | char kernel_build_opts[256]; | |
57 | size_t size = sizeof (cl_int) * SIZE; | |
58 | const size_t global_work_size[] = {SIZE, 0, 0}; /* size of each dimension */ | |
59 | cl_int *data; | |
60 | ||
61 | /* In order to see which devices the OpenCL implementation on your platform | |
62 | provides you may issue a call to the print_clinfo () fuction. */ | |
63 | ||
64 | /* Initialize the data the OpenCl program operates on. */ | |
65 | data = (cl_int*) calloc (1, size); | |
66 | if (data == NULL) | |
67 | { | |
68 | fprintf (stderr, "calloc failed\n"); | |
69 | exit (EXIT_FAILURE); | |
70 | } | |
71 | ||
72 | /* Pick the first platform. */ | |
73 | CHK (clGetPlatformIDs (1, &platform, NULL)); | |
74 | /* Get the default device and create context. */ | |
75 | CHK (clGetDeviceIDs (platform, CL_DEVICE_TYPE_DEFAULT, 1, &device, NULL)); | |
76 | context_props[0] = CL_CONTEXT_PLATFORM; | |
77 | context_props[1] = (cl_context_properties) platform; | |
78 | context_props[2] = 0; | |
79 | context = clCreateContext (context_props, 1, &device, NULL, NULL, &err); | |
80 | CHK_ERR ("clCreateContext", err); | |
81 | queue = clCreateCommandQueue (context, device, 0, &err); | |
82 | CHK_ERR ("clCreateCommandQueue", err); | |
83 | ||
84 | /* Query OpenCL extensions of that device. */ | |
85 | CHK (clGetDeviceInfo (device, CL_DEVICE_EXTENSIONS, 0, NULL, &len)); | |
86 | device_extensions = (char *) malloc (len); | |
87 | CHK (clGetDeviceInfo (device, CL_DEVICE_EXTENSIONS, len, device_extensions, | |
88 | NULL)); | |
89 | strcpy (kernel_build_opts, "-Werror -cl-opt-disable"); | |
90 | if (strstr (device_extensions, "cl_khr_fp64") != NULL) | |
91 | strcpy (kernel_build_opts + strlen (kernel_build_opts), | |
92 | " -D HAVE_cl_khr_fp64"); | |
93 | if (strstr (device_extensions, "cl_khr_fp16") != NULL) | |
94 | strcpy (kernel_build_opts + strlen (kernel_build_opts), | |
95 | " -D HAVE_cl_khr_fp16"); | |
96 | ||
97 | /* Read the OpenCL kernel source into the main memory. */ | |
98 | program_source = read_file (STRINGIFY (CL_SOURCE), &len); | |
99 | if (program_source == NULL) | |
100 | { | |
101 | fprintf (stderr, "file does not exist: %s\n", STRINGIFY (CL_SOURCE)); | |
102 | exit (EXIT_FAILURE); | |
103 | } | |
104 | ||
105 | /* Build the OpenCL kernel. */ | |
106 | program = clCreateProgramWithSource (context, 1, &program_source, | |
107 | &len, &err); | |
108 | free ((void*) program_source); | |
109 | CHK_ERR ("clCreateProgramWithSource", err); | |
110 | err = clBuildProgram (program, 0, NULL, kernel_build_opts, NULL, | |
111 | NULL); | |
112 | if (err != CL_SUCCESS) | |
113 | { | |
114 | size_t len; | |
115 | char *clbuild_log = NULL; | |
116 | CHK (clGetProgramBuildInfo (program, device, CL_PROGRAM_BUILD_LOG, 0, | |
117 | NULL, &len)); | |
118 | clbuild_log = malloc (len); | |
119 | if (clbuild_log) | |
120 | { | |
121 | CHK (clGetProgramBuildInfo (program, device, CL_PROGRAM_BUILD_LOG, | |
122 | len, clbuild_log, NULL)); | |
123 | fprintf (stderr, "clBuildProgram failed with:\n%s\n", clbuild_log); | |
124 | free (clbuild_log); | |
125 | } | |
126 | exit (EXIT_FAILURE); | |
127 | } | |
128 | ||
129 | /* In some cases it might be handy to save the OpenCL program binaries to do | |
130 | further analysis on them. In order to do so you may call the following | |
131 | function: save_program_binaries (program);. */ | |
132 | ||
133 | kernel = clCreateKernel (program, "testkernel", &err); | |
134 | CHK_ERR ("clCreateKernel", err); | |
135 | ||
136 | /* Setup the input data for the kernel. */ | |
137 | buffer = clCreateBuffer (context, CL_MEM_USE_HOST_PTR, size, data, &err); | |
138 | CHK_ERR ("clCreateBuffer", err); | |
139 | ||
140 | /* Execute the kernel (data parallel). */ | |
141 | CHK (clSetKernelArg (kernel, 0, sizeof (buffer), &buffer)); | |
142 | CHK (clEnqueueNDRangeKernel (queue, kernel, 1, NULL, global_work_size, NULL, | |
143 | 0, NULL, NULL)); | |
144 | ||
145 | /* Fetch the results (blocking). */ | |
146 | CHK (clEnqueueReadBuffer (queue, buffer, CL_TRUE, 0, size, data, 0, NULL, | |
147 | NULL)); | |
148 | ||
149 | /* Compare the results. */ | |
150 | for (i = 0; i < SIZE; i++) | |
151 | { | |
152 | if (data[i] != 0x1) | |
153 | { | |
154 | fprintf (stderr, "error: data[%d]: %d != 0x1\n", i, data[i]); | |
155 | exit (EXIT_FAILURE); | |
156 | } | |
157 | } | |
158 | ||
159 | /* Cleanup. */ | |
160 | CHK (clReleaseMemObject (buffer)); | |
161 | CHK (clReleaseKernel (kernel)); | |
162 | CHK (clReleaseProgram (program)); | |
163 | CHK (clReleaseCommandQueue (queue)); | |
164 | CHK (clReleaseContext (context)); | |
165 | free (data); | |
166 | ||
167 | return 0; | |
168 | } |