Use _exit() instead of exit() in child processes
[piglit.git] / tests / cl / api / link-program.c
blobc1734ebb19441f79db0116f085887f5e47c3e55a
1 /*
2 * Copyright © 2014 EdB <edb+piglit@sigluy.net>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /**
25 * @file link-program.c
27 * Test API function:
29 * cl_program
30 * clLinkProgram(cl_context context,
31 * cl_uint num_devices, const cl_device_id device_list,
32 * const char *options,
33 * cl_uint num_input_programs, const cl_program *input_programs,
34 * void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
35 * void *user_data,
36 * cl_int *errcode_ret)
39 #include "piglit-framework-cl-api.h"
42 PIGLIT_CL_API_TEST_CONFIG_BEGIN
44 config.name = "clLinkProgram";
45 config.version_min = 12;
47 config.run_per_platform = true;
48 config.create_context = true;
50 PIGLIT_CL_API_TEST_CONFIG_END
53 const char* strings[] = {
54 "int get_number(void) { return 42; }\n",
55 "int get_number(void);\n",
56 "kernel void test_kernel(void) { int i = get_number(); }\n",
57 "int get_number(void) { return 0; }\n"
60 #if defined(CL_VERSION_1_2)
61 static cl_program
62 compile_program(cl_context context,
63 cl_uint num_devices, const cl_device_id *device_list,
64 cl_uint count, const char **strings,
65 const char* err_str) {
66 cl_int errNo;
67 cl_program program;
69 /* Create program with source */
70 program = clCreateProgramWithSource(context,
71 count,
72 strings,
73 NULL,
74 &errNo);
75 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
76 fprintf(stderr,
77 "Failed (error code: %s): Create program with source (for the %s).\n",
78 piglit_cl_get_error_name(errNo), err_str);
79 return NULL;
82 /* Compile program */
83 errNo = clCompileProgram(program,
84 num_devices, device_list,
85 " ",
86 0, NULL, NULL,
87 NULL, NULL);
89 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
90 int i;
91 fprintf(stderr, "Failed (error code: %s): Compile program (for the %s).\n",
92 piglit_cl_get_error_name(errNo), err_str);
94 for(i = 0; i < num_devices; ++i) {
95 char *build_log = piglit_cl_get_program_build_info(program, device_list[i], CL_PROGRAM_BUILD_LOG);
96 fprintf(stderr, "Build log:\n%s\n", build_log);
97 free(build_log);
100 clReleaseProgram(program);
101 return NULL;
104 return program;
107 static bool
108 test(cl_context context,
109 cl_uint num_devices, const cl_device_id *device_list,
110 const char *options,
111 cl_uint num_input_programs, const cl_program *input_programs,
112 void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data),
113 void *user_data,
114 cl_program *ret_program,
115 cl_int expected_error, enum piglit_result* result,
116 const char* test_str) {
117 cl_program program;
118 cl_int errNo;
120 program = clLinkProgram(context,
121 num_devices, device_list,
122 options,
123 num_input_programs, input_programs,
124 pfn_notify, user_data,
125 &errNo);
127 if (ret_program) {
128 *ret_program = program;
129 } else {
130 if (program)
131 clReleaseProgram(program);
134 if(!piglit_cl_check_error(errNo, expected_error)) {
135 fprintf(stderr, "Failed (error code: %s): %s.\n",
136 piglit_cl_get_error_name(errNo), test_str);
137 piglit_merge_result(result, PIGLIT_FAIL);
138 return false;
141 return true;
143 #endif
145 enum piglit_result
146 piglit_cl_test(const int argc,
147 const char** argv,
148 const struct piglit_cl_api_test_config* config,
149 const struct piglit_cl_api_test_env* env)
151 #if defined(CL_VERSION_1_2)
152 enum piglit_result result = PIGLIT_PASS;
154 bool linker_available;
155 int i;
156 cl_program_binary_type* binary_type;
157 cl_program compiled_programs[2];
158 cl_program function_prog;
159 cl_program kernel_prog;
160 cl_program linked_prog;
162 linker_available = false;
163 for(i = 0; i < env->context->num_devices; ++i) {
164 cl_bool* dev_linker =
165 piglit_cl_get_device_info(env->context->device_ids[i],
166 CL_DEVICE_LINKER_AVAILABLE);
168 if (*dev_linker)
169 linker_available |= true;
171 free(dev_linker);
174 if (!linker_available)
175 return PIGLIT_SKIP;
177 /* Create compiled program */
178 function_prog = compile_program(env->context->cl_ctx,
179 env->context->num_devices, env->context->device_ids,
180 1, &strings[0],
181 "function program");
182 kernel_prog = compile_program(env->context->cl_ctx,
183 env->context->num_devices, env->context->device_ids,
184 2, &strings[1],
185 "kernel program");
187 if (!function_prog || !kernel_prog) {
188 clReleaseProgram(function_prog);
189 clReleaseProgram(kernel_prog);
190 return PIGLIT_FAIL;
193 compiled_programs[0] = function_prog;
194 compiled_programs[1] = kernel_prog;
196 /*** Normal usage ***/
197 test(env->context->cl_ctx,
198 env->context->num_devices, env->context->device_ids,
199 "-create-library",
200 1, compiled_programs,
201 NULL, NULL,
202 &linked_prog,
203 CL_SUCCESS, &result, "Link program as library");
205 for(i = 0; i < env->context->num_devices; ++i) {
206 binary_type = piglit_cl_get_program_build_info(linked_prog,
207 env->context->device_ids[i],
208 CL_PROGRAM_BINARY_TYPE);
209 if (*binary_type != CL_PROGRAM_BINARY_TYPE_LIBRARY) {
210 piglit_merge_result(&result, PIGLIT_FAIL);
211 fprintf(stderr,
212 "Failed: binary is not of type CL_PROGRAM_BINARY_TYPE_LIBRARY.\n");
214 free(binary_type);
217 clReleaseProgram(linked_prog);
219 test(env->context->cl_ctx,
220 env->context->num_devices, env->context->device_ids,
222 2, compiled_programs,
223 NULL, NULL,
224 &linked_prog,
225 CL_SUCCESS, &result, "Link program as executable");
227 for(i = 0; i < env->context->num_devices; ++i) {
228 binary_type = piglit_cl_get_program_build_info(linked_prog,
229 env->context->device_ids[i],
230 CL_PROGRAM_BINARY_TYPE);
231 if (*binary_type != CL_PROGRAM_BINARY_TYPE_EXECUTABLE) {
232 piglit_merge_result(&result, PIGLIT_FAIL);
233 fprintf(stderr,
234 "Failed: binary is not of type CL_PROGRAM_BINARY_TYPE_EXECUTABLE.\n");
236 free(binary_type);
240 /*** Errors ***/
243 * CL_INVALID_VALUE if device_list is NULL and num_devices is greater than
244 * zero, or if device_list is not NULL and num_devices is zero
246 test(env->context->cl_ctx,
247 env->context->num_devices, NULL,
249 2, compiled_programs,
250 NULL, NULL,
251 NULL,
252 CL_INVALID_VALUE, &result,
253 "Trigger CL_INVALID_VALUE if device_list is NULL and num_devices is greater than zero");
255 test(env->context->cl_ctx,
256 0, env->context->device_ids,
258 2, compiled_programs,
259 NULL, NULL,
260 NULL,
261 CL_INVALID_VALUE, &result,
262 "Trigger CL_INVALID_VALUE if device_list is not NULL and num_devices is zero");
265 * CL_INVALID_VALUE if num_input_programs is zero and input_programs is NULL
266 * or if num_input_programs is zero and input_programs is not NULL
267 * or if num_input_programs is not zero and input_programs is NULL
269 test(env->context->cl_ctx,
270 env->context->num_devices, env->context->device_ids,
272 0, NULL,
273 NULL, NULL,
274 NULL,
275 CL_INVALID_VALUE, &result,
276 "Trigger CL_INVALID_VALUE if num_input_programs is zero and input_programs is NULL");
278 test(env->context->cl_ctx,
279 env->context->num_devices, env->context->device_ids,
281 0, compiled_programs,
282 NULL, NULL,
283 NULL,
284 CL_INVALID_VALUE, &result,
285 "Trigger CL_INVALID_VALUE if num_input_programs is zero and input_programs is not NULL");
287 test(env->context->cl_ctx,
288 env->context->num_devices, env->context->device_ids,
290 2, NULL,
291 NULL, NULL,
292 NULL,
293 CL_INVALID_VALUE, &result,
294 "Trigger CL_INVALID_VALUE if num_input_programs is not zero and input_programs is NULL");
297 * CL_INVALID_PROGRAM if programs specified in input_programs are not valid program objects
302 * CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL.
304 test(env->context->cl_ctx,
305 env->context->num_devices, env->context->device_ids,
307 2, compiled_programs,
308 NULL, &i,
309 NULL,
310 CL_INVALID_VALUE, &result,
311 "Trigger CL_INVALID_VALUE if pfn_notify is NULL but user_data is not NULL");
314 * CL_INVALID_DEVICE if OpenCL devices listed in device_list are not in the
315 * list of devices associated with context
320 * CL_INVALID_LINKER_OPTIONS if the linker options specified by options are
321 * invalid
323 test(env->context->cl_ctx,
324 env->context->num_devices, env->context->device_ids,
325 "-invalid- --link-- options",
326 2, compiled_programs,
327 NULL, NULL,
328 NULL,
329 CL_INVALID_LINKER_OPTIONS, &result,
330 "Trigger CL_INVALID_LINKER_OPTIONS if the linker options specified by options are invalid");
333 * CL_INVALID_OPERATION if the compilation or build of a program executable
334 * for any of the devices listed in device_list by a previous call to
335 * clCompileProgram or clBuildProgram for program has not completed
340 * CL_INVALID_OPERATION if the rules for devices containing compiled binaries
341 * or libraries as described in input_programs argument above are not followed
343 compiled_programs[0] = linked_prog;
344 test(env->context->cl_ctx,
345 env->context->num_devices, env->context->device_ids,
347 2, compiled_programs,
348 NULL, NULL,
349 NULL,
350 CL_INVALID_OPERATION, &result,
351 "Trigger CL_INVALID_OPERATION if the rules for devices containing compiled binaries or libraries as described in input_programs argument above are not followed");
354 * CL_LINKER_NOT_AVAILABLE if a linker is not available
355 * i.e. CL_DEVICE_LINKER_AVAILABLE specified in the table of allowed values
356 * for param_name for clGetDeviceInfo is set to CL_FALSE.
358 for(i = 0; i < env->context->num_devices; ++i) {
359 cl_bool* dev_linker =
360 piglit_cl_get_device_info(env->context->device_ids[i],
361 CL_DEVICE_LINKER_AVAILABLE);
362 if(!(*dev_linker)) {
363 test(env->context->cl_ctx,
364 1, &env->context->device_ids[i],
366 2, compiled_programs,
367 NULL, NULL,
368 NULL,
369 CL_LINKER_NOT_AVAILABLE, &result,
370 "Trigger CL_LINKER_NOT_AVAILABLE if a linker is not available");
372 free(dev_linker);
376 /* Release programs */
377 clReleaseProgram(function_prog);
378 clReleaseProgram(kernel_prog);
379 clReleaseProgram(linked_prog);
382 * CL_LINK_PROGRAM_FAILURE if there is a failure to link the compiled binaries
383 * and/or libraries.
385 function_prog = compile_program(env->context->cl_ctx,
386 env->context->num_devices, env->context->device_ids,
387 1, &strings[0],
388 "2nd function program");
389 kernel_prog = compile_program(env->context->cl_ctx,
390 env->context->num_devices, env->context->device_ids,
391 3, &strings[1],
392 "2nd kernel program");
394 if (!function_prog || !kernel_prog) {
395 result = PIGLIT_FAIL;
396 } else {
397 compiled_programs[0] = function_prog;
398 compiled_programs[1] = kernel_prog;
400 test(env->context->cl_ctx,
401 env->context->num_devices, env->context->device_ids,
403 2, compiled_programs,
404 NULL, NULL,
405 NULL,
406 CL_LINK_PROGRAM_FAILURE, &result,
407 "Trigger CL_LINK_PROGRAM_FAILURE if there is a failure to link the compiled binaries and/or libraries");
410 /* Release programs */
411 clReleaseProgram(function_prog);
412 clReleaseProgram(kernel_prog);
414 return result;
415 #else
416 return PIGLIT_SKIP;
417 #endif