glx-multithread-texture: Avoid front-buffer rendering.
[piglit.git] / tests / util / piglit-util-cl.c
blob42a5e72f92c64b774a27072ebdb5ef9ea2176730
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 (%lu ulps), 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 return 0;
671 if(errNo != CL_SUCCESS) {
672 free(platform_ids);
673 *device_ids = malloc(0);
674 fprintf(stderr,
675 "Could not get number of devices: %s\n",
676 piglit_cl_get_error_name(errNo));
677 return 0;
680 /* get device list */
681 if(device_ids != NULL && num_device_ids > 0) {
682 *device_ids = malloc(num_device_ids * sizeof(cl_device_id));
683 errNo = clGetDeviceIDs(platform_id,
684 CL_DEVICE_TYPE_ALL,
685 num_device_ids,
686 *device_ids,
687 NULL);
688 if(errNo != CL_SUCCESS) {
689 free(platform_ids);
690 free(device_ids);
691 *device_ids = malloc(0);
692 fprintf(stderr,
693 "Could not get get device list: %s\n",
694 piglit_cl_get_error_name(errNo));
695 return 0;
699 free(platform_ids);
701 return num_device_ids;
705 free(platform_ids);
707 /* received invalid platform_id */
708 fprintf(stderr, "Trying to get a device from invalid platform_id\n");
710 *device_ids = malloc(0);
711 return 0;
714 piglit_cl_context
715 piglit_cl_create_context(cl_platform_id platform_id,
716 const cl_device_id device_ids[],
717 unsigned int num_devices)
719 piglit_cl_context context = malloc(sizeof(struct _piglit_cl_context));
721 int i;
722 cl_int errNo;
723 cl_context_properties cl_ctx_properties[] = {
724 CL_CONTEXT_PLATFORM, (cl_context_properties)platform_id,
728 /* assign platform */
729 context->platform_id = platform_id;
731 /* assign devices */
732 context->num_devices = num_devices;
733 context->device_ids = malloc(num_devices * sizeof(cl_device_id));
734 memcpy(context->device_ids, device_ids, num_devices * sizeof(cl_device_id));
736 /* create and assign context */
737 context->cl_ctx = clCreateContext(cl_ctx_properties,
738 context->num_devices,
739 context->device_ids,
740 NULL,
741 NULL,
742 &errNo);
743 if(errNo != CL_SUCCESS) {
744 free(context->device_ids);
745 free(context);
746 fprintf(stderr,
747 "Could not create context: %s\n",
748 piglit_cl_get_error_name(errNo));
749 return NULL;
752 /* create and assing command queues */
753 context->command_queues = malloc(num_devices * sizeof(cl_command_queue));
754 for(i = 0; i < num_devices; i++) {
755 context->command_queues[i] = clCreateCommandQueue(context->cl_ctx,
756 context->device_ids[i],
758 &errNo);
759 if(errNo != CL_SUCCESS) {
760 clReleaseContext(context->cl_ctx);
761 free(context->device_ids);
762 free(context->command_queues);
763 free(context);
764 fprintf(stderr,
765 "Could not create command queue: %s\n",
766 piglit_cl_get_error_name(errNo));
767 return NULL;
771 return context;
774 void
775 piglit_cl_release_context(piglit_cl_context context)
777 int i;
779 if(context == NULL) {
780 return;
783 /* release command queues */
784 for(i = 0; i < context->num_devices; i++) {
785 if(clReleaseCommandQueue(context->command_queues[i]) != CL_SUCCESS) {
786 printf("Command queue already released\n");
790 /* release context */
791 if(clReleaseContext(context->cl_ctx) != CL_SUCCESS) {
792 printf("Context already released\n");
795 /* free memory */
796 free(context->device_ids);
797 free(context->command_queues);
798 free(context);
801 cl_program
802 piglit_cl_build_program_with_source_extended(piglit_cl_context context,
803 cl_uint count, char** strings,
804 const char* options, bool fail)
806 cl_int errNo;
807 cl_program program;
809 program = clCreateProgramWithSource(context->cl_ctx,
810 count,
811 (const char**)strings,
812 NULL,
813 &errNo);
814 if(errNo != CL_SUCCESS) {
815 fprintf(stderr,
816 "Could not create program with source: %s\n",
817 piglit_cl_get_error_name(errNo));
818 return NULL;
821 errNo = clBuildProgram(program,
822 context->num_devices,
823 context->device_ids,
824 options,
825 NULL,
826 NULL);
827 if( (!fail && errNo != CL_SUCCESS)
828 || ( fail && errNo == CL_SUCCESS)) {
829 int i;
831 fprintf(stderr,
832 !fail ? "Could not build program: %s\n"
833 : "Program built when it should have failed: %s\n",
834 piglit_cl_get_error_name(errNo));
836 /*printf("Build log for source:\n");
837 for(i = 0; i < count; i++) {
838 printf("%s\n", strings[i]);
841 for(i = 0; i < context->num_devices; i++) {
842 char* device_name = piglit_cl_get_device_info(context->device_ids[i],
843 CL_DEVICE_NAME);
844 char* log = piglit_cl_get_program_build_info(program,
845 context->device_ids[i],
846 CL_PROGRAM_BUILD_LOG);
848 printf("Build log for device %s:\n -------- \n%s\n -------- \n",
849 device_name,
850 log);
852 free(device_name);
853 free(log);
856 clReleaseProgram(program);
857 return NULL;
860 return program;
863 cl_program
864 piglit_cl_build_program_with_source(piglit_cl_context context, cl_uint count,
865 char** strings, const char* options)
867 return piglit_cl_build_program_with_source_extended(context, count, strings, options, false);
870 cl_program
871 piglit_cl_fail_build_program_with_source(piglit_cl_context context,
872 cl_uint count, char** strings,
873 const char* options)
875 return piglit_cl_build_program_with_source_extended(context, count, strings, options, true);
878 cl_program
879 piglit_cl_build_program_with_binary_extended(piglit_cl_context context,
880 size_t* lenghts,
881 unsigned char** binaries,
882 const char* options, bool fail)
884 cl_int errNo;
885 cl_program program;
887 cl_int* binary_status = malloc(sizeof(cl_int) * context->num_devices);
889 program = clCreateProgramWithBinary(context->cl_ctx,
890 context->num_devices,
891 context->device_ids,
892 lenghts,
893 (const unsigned char**)binaries,
894 binary_status,
895 &errNo);
896 if(errNo != CL_SUCCESS) {
897 int i;
899 fprintf(stderr,
900 "Could not create program with binary: %s\n",
901 piglit_cl_get_error_name(errNo));
903 printf("Create error with binaries:\n");
904 for(i = 0; i < context->num_devices; i++) {
905 char* device_name = piglit_cl_get_device_info(context->device_ids[i],
906 CL_DEVICE_NAME);
908 printf("Error for %s: %s\n",
909 device_name,
910 piglit_cl_get_error_name(binary_status[i]));
912 free(device_name);
915 free(binary_status);
916 return NULL;
918 free(binary_status);
920 errNo = clBuildProgram(program,
921 context->num_devices,
922 context->device_ids,
923 options,
924 NULL,
925 NULL);
926 if( (!fail && errNo != CL_SUCCESS)
927 || ( fail && errNo == CL_SUCCESS)) {
928 int i;
930 fprintf(stderr,
931 !fail ? "Could not build program: %s\n"
932 : "Program built when it should have failed: %s\n",
933 piglit_cl_get_error_name(errNo));
935 printf("Build log for binaries.\n");
937 for(i = 0; i < context->num_devices; i++) {
938 char* device_name = piglit_cl_get_device_info(context->device_ids[i],
939 CL_DEVICE_NAME);
940 char* log = piglit_cl_get_program_build_info(program,
941 context->device_ids[i],
942 CL_PROGRAM_BUILD_LOG);
944 printf("Build log for device %s:\n -------- \n%s\n -------- \n",
945 device_name,
946 log);
948 free(device_name);
949 free(log);
952 clReleaseProgram(program);
953 return NULL;
956 return program;
959 cl_program
960 piglit_cl_build_program_with_binary(piglit_cl_context context, size_t* lenghts,
961 unsigned char** binaries,
962 const char* options)
964 return piglit_cl_build_program_with_binary_extended(context, lenghts,
965 binaries, options,
966 false);
969 cl_program
970 piglit_cl_fail_build_program_with_binary(piglit_cl_context context,
971 size_t* lenghts,
972 unsigned char** binaries,
973 const char* options)
975 return piglit_cl_build_program_with_binary_extended(context, lenghts,
976 binaries, options,
977 true);
980 cl_mem
981 piglit_cl_create_buffer(piglit_cl_context context, cl_mem_flags flags,
982 size_t size)
984 cl_int errNo;
985 cl_mem buffer;
987 buffer = clCreateBuffer(context->cl_ctx, flags, size, NULL, &errNo);
988 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
989 fprintf(stderr,
990 "Could not create buffer: %s\n",
991 piglit_cl_get_error_name(errNo));
994 return buffer;
997 bool
998 piglit_cl_write_buffer(cl_command_queue command_queue, cl_mem buffer,
999 size_t offset, size_t cb, const void *ptr)
1001 cl_int errNo;
1003 errNo = clEnqueueWriteBuffer(command_queue, buffer, CL_TRUE, offset, cb,
1004 ptr, 0, NULL, NULL);
1005 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1006 fprintf(stderr,
1007 "Could not enqueue buffer write: %s\n",
1008 piglit_cl_get_error_name(errNo));
1009 return false;
1012 return true;
1015 bool
1016 piglit_cl_write_whole_buffer(cl_command_queue command_queue, cl_mem buffer,
1017 const void *ptr)
1019 bool success;
1020 size_t* buffer_size;
1022 buffer_size = piglit_cl_get_mem_object_info(buffer, CL_MEM_SIZE);
1023 success = piglit_cl_write_buffer(command_queue, buffer, 0, *buffer_size,
1024 ptr);
1025 free(buffer_size);
1027 return success;
1030 bool
1031 piglit_cl_read_buffer(cl_command_queue command_queue, cl_mem buffer,
1032 size_t offset, size_t cb, void *ptr)
1034 cl_int errNo;
1036 errNo = clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, offset, cb, ptr,
1037 0, NULL, NULL);
1038 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1039 fprintf(stderr,
1040 "Could not enqueue buffer read: %s\n",
1041 piglit_cl_get_error_name(errNo));
1042 return false;
1045 return true;
1048 bool
1049 piglit_cl_read_whole_buffer(cl_command_queue command_queue, cl_mem buffer,
1050 void *ptr)
1052 bool success;
1053 size_t* buffer_size;
1055 buffer_size = piglit_cl_get_mem_object_info(buffer, CL_MEM_SIZE);
1056 success = piglit_cl_read_buffer(command_queue, buffer, 0, *buffer_size,
1057 ptr);
1058 free(buffer_size);
1060 return success;
1063 bool
1064 piglit_cl_get_context_image_support(const piglit_cl_context context)
1066 bool ret = false;
1068 unsigned i;
1069 for(i = 0; i < context->num_devices; i++)
1070 ret |= piglit_cl_get_device_image_support(context->device_ids[i]);
1072 return ret;
1075 bool
1076 piglit_cl_get_device_image_support(cl_device_id device)
1078 bool ret = false;
1080 cl_bool *image_support =
1081 piglit_cl_get_device_info(device, CL_DEVICE_IMAGE_SUPPORT);
1083 if (image_support)
1084 ret = *image_support;
1086 free(image_support);
1088 return ret;
1091 cl_mem
1092 piglit_cl_create_image(piglit_cl_context context, cl_mem_flags flags,
1093 const cl_image_format *format,
1094 const piglit_image_desc *desc)
1096 cl_int errNo;
1097 cl_mem image = NULL;
1099 #ifdef CL_VERSION_1_2
1100 if (piglit_cl_get_platform_version(context->platform_id) >= 12) {
1101 image = clCreateImage(context->cl_ctx, flags, format, desc, NULL, &errNo);
1102 } else
1103 #endif
1104 if (desc->image_type == CL_MEM_OBJECT_IMAGE2D) {
1105 image = clCreateImage2D(context->cl_ctx, flags, format,
1106 desc->image_width, desc->image_height, 0,
1107 NULL, &errNo);
1108 } else if (desc->image_type == CL_MEM_OBJECT_IMAGE3D) {
1109 image = clCreateImage3D(context->cl_ctx, flags, format,
1110 desc->image_width, desc->image_height,
1111 desc->image_depth, 0, 0,
1112 NULL, &errNo);
1113 } else {
1114 errNo = CL_INVALID_OPERATION;
1115 fprintf(stderr,
1116 "Invalid image mem object type: %s\n",
1117 piglit_cl_get_enum_name(desc->image_type));
1119 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1120 fprintf(stderr,
1121 "Could not create image: %s\n",
1122 piglit_cl_get_error_name(errNo));
1125 return image;
1128 bool
1129 piglit_cl_write_image(cl_command_queue command_queue, cl_mem image,
1130 const size_t *origin, const size_t *region,
1131 const void *ptr)
1133 cl_int errNo;
1135 errNo = clEnqueueWriteImage(command_queue, image, CL_TRUE, origin, region,
1136 0, 0, ptr, 0, NULL, NULL);
1137 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1138 fprintf(stderr,
1139 "Could not enqueue image write: %s\n",
1140 piglit_cl_get_error_name(errNo));
1141 return false;
1144 return true;
1147 static void
1148 piglit_get_image_region(cl_mem image, size_t *region)
1150 size_t *p = NULL;
1151 cl_mem_object_type *type;
1153 type = piglit_cl_get_mem_object_info(image, CL_MEM_TYPE);
1155 p = piglit_cl_get_image_info(image, CL_IMAGE_WIDTH);
1156 region[0] = *p;
1157 free(p);
1159 switch (*type) {
1160 #ifdef CL_VERSION_1_2
1161 case CL_MEM_OBJECT_IMAGE1D_ARRAY:
1162 p = piglit_cl_get_image_info(image, CL_IMAGE_ARRAY_SIZE);
1163 region[1] = *p;
1164 free(p);
1165 region[2] = 1;
1166 break;
1167 case CL_MEM_OBJECT_IMAGE1D:
1168 case CL_MEM_OBJECT_IMAGE1D_BUFFER:
1169 region[1] = 1;
1170 region[2] = 1;
1171 break;
1172 case CL_MEM_OBJECT_IMAGE2D_ARRAY:
1173 p = piglit_cl_get_image_info(image, CL_IMAGE_HEIGHT);
1174 region[1] = *p;
1175 free(p);
1176 p = piglit_cl_get_image_info(image, CL_IMAGE_ARRAY_SIZE);
1177 region[2] = *p;
1178 free(p);
1179 break;
1180 #endif
1181 case CL_MEM_OBJECT_IMAGE2D:
1182 p = piglit_cl_get_image_info(image, CL_IMAGE_HEIGHT);
1183 region[1] = *p;
1184 free(p);
1185 region[2] = 1;
1186 break;
1187 case CL_MEM_OBJECT_IMAGE3D:
1188 p = piglit_cl_get_image_info(image, CL_IMAGE_HEIGHT);
1189 region[1] = *p;
1190 free(p);
1191 p = piglit_cl_get_image_info(image, CL_IMAGE_DEPTH);
1192 region[2] = *p;
1193 free(p);
1194 break;
1197 free(type);
1200 bool
1201 piglit_cl_write_whole_image(cl_command_queue command_queue, cl_mem image,
1202 const void *ptr)
1204 bool success;
1205 size_t origin[3], region[3];
1207 memset(origin, 0, sizeof(origin));
1208 piglit_get_image_region(image, region);
1209 success = piglit_cl_write_image(command_queue, image, origin, region, ptr);
1211 return success;
1214 bool
1215 piglit_cl_read_image(cl_command_queue command_queue, cl_mem image,
1216 const size_t *origin, const size_t *region,
1217 void *ptr)
1219 cl_int errNo;
1221 errNo = clEnqueueReadImage(command_queue, image, CL_TRUE, origin, region,
1222 0, 0, ptr, 0, NULL, NULL);
1223 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1224 fprintf(stderr,
1225 "Could not enqueue image read: %s\n",
1226 piglit_cl_get_error_name(errNo));
1227 return false;
1230 return true;
1233 bool
1234 piglit_cl_read_whole_image(cl_command_queue command_queue, cl_mem image,
1235 void *ptr)
1237 bool success;
1238 size_t origin[3], region[3];
1240 memset(origin, 0, sizeof(origin));
1241 piglit_get_image_region(image, region);
1242 success = piglit_cl_read_image(command_queue, image, origin, region, ptr);
1244 return success;
1247 cl_kernel
1248 piglit_cl_create_kernel(cl_program program, const char* kernel_name)
1250 cl_int errNo;
1251 cl_kernel kernel;
1253 kernel = clCreateKernel(program, kernel_name, &errNo);
1254 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1255 fprintf(stderr,
1256 "Could not create kernel %s: %s\n",
1257 kernel_name,
1258 piglit_cl_get_error_name(errNo));
1261 return kernel;
1264 cl_sampler
1265 piglit_cl_create_sampler(piglit_cl_context context,
1266 cl_bool normalized_coords,
1267 cl_addressing_mode addressing_mode,
1268 cl_filter_mode filter_mode)
1270 cl_int errNo;
1271 cl_sampler sampler;
1273 sampler = clCreateSampler(context->cl_ctx, normalized_coords,
1274 addressing_mode, filter_mode, &errNo);
1275 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1276 fprintf(stderr,
1277 "Could not create sampler: %s\n",
1278 piglit_cl_get_error_name(errNo));
1281 return sampler;
1284 bool
1285 piglit_cl_set_kernel_arg(cl_kernel kernel, cl_uint arg_index, size_t size,
1286 const void* arg_value)
1288 cl_int errNo;
1290 errNo = clSetKernelArg(kernel, arg_index, size, arg_value);
1291 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1292 fprintf(stderr,
1293 "Could not set kernel argument %u: %s\n",
1294 arg_index,
1295 piglit_cl_get_error_name(errNo));
1296 return false;
1299 return true;
1302 bool
1303 piglit_cl_set_kernel_buffer_arg(cl_kernel kernel, cl_uint arg_index,
1304 cl_mem *buffer)
1306 bool success;
1308 success = piglit_cl_set_kernel_arg(kernel, arg_index, sizeof(cl_mem),
1309 buffer);
1310 if(!success) {
1311 fprintf(stderr,
1312 "Could not set kernel buffer argument %u\n",
1313 arg_index);
1314 return false;
1317 return success;
1320 bool
1321 piglit_cl_enqueue_ND_range_kernel(cl_command_queue command_queue,
1322 cl_kernel kernel, cl_uint work_dim,
1323 const size_t* global_offset,
1324 const size_t* global_work_size,
1325 const size_t* local_work_size,
1326 cl_event *ev)
1328 cl_int errNo;
1330 errNo = clEnqueueNDRangeKernel(command_queue, kernel, work_dim,
1331 global_offset, global_work_size,
1332 local_work_size, 0, NULL, ev);
1333 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1334 fprintf(stderr,
1335 "Could not enqueue ND range kernel: %s\n",
1336 piglit_cl_get_error_name(errNo));
1337 return false;
1340 return true;
1343 bool
1344 piglit_cl_execute_ND_range_kernel(cl_command_queue command_queue,
1345 cl_kernel kernel, cl_uint work_dim,
1346 const size_t* global_offset,
1347 const size_t* global_work_size,
1348 const size_t* local_work_size)
1350 int errNo;
1351 cl_event ev;
1353 if(!piglit_cl_enqueue_ND_range_kernel(command_queue,
1354 kernel,
1355 work_dim,
1356 global_offset,
1357 global_work_size,
1358 local_work_size,
1359 &ev)) {
1360 return false;
1363 errNo = clWaitForEvents(1, &ev);
1364 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1365 fprintf(stderr,
1366 "Could not wait for kernel to finish: %s\n",
1367 piglit_cl_get_error_name(errNo));
1368 return false;
1371 return true;
1374 bool
1375 piglit_cl_enqueue_task(cl_command_queue command_queue, cl_kernel kernel)
1377 cl_int errNo;
1379 errNo = clEnqueueTask(command_queue, kernel,
1380 0, NULL, NULL);
1381 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1382 fprintf(stderr,
1383 "Could not enqueue task: %s\n",
1384 piglit_cl_get_error_name(errNo));
1385 return false;
1388 return true;
1391 bool
1392 piglit_cl_execute_task(cl_command_queue command_queue, cl_kernel kernel)
1394 int errNo;
1396 if(!piglit_cl_enqueue_task(command_queue,
1397 kernel)) {
1398 return false;
1401 errNo = clFinish(command_queue);
1402 if(!piglit_cl_check_error(errNo, CL_SUCCESS)) {
1403 fprintf(stderr,
1404 "Could not wait for kernel to finish: %s\n",
1405 piglit_cl_get_error_name(errNo));
1406 return false;
1409 return true;