cl: Don't use device_infos if num_device_infos == 0
[piglit.git] / tests / util / piglit-util-cl.c
blob61d5cd067bbef4f88cf36237d6246500dd64a4bf
1 /*
2 * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
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 #include <inttypes.h>
26 #include "piglit-util-cl.h"
28 bool
29 piglit_cl_probe_integer(int64_t value, int64_t expect, uint64_t tolerance)
31 int64_t diff = value > expect ? value-expect : expect-value;
33 if(diff > tolerance) {
34 printf("Expecting %"PRId64" (0x%"PRIx64") with tolerance %"PRIu64
35 ", but got %"PRId64" (0x%"PRIx64")\n",
36 expect, (uint64_t)expect, tolerance, value, (uint64_t)value);
37 return false;
40 return true;
43 bool
44 piglit_cl_probe_uinteger(uint64_t value, uint64_t expect, uint64_t tolerance)
46 uint64_t diff = value > expect ? value-expect : expect-value;
48 if(diff > tolerance) {
49 printf("Expecting %"PRIu64" (0x%"PRIx64") with tolerance %"PRIu64
50 ", but got %"PRIu64" (0x%"PRIx64")\n",
51 expect, expect, tolerance, value, value);
52 return false;
55 return true;
58 # define probe_float_check_nan_inf(value, expect) \
59 ((isnan(value) && isnan(expect)) || \
60 (isinf(value) && isinf(expect) && ((value > 0) == (expect > 0))))
62 static float float_from_cl_half(uint32_t in)
64 union {
65 uint32_t bits;
66 float val;
67 } convert;
68 uint32_t exponent = ((in >> 10) & 0x1f);
69 convert.bits = (((in >> 15) & 0x1) << 31) | //sign
70 ((exponent ? (exponent != 0x1f ? exponent + 112 : 0xff)
71 : 0) << 23) | //exponent (0 and 1f are special cases)
72 (((in >> 0) & 0x3ff) << 13); // mantissa
73 return convert.val;
76 bool piglit_cl_probe_half(cl_half value, cl_half expect, uint32_t ulp)
78 // after conversion to float the last 13 digits are 0, adjust ulp
79 return piglit_cl_probe_floating(float_from_cl_half(value),
80 float_from_cl_half(expect),
81 ulp * 8192);
84 bool piglit_cl_probe_floating(float value, float expect, uint32_t ulp)
86 float diff;
87 union {
88 float f;
89 uint32_t u;
90 } v, e;
92 v.f = value;
93 e.f = expect;
95 /* Treat infinity and nan separately */
96 if (probe_float_check_nan_inf(value, expect)) {
97 return true;
100 /* Check "any value" */
101 if (ulp >= (1u << 24)) {
102 return true;
105 /* expect is correctly rounded, 1 ULP is the distance to next
106 * representable value */
107 float direction = signbit(expect) ? -INFINITY : INFINITY;
108 float one_ulp = nextafterf(expect, direction) - expect;
109 float tolerance = fabsf(ulp * one_ulp);
111 diff = fabsf(value - expect);
113 if (diff > tolerance || isnan(value)) {
114 printf("Expecting %f (0x%x) with tolerance %f (%u ulps), but got %f (0x%x)\n",
115 e.f, e.u, tolerance, ulp, v.f, v.u);
116 return false;
119 return true;
122 bool piglit_cl_probe_double(double value, double expect, uint64_t ulp)
124 double diff;
125 union {
126 double f;
127 uint64_t u;
128 } v, e;
130 v.f = value;
131 e.f = expect;
133 /* Treat infinity and nan separately */
134 if (probe_float_check_nan_inf(value, expect)) {
135 return true;
137 /* Check "any value" */
138 if (ulp >= (1ul << 53)) {
139 return true;
142 double direction = signbit(expect) ? -INFINITY : INFINITY;
143 double one_ulp = nextafter(expect, direction) - expect;
144 double tolerance = fabs(ulp * one_ulp);
146 diff = fabs(value - expect);
148 if(diff > tolerance || isnan(value)) {
149 printf("Expecting %f (0x%" PRIx64") with tolerance %f (%" PRIu64"), but got %f (0x%" PRIx64")\n",
150 e.f, e.u, tolerance, ulp, v.f, v.u);
151 return false;
154 return true;
158 cl_half convert_cl_half(double in)
160 union {
161 uint64_t bits;
162 double val;
163 } convert = { .val = in };
164 /* Bit 63 is sign bit */
165 cl_half sign = (cl_half)((convert.bits >> 63) << 15);
166 /* Get only the top 10 bits of mantissa */
167 cl_half mantissa = (cl_half)((convert.bits >> 42) & 0x3ff);
168 /* 11 bits of exponent */
169 uint64_t exp = (convert.bits >> 52) & 0x7ff;
170 /* 0 and ~0 are special cases that are not adjusted,
171 * half bias is 15, double bias is 1023 */
172 cl_half exponent = ((exp == 0 || exp == 0x7ff) ? (exp & 0x3ff) :
173 (exp - 1008)) << 10;
174 return (sign | exponent | mantissa);
177 bool
178 piglit_cl_check_error(cl_int error, cl_int expected_error)
180 if (error == expected_error) {
181 return true;
185 * If the lookup of the error's name is successful, then print
186 * Unexpected CL error: NAME DEC
187 * Else, print
188 * Unexpected CL error: DEC
190 printf("Unexpected CL error: %s %d\n",
191 piglit_cl_get_error_name(error), error);
193 /* Print the expected error, but only if an error was really expected. */
194 if (expected_error != CL_SUCCESS) {
195 printf("Expected CL error: %s %d\n",
196 piglit_cl_get_error_name(expected_error),
197 expected_error);
200 return false;
203 void
204 piglit_cl_expect_error(cl_int error,
205 cl_int expected_error,
206 enum piglit_result result)
208 if(!piglit_cl_check_error(error, expected_error)) {
209 piglit_report_result(result);
214 piglit_cl_get_platform_version(cl_platform_id platform)
216 char* version_string;
217 const char *version_number_string;
218 int scanf_count;
219 int major;
220 int minor;
223 * Returned format:
224 * OpenCL<space><major_version.minor_version><space><platform-specific information>
226 version_string = piglit_cl_get_platform_info(platform, CL_PLATFORM_VERSION);
228 /* skip to version number */
229 version_number_string = version_string + 6;
231 /* Interpret version number */
232 scanf_count = sscanf(version_number_string, "%i.%i", &major, &minor);
233 if (scanf_count != 2) {
234 printf("Unable to interpret CL_PLATFORM_VERSION string: %s\n",
235 version_string);
236 free(version_string);
237 piglit_report_result(PIGLIT_FAIL);
239 free(version_string);
241 return 10*major+minor;
244 void
245 piglit_cl_require_platform_version(cl_platform_id platform,
246 int required_version_times_10)
248 if (piglit_cl_get_platform_version(platform) < required_version_times_10) {
249 printf("Test requires OpenCL version %g\n",
250 required_version_times_10 / 10.0);
251 piglit_report_result(PIGLIT_SKIP);
256 piglit_cl_get_device_version(cl_device_id device)
258 char* version_string;
259 const char *version_number_string;
260 int scanf_count;
261 int major;
262 int minor;
265 * Returned format:
266 * OpenCL<space><major_version.minor_version><space><platform-specific information>
268 version_string = piglit_cl_get_device_info(device, CL_DEVICE_VERSION);
270 /* skip to version number */
271 version_number_string = version_string + 6;
273 /* Interpret version number */
274 scanf_count = sscanf(version_number_string, "%i.%i", &major, &minor);
275 if (scanf_count != 2) {
276 printf("Unable to interpret CL_DEVICE_VERSION string: %s\n",
277 version_string);
278 free(version_string);
279 piglit_report_result(PIGLIT_FAIL);
281 free(version_string);
283 return 10*major+minor;
286 void
287 piglit_cl_require_device_version(cl_device_id device,
288 int required_version_times_10)
290 if (piglit_cl_get_device_version(device) < required_version_times_10) {
291 printf("Test requires OpenCL version %g\n",
292 required_version_times_10 / 10.0);
293 piglit_report_result(PIGLIT_SKIP);
298 piglit_cl_get_device_cl_c_version(cl_device_id device)
300 char* version_string;
301 const char *version_number_string;
302 int scanf_count;
303 int major;
304 int minor;
306 /* OpenCL 1.0 does not have enum CL_DEVICE_OPENCL_C_VERSION */
307 if(piglit_cl_get_device_version(device) == 10) {
308 return 10;
312 * Returned format:
313 * OpenCL<space>C<space><major_version.minor_version><space><vendor-specific information>
315 version_string = piglit_cl_get_device_info(device,
316 CL_DEVICE_OPENCL_C_VERSION);
318 /* skip to version number */
319 version_number_string = version_string + 8;
321 /* Interpret version number */
322 scanf_count = sscanf(version_number_string, "%i.%i", &major, &minor);
323 if (scanf_count != 2) {
324 printf("Unable to interpret CL_DEVICE_OPENCL_C_VERSION string: %s\n",
325 version_string);
326 free(version_string);
327 piglit_report_result(PIGLIT_FAIL);
329 free(version_string);
331 return 10*major+minor;
334 void
335 piglit_cl_require_device_cl_c_version(cl_device_id device,
336 int required_version_times_10)
338 if (piglit_cl_get_device_cl_c_version(device) < required_version_times_10) {
339 printf("Test requires OpenCL C version %g\n",
340 required_version_times_10 / 10.0);
341 piglit_report_result(PIGLIT_SKIP);
345 struct _program_build_info_args {
346 cl_program program;
347 cl_device_id device;
349 struct _kernel_work_group_info_args {
350 cl_kernel kernel;
351 cl_device_id device;
354 static void*
355 piglit_cl_get_info(void* fn_ptr, void* obj, cl_uint param)
357 cl_int errNo;
358 size_t param_size;
359 void* param_ptr = NULL;
361 /* get param size */
362 if(fn_ptr == clGetPlatformInfo) {
363 errNo = clGetPlatformInfo(*(cl_platform_id*)obj, param, 0, NULL,
364 &param_size);
365 } else if(fn_ptr == clGetDeviceInfo) {
366 errNo = clGetDeviceInfo(*(cl_device_id*)obj, param, 0, NULL,
367 &param_size);
368 } else if(fn_ptr == clGetContextInfo) {
369 errNo = clGetContextInfo(*(cl_context*)obj, param, 0, NULL,
370 &param_size);
371 } else if(fn_ptr == clGetCommandQueueInfo) {
372 errNo = clGetCommandQueueInfo(*(cl_command_queue*)obj, param, 0, NULL,
373 &param_size);
374 } else if(fn_ptr == clGetMemObjectInfo) {
375 errNo = clGetMemObjectInfo(*(cl_mem*)obj, param, 0, NULL,
376 &param_size);
377 } else if(fn_ptr == clGetImageInfo) {
378 errNo = clGetImageInfo(*(cl_mem*)obj, param, 0, NULL,
379 &param_size);
380 } else if(fn_ptr == clGetSamplerInfo) {
381 errNo = clGetSamplerInfo(*(cl_sampler*)obj, param, 0, NULL,
382 &param_size);
383 } else if(fn_ptr == clGetProgramInfo) {
384 errNo = clGetProgramInfo(*(cl_program*)obj, param, 0, NULL,
385 &param_size);
386 } else if(fn_ptr == clGetProgramBuildInfo) {
387 errNo = clGetProgramBuildInfo(((struct _program_build_info_args*)obj)->program,
388 ((struct _program_build_info_args*)obj)->device,
389 param, 0, NULL, &param_size);
390 } else if(fn_ptr == clGetKernelInfo) {
391 errNo = clGetKernelInfo(*(cl_kernel*)obj, param, 0, NULL,
392 &param_size);
393 } else if(fn_ptr == clGetKernelWorkGroupInfo) {
394 errNo = clGetKernelWorkGroupInfo(((struct _kernel_work_group_info_args*)obj)->kernel,
395 ((struct _kernel_work_group_info_args*)obj)->device,
396 param, 0, NULL, &param_size);
397 } else if(fn_ptr == clGetEventInfo) {
398 errNo = clGetEventInfo(*(cl_event*)obj, param, 0, NULL,
399 &param_size);
400 } else if(fn_ptr == clGetEventProfilingInfo) {
401 errNo = clGetEventProfilingInfo(*(cl_event*)obj, param, 0, NULL,
402 &param_size);
403 } else {
404 fprintf(stderr,
405 "Trying to get %s information from undefined function.\n",
406 piglit_cl_get_enum_name(param));
407 piglit_report_result(PIGLIT_FAIL);
410 if(errNo == CL_SUCCESS) {
411 param_ptr = calloc(param_size, sizeof(char));
413 /* retrieve param */
414 if(fn_ptr == clGetPlatformInfo) {
415 errNo = clGetPlatformInfo(*(cl_platform_id*)obj, param,
416 param_size, param_ptr, NULL);
417 } else if(fn_ptr == clGetDeviceInfo) {
418 errNo = clGetDeviceInfo(*(cl_device_id*)obj, param,
419 param_size, param_ptr, NULL);
420 } else if(fn_ptr == clGetContextInfo) {
421 errNo = clGetContextInfo(*(cl_context*)obj, param,
422 param_size, param_ptr, NULL);
423 } else if(fn_ptr == clGetCommandQueueInfo) {
424 errNo = clGetCommandQueueInfo(*(cl_command_queue*)obj,
425 param, param_size, param_ptr, NULL);
426 } else if(fn_ptr == clGetMemObjectInfo) {
427 errNo = clGetMemObjectInfo(*(cl_mem*)obj, param,
428 param_size, param_ptr, NULL);
429 } else if(fn_ptr == clGetImageInfo) {
430 errNo = clGetImageInfo(*(cl_mem*)obj, param,
431 param_size, param_ptr, NULL);
432 } else if(fn_ptr == clGetSamplerInfo) {
433 errNo = clGetSamplerInfo(*(cl_sampler*)obj, param,
434 param_size, param_ptr, NULL);
435 } else if(fn_ptr == clGetProgramInfo) {
436 errNo = clGetProgramInfo(*(cl_program*)obj, param,
437 param_size, param_ptr, NULL);
438 } else if(fn_ptr == clGetProgramBuildInfo) {
439 errNo = clGetProgramBuildInfo(((struct _program_build_info_args*)obj)->program,
440 ((struct _program_build_info_args*)obj)->device,
441 param, param_size, param_ptr, NULL);
442 } else if(fn_ptr == clGetKernelInfo) {
443 errNo = clGetKernelInfo(*(cl_kernel*)obj, param,
444 param_size, param_ptr, NULL);
445 } else if(fn_ptr == clGetKernelWorkGroupInfo) {
446 errNo = clGetKernelWorkGroupInfo(((struct _kernel_work_group_info_args*)obj)->kernel,
447 ((struct _kernel_work_group_info_args*)obj)->device,
448 param, param_size, param_ptr, NULL);
449 } else if(fn_ptr == clGetEventInfo) {
450 errNo = clGetEventInfo(*(cl_event*)obj, param,
451 param_size, param_ptr, NULL);
452 } else if(fn_ptr == clGetEventProfilingInfo) {
453 errNo = clGetEventProfilingInfo(*(cl_event*)obj, param,
454 param_size, param_ptr, NULL);
457 if(errNo != CL_SUCCESS) {
458 free(param_ptr);
459 param_ptr = NULL;
463 if(param_ptr == NULL) {
464 fprintf(stderr,
465 "Unable to get %s information (Error: %s)\n",
466 piglit_cl_get_enum_name(param),
467 piglit_cl_get_error_name(errNo));
468 piglit_report_result(PIGLIT_FAIL);
471 return param_ptr;
474 void*
475 piglit_cl_get_platform_info(cl_platform_id platform, cl_platform_info param) {
476 return piglit_cl_get_info(clGetPlatformInfo, &platform, param);
479 void*
480 piglit_cl_get_device_info(cl_device_id device, cl_device_info param) {
481 return piglit_cl_get_info(clGetDeviceInfo, &device, param);
484 void*
485 piglit_cl_get_context_info(cl_context context, cl_context_info param) {
486 return piglit_cl_get_info(clGetContextInfo, &context, param);
489 void*
490 piglit_cl_get_command_queue_info(cl_command_queue command_queue,
491 cl_command_queue_info param) {
492 return piglit_cl_get_info(clGetCommandQueueInfo, &command_queue, param);
495 void*
496 piglit_cl_get_mem_object_info(cl_mem mem_obj, cl_mem_info param) {
497 return piglit_cl_get_info(clGetMemObjectInfo, &mem_obj, param);
500 void*
501 piglit_cl_get_image_info(cl_mem image, cl_image_info param) {
502 return piglit_cl_get_info(clGetImageInfo, &image, param);
505 void*
506 piglit_cl_get_sampler_info(cl_sampler sampler, cl_sampler_info param) {
507 return piglit_cl_get_info(clGetSamplerInfo, &sampler, param);
510 void*
511 piglit_cl_get_program_info(cl_program program, cl_program_info param) {
512 return piglit_cl_get_info(clGetProgramInfo, &program, param);
515 void*
516 piglit_cl_get_program_build_info(cl_program program, cl_device_id device,
517 cl_program_build_info param) {
518 struct _program_build_info_args args = {
519 .program = program,
520 .device = device
523 return piglit_cl_get_info(clGetProgramBuildInfo, &args, param);
526 void*
527 piglit_cl_get_kernel_info(cl_kernel kernel, cl_mem_info param) {
528 return piglit_cl_get_info(clGetKernelInfo, &kernel, param);
531 void*
532 piglit_cl_get_kernel_work_group_info(cl_kernel kernel, cl_device_id device,
533 cl_mem_info param) {
534 struct _kernel_work_group_info_args args = {
535 .kernel = kernel,
536 .device = device
539 return piglit_cl_get_info(clGetKernelWorkGroupInfo, &args, param);
542 void*
543 piglit_cl_get_event_info(cl_event event, cl_event_info param) {
544 return piglit_cl_get_info(clGetEventInfo, &event, param);
547 void*
548 piglit_cl_get_event_profiling_info(cl_event event, cl_profiling_info param) {
549 return piglit_cl_get_info(clGetEventProfilingInfo, &event, param);
552 bool
553 piglit_cl_is_platform_extension_supported(cl_platform_id platform,
554 const char *name)
556 char* extensions = piglit_cl_get_platform_info(platform,
557 CL_PLATFORM_EXTENSIONS);
558 bool supported = piglit_is_extension_in_string(extensions, name);
560 free(extensions);
562 return supported;
565 void
566 piglit_cl_require_platform_extension(cl_platform_id platform, const char *name)
568 if (!piglit_cl_is_platform_extension_supported(platform, name)) {
569 printf("Test requires %s platform extension\n", name);
570 piglit_report_result(PIGLIT_SKIP);
574 void
575 piglit_cl_require_not_platform_extension(cl_platform_id platform,
576 const char *name)
578 if (piglit_cl_is_platform_extension_supported(platform, name)) {
579 printf("Test requires absence of %s\n platform extension\n", name);
580 piglit_report_result(PIGLIT_SKIP);
584 bool
585 piglit_cl_is_device_extension_supported(cl_device_id device, const char *name)
587 char* extensions = piglit_cl_get_device_info(device, CL_DEVICE_EXTENSIONS);
588 bool supported = piglit_is_extension_in_string(extensions, name);
590 free(extensions);
592 return supported;
595 void
596 piglit_cl_require_device_extension(cl_device_id device, const char *name)
598 if (!piglit_cl_is_device_extension_supported(device, name)) {
599 printf("Test requires %s device extension\n", name);
600 piglit_report_result(PIGLIT_SKIP);
604 void
605 piglit_cl_require_not_device_extension(cl_device_id device, const char *name)
607 if (piglit_cl_is_device_extension_supported(device, name)) {
608 printf("Test requires absence of %s device extension\n", name);
609 piglit_report_result(PIGLIT_SKIP);
613 unsigned int
614 piglit_cl_get_platform_ids(cl_platform_id** platform_ids)
616 cl_int errNo;
617 cl_uint num_platform_ids;
619 /* get number of platforms */
620 errNo = clGetPlatformIDs(0, NULL, &num_platform_ids);
621 if(errNo != CL_SUCCESS) {
622 fprintf(stderr,
623 "Could not get number of platforms: %s\n",
624 piglit_cl_get_error_name(errNo));
625 return 0;
628 /* get platform list */
629 if(platform_ids != NULL && num_platform_ids > 0) {
630 *platform_ids = malloc(num_platform_ids * sizeof(cl_platform_id));
631 errNo = clGetPlatformIDs(num_platform_ids, *platform_ids, NULL);
632 if(errNo != CL_SUCCESS) {
633 free(platform_ids);
634 *platform_ids = malloc(0);
635 fprintf(stderr,
636 "Could not get get platform list: %s\n",
637 piglit_cl_get_error_name(errNo));
638 return 0;
642 return num_platform_ids;
645 unsigned int
646 piglit_cl_get_device_ids(cl_platform_id platform_id, cl_device_type device_type,
647 cl_device_id** device_ids)
649 cl_int errNo;
650 cl_uint num_device_ids;
651 cl_uint num_platform_ids;
652 cl_platform_id *platform_ids;
653 int i;
655 /* get platform_ids */
656 num_platform_ids = piglit_cl_get_platform_ids(&platform_ids);
658 /* find the right platform */
659 for(i = 0; i < num_platform_ids; i++) {
660 if(platform_ids[i] == platform_id) {
661 /* get number of devices */
662 errNo = clGetDeviceIDs(platform_id,
663 device_type,
665 NULL,
666 &num_device_ids);
667 if(errNo == CL_DEVICE_NOT_FOUND) {
668 *device_ids = malloc(0);
669 goto fail;
671 if(errNo != CL_SUCCESS) {
672 *device_ids = malloc(0);
673 fprintf(stderr,
674 "Could not get number of devices: %s\n",
675 piglit_cl_get_error_name(errNo));
676 goto fail;
679 /* get device list */
680 if(device_ids != NULL && num_device_ids > 0) {
681 *device_ids = malloc(num_device_ids * sizeof(cl_device_id));
682 errNo = clGetDeviceIDs(platform_id,
683 CL_DEVICE_TYPE_ALL,
684 num_device_ids,
685 *device_ids,
686 NULL);
687 if(errNo != CL_SUCCESS) {
688 free(device_ids);
689 *device_ids = malloc(0);
690 fprintf(stderr,
691 "Could not get get device list: %s\n",
692 piglit_cl_get_error_name(errNo));
693 goto fail;
697 free(platform_ids);
699 return num_device_ids;
703 /* received invalid platform_id */
704 fprintf(stderr, "Trying to get a device from invalid platform_id\n");
706 *device_ids = malloc(0);
708 fail:
709 free(platform_ids);
710 return 0;
713 piglit_cl_context
714 piglit_cl_create_context(cl_platform_id platform_id,
715 const cl_device_id device_ids[],
716 unsigned int num_devices)
718 piglit_cl_context context = malloc(sizeof(struct _piglit_cl_context));
720 int i;
721 cl_int errNo;
722 cl_context_properties cl_ctx_properties[] = {
723 CL_CONTEXT_PLATFORM, (cl_context_properties)platform_id,
727 /* assign platform */
728 context->platform_id = platform_id;
730 /* assign devices */
731 context->num_devices = num_devices;
732 context->device_ids = malloc(num_devices * sizeof(cl_device_id));
733 memcpy(context->device_ids, device_ids, num_devices * sizeof(cl_device_id));
735 /* create and assign context */
736 context->cl_ctx = clCreateContext(cl_ctx_properties,
737 context->num_devices,
738 context->device_ids,
739 NULL,
740 NULL,
741 &errNo);
742 if(errNo != CL_SUCCESS) {
743 free(context->device_ids);
744 free(context);
745 fprintf(stderr,
746 "Could not create context: %s\n",
747 piglit_cl_get_error_name(errNo));
748 return NULL;
751 /* create and assign command queues */
752 context->command_queues = malloc(num_devices * sizeof(cl_command_queue));
753 for(i = 0; i < num_devices; i++) {
754 context->command_queues[i] = clCreateCommandQueue(context->cl_ctx,
755 context->device_ids[i],
757 &errNo);
758 if(errNo != CL_SUCCESS) {
759 clReleaseContext(context->cl_ctx);
760 free(context->device_ids);
761 free(context->command_queues);
762 free(context);
763 fprintf(stderr,
764 "Could not create command queue: %s\n",
765 piglit_cl_get_error_name(errNo));
766 return NULL;
770 return context;
773 void
774 piglit_cl_release_context(piglit_cl_context context)
776 int i;
778 if(context == NULL) {
779 return;
782 /* release command queues */
783 for(i = 0; i < context->num_devices; i++) {
784 if(clReleaseCommandQueue(context->command_queues[i]) != CL_SUCCESS) {
785 printf("Command queue already released\n");
789 /* release context */
790 if(clReleaseContext(context->cl_ctx) != CL_SUCCESS) {
791 printf("Context already released\n");
794 /* free memory */
795 free(context->device_ids);
796 free(context->command_queues);
797 free(context);
800 cl_program
801 piglit_cl_build_program_with_source_extended(piglit_cl_context context,
802 cl_uint count, char** strings,
803 const char* options, bool fail)
805 cl_int errNo;
806 cl_program program;
808 program = clCreateProgramWithSource(context->cl_ctx,
809 count,
810 (const char**)strings,
811 NULL,
812 &errNo);
813 if(errNo != CL_SUCCESS) {
814 fprintf(stderr,
815 "Could not create program with source: %s\n",
816 piglit_cl_get_error_name(errNo));
817 return NULL;
820 errNo = clBuildProgram(program,
821 context->num_devices,
822 context->device_ids,
823 options,
824 NULL,
825 NULL);
826 if( (!fail && errNo != CL_SUCCESS)
827 || ( fail && errNo == CL_SUCCESS)) {
828 int i;
830 fprintf(stderr,
831 !fail ? "Could not build program: %s\n"
832 : "Program built when it should have failed: %s\n",
833 piglit_cl_get_error_name(errNo));
835 /*printf("Build log for source:\n");
836 for(i = 0; i < count; i++) {
837 printf("%s\n", strings[i]);
840 for(i = 0; i < context->num_devices; i++) {
841 char* device_name = piglit_cl_get_device_info(context->device_ids[i],
842 CL_DEVICE_NAME);
843 char* log = piglit_cl_get_program_build_info(program,
844 context->device_ids[i],
845 CL_PROGRAM_BUILD_LOG);
847 printf("Build log for device %s:\n -------- \n%s\n -------- \n",
848 device_name,
849 log);
851 free(device_name);
852 free(log);
855 clReleaseProgram(program);
856 return NULL;
859 return program;
862 cl_program
863 piglit_cl_build_program_with_source(piglit_cl_context context, cl_uint count,
864 char** strings, const char* options)
866 return piglit_cl_build_program_with_source_extended(context, count, strings, options, false);
869 cl_program
870 piglit_cl_fail_build_program_with_source(piglit_cl_context context,
871 cl_uint count, char** strings,
872 const char* options)
874 return piglit_cl_build_program_with_source_extended(context, count, strings, options, true);
877 cl_program
878 piglit_cl_build_program_with_binary_extended(piglit_cl_context context,
879 size_t* lengths,
880 unsigned char** binaries,
881 const char* options, bool fail)
883 cl_int errNo;
884 cl_program program;
886 cl_int* binary_status = malloc(sizeof(cl_int) * context->num_devices);
888 program = clCreateProgramWithBinary(context->cl_ctx,
889 context->num_devices,
890 context->device_ids,
891 lengths,
892 (const unsigned char**)binaries,
893 binary_status,
894 &errNo);
895 if(errNo != CL_SUCCESS) {
896 int i;
898 fprintf(stderr,
899 "Could not create program with binary: %s\n",
900 piglit_cl_get_error_name(errNo));
902 printf("Create error with binaries:\n");
903 for(i = 0; i < context->num_devices; i++) {
904 char* device_name = piglit_cl_get_device_info(context->device_ids[i],
905 CL_DEVICE_NAME);
907 printf("Error for %s: %s\n",
908 device_name,
909 piglit_cl_get_error_name(binary_status[i]));
911 free(device_name);
914 free(binary_status);
915 return NULL;
917 free(binary_status);
919 errNo = clBuildProgram(program,
920 context->num_devices,
921 context->device_ids,
922 options,
923 NULL,
924 NULL);
925 if( (!fail && errNo != CL_SUCCESS)
926 || ( fail && errNo == CL_SUCCESS)) {
927 int i;
929 fprintf(stderr,
930 !fail ? "Could not build program: %s\n"
931 : "Program built when it should have failed: %s\n",
932 piglit_cl_get_error_name(errNo));
934 printf("Build log for binaries.\n");
936 for(i = 0; i < context->num_devices; i++) {
937 char* device_name = piglit_cl_get_device_info(context->device_ids[i],
938 CL_DEVICE_NAME);
939 char* log = piglit_cl_get_program_build_info(program,
940 context->device_ids[i],
941 CL_PROGRAM_BUILD_LOG);
943 printf("Build log for device %s:\n -------- \n%s\n -------- \n",
944 device_name,
945 log);
947 free(device_name);
948 free(log);
951 clReleaseProgram(program);
952 return NULL;
955 return program;
958 cl_program
959 piglit_cl_build_program_with_binary(piglit_cl_context context, size_t* lengths,
960 unsigned char** binaries,
961 const char* options)
963 return piglit_cl_build_program_with_binary_extended(context, lengths,
964 binaries, options,
965 false);
968 cl_program
969 piglit_cl_fail_build_program_with_binary(piglit_cl_context context,
970 size_t* lengths,
971 unsigned char** binaries,
972 const char* options)
974 return piglit_cl_build_program_with_binary_extended(context, lengths,
975 binaries, options,
976 true);
979 cl_mem
980 piglit_cl_create_buffer(piglit_cl_context context, cl_mem_flags flags,
981 size_t size)
983 cl_int errNo;
984 cl_mem buffer;
986 buffer = clCreateBuffer(context->cl_ctx, flags, size, NULL, &errNo);
987 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
988 fprintf(stderr,
989 "Could not create buffer: %s\n",
990 piglit_cl_get_error_name(errNo));
993 return buffer;
996 bool
997 piglit_cl_write_buffer(cl_command_queue command_queue, cl_mem buffer,
998 size_t offset, size_t cb, const void *ptr)
1000 cl_int errNo;
1002 errNo = clEnqueueWriteBuffer(command_queue, buffer, CL_TRUE, offset, cb,
1003 ptr, 0, NULL, NULL);
1004 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1005 fprintf(stderr,
1006 "Could not enqueue buffer write: %s\n",
1007 piglit_cl_get_error_name(errNo));
1008 return false;
1011 return true;
1014 bool
1015 piglit_cl_write_whole_buffer(cl_command_queue command_queue, cl_mem buffer,
1016 const void *ptr)
1018 bool success;
1019 size_t* buffer_size;
1021 buffer_size = piglit_cl_get_mem_object_info(buffer, CL_MEM_SIZE);
1022 success = piglit_cl_write_buffer(command_queue, buffer, 0, *buffer_size,
1023 ptr);
1024 free(buffer_size);
1026 return success;
1029 bool
1030 piglit_cl_read_buffer(cl_command_queue command_queue, cl_mem buffer,
1031 size_t offset, size_t cb, void *ptr)
1033 cl_int errNo;
1035 errNo = clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, offset, cb, ptr,
1036 0, NULL, NULL);
1037 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1038 fprintf(stderr,
1039 "Could not enqueue buffer read: %s\n",
1040 piglit_cl_get_error_name(errNo));
1041 return false;
1044 return true;
1047 bool
1048 piglit_cl_read_whole_buffer(cl_command_queue command_queue, cl_mem buffer,
1049 void *ptr)
1051 bool success;
1052 size_t* buffer_size;
1054 buffer_size = piglit_cl_get_mem_object_info(buffer, CL_MEM_SIZE);
1055 success = piglit_cl_read_buffer(command_queue, buffer, 0, *buffer_size,
1056 ptr);
1057 free(buffer_size);
1059 return success;
1062 bool
1063 piglit_cl_get_context_image_support(const piglit_cl_context context)
1065 bool ret = false;
1067 unsigned i;
1068 for(i = 0; i < context->num_devices; i++)
1069 ret |= piglit_cl_get_device_image_support(context->device_ids[i]);
1071 return ret;
1074 bool
1075 piglit_cl_get_device_image_support(cl_device_id device)
1077 bool ret = false;
1079 cl_bool *image_support =
1080 piglit_cl_get_device_info(device, CL_DEVICE_IMAGE_SUPPORT);
1082 if (image_support)
1083 ret = *image_support;
1085 free(image_support);
1087 return ret;
1090 cl_mem
1091 piglit_cl_create_image(piglit_cl_context context, cl_mem_flags flags,
1092 const cl_image_format *format,
1093 const piglit_image_desc *desc)
1095 cl_int errNo;
1096 cl_mem image = NULL;
1098 #ifdef CL_VERSION_1_2
1099 if (piglit_cl_get_platform_version(context->platform_id) >= 12) {
1100 image = clCreateImage(context->cl_ctx, flags, format, desc, NULL, &errNo);
1101 } else
1102 #endif
1103 if (desc->image_type == CL_MEM_OBJECT_IMAGE2D) {
1104 image = clCreateImage2D(context->cl_ctx, flags, format,
1105 desc->image_width, desc->image_height, 0,
1106 NULL, &errNo);
1107 } else if (desc->image_type == CL_MEM_OBJECT_IMAGE3D) {
1108 image = clCreateImage3D(context->cl_ctx, flags, format,
1109 desc->image_width, desc->image_height,
1110 desc->image_depth, 0, 0,
1111 NULL, &errNo);
1112 } else {
1113 errNo = CL_INVALID_OPERATION;
1114 fprintf(stderr,
1115 "Invalid image mem object type: %s\n",
1116 piglit_cl_get_enum_name(desc->image_type));
1118 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1119 fprintf(stderr,
1120 "Could not create image: %s\n",
1121 piglit_cl_get_error_name(errNo));
1124 return image;
1127 bool
1128 piglit_cl_write_image(cl_command_queue command_queue, cl_mem image,
1129 const size_t *origin, const size_t *region,
1130 const void *ptr)
1132 cl_int errNo;
1134 errNo = clEnqueueWriteImage(command_queue, image, CL_TRUE, origin, region,
1135 0, 0, ptr, 0, NULL, NULL);
1136 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1137 fprintf(stderr,
1138 "Could not enqueue image write: %s\n",
1139 piglit_cl_get_error_name(errNo));
1140 return false;
1143 return true;
1146 static void
1147 piglit_get_image_region(cl_mem image, size_t *region)
1149 size_t *p = NULL;
1150 cl_mem_object_type *type;
1152 type = piglit_cl_get_mem_object_info(image, CL_MEM_TYPE);
1154 p = piglit_cl_get_image_info(image, CL_IMAGE_WIDTH);
1155 region[0] = *p;
1156 free(p);
1158 switch (*type) {
1159 #ifdef CL_VERSION_1_2
1160 case CL_MEM_OBJECT_IMAGE1D_ARRAY:
1161 p = piglit_cl_get_image_info(image, CL_IMAGE_ARRAY_SIZE);
1162 region[1] = *p;
1163 free(p);
1164 region[2] = 1;
1165 break;
1166 case CL_MEM_OBJECT_IMAGE1D:
1167 case CL_MEM_OBJECT_IMAGE1D_BUFFER:
1168 region[1] = 1;
1169 region[2] = 1;
1170 break;
1171 case CL_MEM_OBJECT_IMAGE2D_ARRAY:
1172 p = piglit_cl_get_image_info(image, CL_IMAGE_HEIGHT);
1173 region[1] = *p;
1174 free(p);
1175 p = piglit_cl_get_image_info(image, CL_IMAGE_ARRAY_SIZE);
1176 region[2] = *p;
1177 free(p);
1178 break;
1179 #endif
1180 case CL_MEM_OBJECT_IMAGE2D:
1181 p = piglit_cl_get_image_info(image, CL_IMAGE_HEIGHT);
1182 region[1] = *p;
1183 free(p);
1184 region[2] = 1;
1185 break;
1186 case CL_MEM_OBJECT_IMAGE3D:
1187 p = piglit_cl_get_image_info(image, CL_IMAGE_HEIGHT);
1188 region[1] = *p;
1189 free(p);
1190 p = piglit_cl_get_image_info(image, CL_IMAGE_DEPTH);
1191 region[2] = *p;
1192 free(p);
1193 break;
1196 free(type);
1199 bool
1200 piglit_cl_write_whole_image(cl_command_queue command_queue, cl_mem image,
1201 const void *ptr)
1203 bool success;
1204 size_t origin[3], region[3];
1206 memset(origin, 0, sizeof(origin));
1207 piglit_get_image_region(image, region);
1208 success = piglit_cl_write_image(command_queue, image, origin, region, ptr);
1210 return success;
1213 bool
1214 piglit_cl_read_image(cl_command_queue command_queue, cl_mem image,
1215 const size_t *origin, const size_t *region,
1216 void *ptr)
1218 cl_int errNo;
1220 errNo = clEnqueueReadImage(command_queue, image, CL_TRUE, origin, region,
1221 0, 0, ptr, 0, NULL, NULL);
1222 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1223 fprintf(stderr,
1224 "Could not enqueue image read: %s\n",
1225 piglit_cl_get_error_name(errNo));
1226 return false;
1229 return true;
1232 bool
1233 piglit_cl_read_whole_image(cl_command_queue command_queue, cl_mem image,
1234 void *ptr)
1236 bool success;
1237 size_t origin[3], region[3];
1239 memset(origin, 0, sizeof(origin));
1240 piglit_get_image_region(image, region);
1241 success = piglit_cl_read_image(command_queue, image, origin, region, ptr);
1243 return success;
1246 cl_kernel
1247 piglit_cl_create_kernel(cl_program program, const char* kernel_name)
1249 cl_int errNo;
1250 cl_kernel kernel;
1252 kernel = clCreateKernel(program, kernel_name, &errNo);
1253 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1254 fprintf(stderr,
1255 "Could not create kernel %s: %s\n",
1256 kernel_name,
1257 piglit_cl_get_error_name(errNo));
1260 return kernel;
1263 cl_sampler
1264 piglit_cl_create_sampler(piglit_cl_context context,
1265 cl_bool normalized_coords,
1266 cl_addressing_mode addressing_mode,
1267 cl_filter_mode filter_mode)
1269 cl_int errNo;
1270 cl_sampler sampler;
1272 sampler = clCreateSampler(context->cl_ctx, normalized_coords,
1273 addressing_mode, filter_mode, &errNo);
1274 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1275 fprintf(stderr,
1276 "Could not create sampler: %s\n",
1277 piglit_cl_get_error_name(errNo));
1280 return sampler;
1283 bool
1284 piglit_cl_set_kernel_arg(cl_kernel kernel, cl_uint arg_index, size_t size,
1285 const void* arg_value)
1287 cl_int errNo;
1289 errNo = clSetKernelArg(kernel, arg_index, size, arg_value);
1290 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1291 fprintf(stderr,
1292 "Could not set kernel argument %u: %s\n",
1293 arg_index,
1294 piglit_cl_get_error_name(errNo));
1295 return false;
1298 return true;
1301 bool
1302 piglit_cl_set_kernel_buffer_arg(cl_kernel kernel, cl_uint arg_index,
1303 cl_mem *buffer)
1305 bool success;
1307 success = piglit_cl_set_kernel_arg(kernel, arg_index, sizeof(cl_mem),
1308 buffer);
1309 if(!success) {
1310 fprintf(stderr,
1311 "Could not set kernel buffer argument %u\n",
1312 arg_index);
1313 return false;
1316 return success;
1319 bool
1320 piglit_cl_enqueue_ND_range_kernel(cl_command_queue command_queue,
1321 cl_kernel kernel, cl_uint work_dim,
1322 const size_t* global_offset,
1323 const size_t* global_work_size,
1324 const size_t* local_work_size,
1325 cl_event *ev)
1327 cl_int errNo;
1329 errNo = clEnqueueNDRangeKernel(command_queue, kernel, work_dim,
1330 global_offset, global_work_size,
1331 local_work_size, 0, NULL, ev);
1332 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1333 fprintf(stderr,
1334 "Could not enqueue ND range kernel: %s\n",
1335 piglit_cl_get_error_name(errNo));
1336 return false;
1339 return true;
1342 bool
1343 piglit_cl_execute_ND_range_kernel(cl_command_queue command_queue,
1344 cl_kernel kernel, cl_uint work_dim,
1345 const size_t* global_offset,
1346 const size_t* global_work_size,
1347 const size_t* local_work_size)
1349 int errNo;
1350 cl_event ev;
1352 if(!piglit_cl_enqueue_ND_range_kernel(command_queue,
1353 kernel,
1354 work_dim,
1355 global_offset,
1356 global_work_size,
1357 local_work_size,
1358 &ev)) {
1359 return false;
1362 errNo = clWaitForEvents(1, &ev);
1363 clReleaseEvent(ev);
1365 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1366 fprintf(stderr,
1367 "Could not wait for kernel to finish: %s\n",
1368 piglit_cl_get_error_name(errNo));
1369 return false;
1372 return true;
1375 bool
1376 piglit_cl_enqueue_task(cl_command_queue command_queue, cl_kernel kernel)
1378 cl_int errNo;
1380 errNo = clEnqueueTask(command_queue, kernel,
1381 0, NULL, NULL);
1382 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1383 fprintf(stderr,
1384 "Could not enqueue task: %s\n",
1385 piglit_cl_get_error_name(errNo));
1386 return false;
1389 return true;
1392 bool
1393 piglit_cl_execute_task(cl_command_queue command_queue, cl_kernel kernel)
1395 int errNo;
1397 if(!piglit_cl_enqueue_task(command_queue,
1398 kernel)) {
1399 return false;
1402 errNo = clFinish(command_queue);
1403 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1404 fprintf(stderr,
1405 "Could not wait for kernel to finish: %s\n",
1406 piglit_cl_get_error_name(errNo));
1407 return false;
1410 return true;