1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #if defined(__APPLE__)
17 #include <OpenCL/opencl.h>
18 #include <mach/mach_time.h>
19 #else
20 #include <CL/cl.h>
21 #include <malloc.h>
22 #endif
23 #include <assert.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "harness/kernelHelpers.h"
27
28 ///////////////////////////////////////////////////////////////////////////////
29 // CL error checking.
30
31 #if defined(_MSC_VER)
32 #define CL_EXIT_ERROR(cmd, ...) \
33 { \
34 if ((cmd) != CL_SUCCESS) \
35 { \
36 log_error("CL ERROR: %s %u: ", __FILE__, __LINE__); \
37 log_error(##__VA_ARGS__); \
38 log_error("\n"); \
39 return -1; \
40 } \
41 }
42 #else
43 #define CL_EXIT_ERROR(cmd, format, ...) \
44 { \
45 if ((cmd) != CL_SUCCESS) \
46 { \
47 log_error("CL ERROR: %s %u: ", __FILE__, __LINE__); \
48 log_error(format, ##__VA_ARGS__); \
49 log_error("\n"); \
50 return -1; \
51 } \
52 }
53 #endif
54
55 #define CL_EXIT_BUILD_ERROR(cmd, program, format, ...) \
56 { \
57 if ((cmd) != CL_SUCCESS) \
58 { \
59 cl_uint num_devices_; \
60 clGetProgramInfo(program, CL_PROGRAM_NUM_DEVICES, \
61 sizeof(num_devices_), &num_devices_, NULL); \
62 cl_device_id *device_list; \
63 device_list = \
64 (cl_device_id *)malloc(num_devices_ * sizeof(cl_device_id)); \
65 clGetProgramInfo(program, CL_PROGRAM_DEVICES, \
66 num_devices_ * sizeof(cl_device_id), device_list, \
67 NULL); \
68 for (unsigned i = 0; i < num_devices_; ++i) \
69 { \
70 size_t len; \
71 char buffer[2048]; \
72 clGetProgramBuildInfo(program, device_list[i], \
73 CL_PROGRAM_BUILD_LOG, sizeof(buffer), \
74 buffer, &len); \
75 log_error("DEVICE %u CL BUILD ERROR: %s(%u): ", i, __FILE__, \
76 __LINE__); \
77 log_error(format, ##__VA_ARGS__); \
78 log_error("\n"); \
79 } \
80 free(device_list); \
81 return -1; \
82 } \
83 }
84
85 const char *src[] = { "__kernel void simple_task(__global float* output) {\n"
86 " output[0] += 1;\n"
87 "}\n" };
88
89 enum
90 {
91 MaxDevices = 8
92 };
93
test_userevents(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)94 int test_userevents(cl_device_id deviceID, cl_context context,
95 cl_command_queue queue, int num_elements)
96 {
97
98 cl_int err;
99
100 cl_event u1 = clCreateUserEvent(context, &err);
101 CL_EXIT_ERROR(err, "clCreateUserEvent failed");
102
103 // Test event properties.
104 cl_int s;
105 size_t sizeofs;
106 CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_COMMAND_EXECUTION_STATUS,
107 sizeof s, &s, &sizeofs),
108 "clGetEventInfo failed");
109 CL_EXIT_ERROR((sizeof s == sizeofs) ? CL_SUCCESS : -1,
110 "clGetEventInfo returned wrong size for "
111 "CL_EVENT_COMMAND_EXECUTION_STATUS");
112 CL_EXIT_ERROR((s == CL_SUBMITTED) ? CL_SUCCESS : -1,
113 "clGetEventInfo returned wrong value for "
114 "CL_EVENT_COMMAND_EXECUTION_STATUS");
115
116 cl_command_type t;
117 size_t sizeoft;
118 CL_EXIT_ERROR(
119 clGetEventInfo(u1, CL_EVENT_COMMAND_TYPE, sizeof t, &t, &sizeoft),
120 "clGetEventInfo failed");
121 CL_EXIT_ERROR(
122 (sizeof t == sizeoft) ? CL_SUCCESS : -1,
123 "clGetEventInfo returned wrong size for CL_EVENT_COMMAND_TYPE");
124 CL_EXIT_ERROR(
125 (t == CL_COMMAND_USER) ? CL_SUCCESS : -1,
126 "clGetEventInfo returned wrong value for CL_EVENT_COMMAND_TYPE");
127
128 cl_command_queue q;
129 size_t sizeofq;
130 CL_EXIT_ERROR(
131 clGetEventInfo(u1, CL_EVENT_COMMAND_QUEUE, sizeof q, &q, &sizeofq),
132 "clGetEventInfo failed");
133 CL_EXIT_ERROR(
134 (sizeof q == sizeofq) ? CL_SUCCESS : -1,
135 "clGetEventInfo returned wrong size for CL_EVENT_COMMAND_QUEUE");
136 CL_EXIT_ERROR(
137 (q == NULL) ? CL_SUCCESS : -1,
138 "clGetEventInfo returned wrong value for CL_EVENT_COMMAND_QUEUE");
139
140 cl_context c;
141 size_t sizeofc;
142 CL_EXIT_ERROR(clGetEventInfo(u1, CL_EVENT_CONTEXT, sizeof c, &c, &sizeofc),
143 "clGetEventInfo failed");
144 CL_EXIT_ERROR((sizeof c == sizeofc) ? CL_SUCCESS : -1,
145 "clGetEventInfo returned wrong size for CL_EVENT_CONTEXT");
146 CL_EXIT_ERROR((c == context) ? CL_SUCCESS : -1,
147 "clGetEventInfo returned wrong value for CL_EVENT_CONTEXT");
148
149 cl_ulong p;
150 err = clGetEventProfilingInfo(u1, CL_PROFILING_COMMAND_QUEUED, sizeof p, &p,
151 0);
152 CL_EXIT_ERROR((err != CL_SUCCESS) ? CL_SUCCESS : -1,
153 "clGetEventProfilingInfo returned wrong error.");
154
155 // Test semantics.
156 cl_program program;
157 err = create_single_kernel_helper_create_program(context, &program, 1, src);
158 CL_EXIT_ERROR(err, "clCreateProgramWithSource failed");
159
160 CL_EXIT_BUILD_ERROR(clBuildProgram(program, 0, NULL, "", NULL, NULL),
161 program, "Building program from inline src:\t%s",
162 src[0]);
163
164 cl_kernel k0 = clCreateKernel(program, "simple_task", &err);
165 CL_EXIT_ERROR(err, "clCreateKernel failed");
166
167 float buffer[1];
168 cl_mem output = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof buffer,
169 buffer, &err);
170 CL_EXIT_ERROR(err, "clCreateBuffer failed.");
171
172 CL_EXIT_ERROR(clSetKernelArg(k0, 0, sizeof(output), &output),
173 "clSetKernelArg failed");
174
175
176 // Successful case.
177 // //////////////////////////////////////////////////////////////////////////////////////
178 {
179 cl_event e[4];
180 cl_uint N = sizeof e / sizeof(cl_event);
181
182 log_info("Enqueuing tasks\n");
183 for (cl_uint i = 0; i != N; ++i)
184 CL_EXIT_ERROR(clEnqueueTask(queue, k0, 1, &u1, &e[i]),
185 "clEnqueueTaskFailed");
186
187 log_info("Checking task status before setting user event status\n");
188 for (cl_uint i = 0; i != N; ++i)
189 {
190 CL_EXIT_ERROR(clGetEventInfo(e[i],
191 CL_EVENT_COMMAND_EXECUTION_STATUS,
192 sizeof s, &s, 0),
193 "clGetEventInfo failed");
194 CL_EXIT_ERROR(
195 (s >= CL_SUBMITTED) ? CL_SUCCESS : -1,
196 "clGetEventInfo %u returned wrong status before user event", i);
197 }
198
199 log_info("Setting user event status to complete\n");
200 CL_EXIT_ERROR(clSetUserEventStatus(u1, CL_COMPLETE),
201 "clSetUserEventStatus failed");
202
203 log_info("Waiting for tasks to finish executing\n");
204 CL_EXIT_ERROR(clWaitForEvents(1, &e[N - 1]), "clWaitForEvent failed");
205
206 log_info("Checking task status after setting user event status\n");
207 for (cl_uint i = 0; i != N; ++i)
208 {
209 CL_EXIT_ERROR(clGetEventInfo(e[i],
210 CL_EVENT_COMMAND_EXECUTION_STATUS,
211 sizeof s, &s, 0),
212 "clGetEventInfo failed");
213 CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,
214 "clGetEventInfo %u returned wrong status %04x after "
215 "successful user event",
216 i, s);
217 }
218
219 CL_EXIT_ERROR(clReleaseEvent(u1), "clReleaseEvent failed");
220
221 for (cl_uint i = 0; i != N; ++i)
222 CL_EXIT_ERROR(clReleaseEvent(e[i]), "clReleaseEvent failed");
223
224 log_info("Successful user event case passed.\n");
225 }
226
227 // Test unsuccessful user event case.
228 // ///////////////////////////////////////////////////////////////////
229 {
230 cl_event u2 = clCreateUserEvent(context, &err);
231 CL_EXIT_ERROR(err, "clCreateUserEvent failed");
232
233 cl_event e[4];
234 cl_uint N = sizeof e / sizeof(cl_event);
235
236 log_info("Enqueuing tasks\n");
237 for (cl_uint i = 0; i != N; ++i)
238 CL_EXIT_ERROR(clEnqueueTask(queue, k0, 1, &u2, &e[i]),
239 "clEnqueueTaskFailed");
240
241 log_info("Checking task status before setting user event status\n");
242 for (cl_uint i = 0; i != N; ++i)
243 {
244 CL_EXIT_ERROR(clGetEventInfo(e[i],
245 CL_EVENT_COMMAND_EXECUTION_STATUS,
246 sizeof s, &s, 0),
247 "clGetEventInfo failed");
248 CL_EXIT_ERROR(
249 (s == CL_QUEUED || s == CL_SUBMITTED) ? CL_SUCCESS : -1,
250 "clGetEventInfo %u returned wrong status %d before user event",
251 i, (int)s);
252 }
253
254 log_info("Setting user event status to unsuccessful result\n");
255 CL_EXIT_ERROR(clSetUserEventStatus(u2, -1),
256 "clSetUserEventStatus failed");
257
258 log_info("Waiting for tasks to finish executing\n");
259 CL_EXIT_ERROR((clWaitForEvents(N, &e[0]) != CL_SUCCESS) ? CL_SUCCESS
260 : -1,
261 "clWaitForEvent succeeded when it should have failed");
262
263 log_info("Checking task status after setting user event status\n");
264 for (cl_uint i = 0; i != N; ++i)
265 {
266 CL_EXIT_ERROR(clGetEventInfo(e[i],
267 CL_EVENT_COMMAND_EXECUTION_STATUS,
268 sizeof s, &s, 0),
269 "clGetEventInfo failed");
270 CL_EXIT_ERROR((s != CL_QUEUED) ? CL_SUCCESS : -1,
271 "clGetEventInfo %u returned wrong status %04x after "
272 "unsuccessful user event",
273 i, s);
274 }
275
276 CL_EXIT_ERROR(clReleaseEvent(u2), "clReleaseEvent failed");
277
278 for (cl_uint i = 0; i != N; ++i)
279 CL_EXIT_ERROR(clReleaseEvent(e[i]), "clReleaseEvent failed");
280
281 log_info("Unsuccessful user event case passed.\n");
282 }
283
284 clReleaseKernel(k0);
285 clReleaseProgram(program);
286 clReleaseMemObject(output);
287
288 return 0;
289 }
290