• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "testBase.h"
17 #include "harness/typeWrappers.h"
18 #include "harness/testHarness.h"
19 #include <ctype.h>
20 #include <string.h>
21 
22 const char *sample_single_param_kernel[] = {
23     "__kernel void sample_test(__global int *src)\n"
24     "{\n"
25     "    size_t  tid = get_global_id(0);\n"
26     "\n"
27     "}\n"
28 };
29 
30 
31 const char *sample_read_image_kernel_pattern[] = {
32     "__kernel void sample_test( __global float *result, ",
33     " )\n"
34     "{\n"
35     "  sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | "
36     "CLK_FILTER_NEAREST;\n"
37     "    size_t  tid = get_global_id(0);\n"
38     "    result[0] = 0.0f;\n",
39     "\n"
40     "}\n"
41 };
42 
43 const char *sample_write_image_kernel_pattern[] = {
44     "__kernel void sample_test( ",
45     " )\n"
46     "{\n"
47     "    size_t  tid = get_global_id(0);\n",
48     "\n"
49     "}\n"
50 };
51 
52 
53 const char *sample_large_parmam_kernel_pattern[] = {
54     "__kernel void sample_test(%s, __global long *result)\n"
55     "{\n"
56     "result[0] = 0;\n"
57     "%s"
58     "\n"
59     "}\n"
60 };
61 
62 const char *sample_large_int_parmam_kernel_pattern[] = {
63     "__kernel void sample_test(%s, __global int *result)\n"
64     "{\n"
65     "result[0] = 0;\n"
66     "%s"
67     "\n"
68     "}\n"
69 };
70 
71 const char *sample_sampler_kernel_pattern[] = {
72     "__kernel void sample_test( read_only image2d_t src, __global int4 *dst",
73     ", sampler_t sampler%d",
74     ")\n"
75     "{\n"
76     "    size_t  tid = get_global_id(0);\n",
77     "    dst[ 0 ] = read_imagei( src, sampler%d, (int2)( 0, 0 ) );\n",
78     "\n"
79     "}\n"
80 };
81 
82 const char *sample_const_arg_kernel[] = {
83     "__kernel void sample_test(__constant int *src1, __global int *dst)\n"
84     "{\n"
85     "    size_t  tid = get_global_id(0);\n"
86     "\n"
87     "    dst[tid] = src1[tid];\n"
88     "\n"
89     "}\n"
90 };
91 
92 const char *sample_local_arg_kernel[] = {
93     "__kernel void sample_test(__local int *src1, __global int *global_src, "
94     "__global int *dst)\n"
95     "{\n"
96     "    size_t  tid = get_global_id(0);\n"
97     "\n"
98     "    src1[tid] = global_src[tid];\n"
99     "    barrier(CLK_GLOBAL_MEM_FENCE);\n"
100     "    dst[tid] = src1[tid];\n"
101     "\n"
102     "}\n"
103 };
104 
105 const char *sample_const_max_arg_kernel_pattern =
106     "__kernel void sample_test(__constant int *src1 %s, __global int *dst)\n"
107     "{\n"
108     "    int  tid = get_global_id(0);\n"
109     "\n"
110     "    dst[tid] = src1[tid];\n"
111     "%s"
112     "\n"
113     "}\n";
114 
test_min_max_thread_dimensions(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)115 int test_min_max_thread_dimensions(cl_device_id deviceID, cl_context context,
116                                    cl_command_queue queue, int num_elements)
117 {
118     int error, retVal;
119     unsigned int maxThreadDim, threadDim, i;
120     clProgramWrapper program;
121     clKernelWrapper kernel;
122     clMemWrapper streams[1];
123     size_t *threads, *localThreads;
124     cl_event event;
125     cl_int event_status;
126 
127 
128     /* Get the max thread dimensions */
129     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
130                             sizeof(maxThreadDim), &maxThreadDim, NULL);
131     test_error(error, "Unable to get max work item dimensions from device");
132 
133     if (maxThreadDim < 3)
134     {
135         log_error("ERROR: Reported max work item dimensions is less than "
136                   "required! (%d)\n",
137                   maxThreadDim);
138         return -1;
139     }
140 
141     log_info("Reported max thread dimensions of %d.\n", maxThreadDim);
142 
143     /* Create a kernel to test with */
144     if (create_single_kernel_helper(context, &program, &kernel, 1,
145                                     sample_single_param_kernel, "sample_test")
146         != 0)
147     {
148         return -1;
149     }
150 
151     /* Create some I/O streams */
152     streams[0] = clCreateBuffer(context, CL_MEM_READ_WRITE,
153                                 sizeof(cl_int) * 100, NULL, &error);
154     if (streams[0] == NULL)
155     {
156         log_error("ERROR: Creating test array failed!\n");
157         return -1;
158     }
159 
160     /* Set the arguments */
161     error = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]);
162     test_error(error, "Unable to set kernel arguments");
163 
164     retVal = 0;
165 
166     /* Now try running the kernel with up to that many threads */
167     for (threadDim = 1; threadDim <= maxThreadDim; threadDim++)
168     {
169         threads = (size_t *)malloc(sizeof(size_t) * maxThreadDim);
170         localThreads = (size_t *)malloc(sizeof(size_t) * maxThreadDim);
171         for (i = 0; i < maxThreadDim; i++)
172         {
173             threads[i] = 1;
174             localThreads[i] = 1;
175         }
176 
177         error = clEnqueueNDRangeKernel(queue, kernel, maxThreadDim, NULL,
178                                        threads, localThreads, 0, NULL, &event);
179         test_error(error, "Failed clEnqueueNDRangeKernel");
180 
181         // Verify that the event does not return an error from the execution
182         error = clWaitForEvents(1, &event);
183         test_error(error, "clWaitForEvent failed");
184         error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
185                                sizeof(event_status), &event_status, NULL);
186         test_error(
187             error,
188             "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
189         clReleaseEvent(event);
190         if (event_status < 0)
191             test_error(error, "Kernel execution event returned error");
192 
193         /* All done */
194         free(threads);
195         free(localThreads);
196     }
197 
198     return retVal;
199 }
200 
201 
test_min_max_work_items_sizes(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)202 int test_min_max_work_items_sizes(cl_device_id deviceID, cl_context context,
203                                   cl_command_queue queue, int num_elements)
204 {
205     int error;
206     size_t *deviceMaxWorkItemSize;
207     unsigned int maxWorkItemDim;
208 
209     /* Get the max work item dimensions */
210     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
211                             sizeof(maxWorkItemDim), &maxWorkItemDim, NULL);
212     test_error(error, "Unable to get max work item dimensions from device");
213 
214     log_info("CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS returned %d\n",
215              maxWorkItemDim);
216     deviceMaxWorkItemSize = (size_t *)malloc(sizeof(size_t) * maxWorkItemDim);
217     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES,
218                             sizeof(size_t) * maxWorkItemDim,
219                             deviceMaxWorkItemSize, NULL);
220     test_error(error, "clDeviceInfo for CL_DEVICE_MAX_WORK_ITEM_SIZES failed");
221 
222     unsigned int i;
223     int errors = 0;
224     for (i = 0; i < maxWorkItemDim; i++)
225     {
226         if (deviceMaxWorkItemSize[i] < 1)
227         {
228             log_error("MAX_WORK_ITEM_SIZE in dimension %d is invalid: %lu\n", i,
229                       deviceMaxWorkItemSize[i]);
230             errors++;
231         }
232         else
233         {
234             log_info("Dimension %d has max work item size %lu\n", i,
235                      deviceMaxWorkItemSize[i]);
236         }
237     }
238 
239     free(deviceMaxWorkItemSize);
240 
241     if (errors) return -1;
242     return 0;
243 }
244 
245 
test_min_max_work_group_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)246 int test_min_max_work_group_size(cl_device_id deviceID, cl_context context,
247                                  cl_command_queue queue, int num_elements)
248 {
249     int error;
250     size_t deviceMaxThreadSize;
251 
252     /* Get the max thread dimensions */
253     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_GROUP_SIZE,
254                             sizeof(deviceMaxThreadSize), &deviceMaxThreadSize,
255                             NULL);
256     test_error(error, "Unable to get max work group size from device");
257 
258     log_info("Reported %ld max device work group size.\n", deviceMaxThreadSize);
259 
260     if (deviceMaxThreadSize == 0)
261     {
262         log_error("ERROR: Max work group size is reported as zero!\n");
263         return -1;
264     }
265     return 0;
266 }
267 
test_min_max_read_image_args(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)268 int test_min_max_read_image_args(cl_device_id deviceID, cl_context context,
269                                  cl_command_queue queue, int num_elements)
270 {
271     int error;
272     unsigned int maxReadImages, i;
273     unsigned int deviceAddressSize;
274     clProgramWrapper program;
275     char readArgLine[128], *programSrc;
276     const char *readArgPattern = ", read_only image2d_t srcimg%d";
277     clKernelWrapper kernel;
278     clMemWrapper *streams, result;
279     size_t threads[2];
280     cl_image_format image_format_desc;
281     size_t maxParameterSize;
282     cl_event event;
283     cl_int event_status;
284     cl_float image_data[4 * 4];
285     float image_result = 0.0f;
286     float actual_image_result;
287     cl_uint minRequiredReadImages = gIsEmbedded ? 8 : 128;
288     cl_device_type deviceType;
289 
290     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
291     image_format_desc.image_channel_order = CL_RGBA;
292     image_format_desc.image_channel_data_type = CL_FLOAT;
293 
294     /* Get the max read image arg count */
295     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_READ_IMAGE_ARGS,
296                             sizeof(maxReadImages), &maxReadImages, NULL);
297     test_error(error, "Unable to get max read image arg count from device");
298 
299     if (maxReadImages < minRequiredReadImages)
300     {
301         log_error("ERROR: Reported max read image arg count is less than "
302                   "required! (%d)\n",
303                   maxReadImages);
304         return -1;
305     }
306 
307     log_info("Reported %d max read image args.\n", maxReadImages);
308 
309     error =
310         clGetDeviceInfo(deviceID, CL_DEVICE_ADDRESS_BITS,
311                         sizeof(deviceAddressSize), &deviceAddressSize, NULL);
312     test_error(error, "Unable to query CL_DEVICE_ADDRESS_BITS for device");
313     deviceAddressSize /= 8; // convert from bits to bytes
314 
315 
316     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
317                             sizeof(maxParameterSize), &maxParameterSize, NULL);
318     test_error(error, "Unable to get max parameter size from device");
319 
320     if (!gIsEmbedded && maxReadImages >= 128 && maxParameterSize == 1024)
321     {
322         error = clGetDeviceInfo(deviceID, CL_DEVICE_TYPE, sizeof(deviceType),
323                                 &deviceType, NULL);
324         test_error(error, "Unable to get device type from device");
325 
326         if (deviceType != CL_DEVICE_TYPE_CUSTOM)
327         {
328             maxReadImages = 127;
329         }
330     }
331     // Subtract the size of the result
332     maxParameterSize -= deviceAddressSize;
333 
334     // Calculate the number we can use
335     if (maxParameterSize / deviceAddressSize < maxReadImages)
336     {
337         log_info("WARNING: Max parameter size of %d bytes limits test to %d "
338                  "max image arguments.\n",
339                  (int)maxParameterSize,
340                  (int)(maxParameterSize / deviceAddressSize));
341         maxReadImages = (unsigned int)(maxParameterSize / deviceAddressSize);
342     }
343 
344     /* Create a program with that many read args */
345     programSrc = (char *)malloc(strlen(sample_read_image_kernel_pattern[0])
346                                 + (strlen(readArgPattern) + 6) * (maxReadImages)
347                                 + strlen(sample_read_image_kernel_pattern[1])
348                                 + 1 + 40240);
349 
350     strcpy(programSrc, sample_read_image_kernel_pattern[0]);
351     strcat(programSrc, "read_only image2d_t srcimg0");
352     for (i = 0; i < maxReadImages - 1; i++)
353     {
354         sprintf(readArgLine, readArgPattern, i + 1);
355         strcat(programSrc, readArgLine);
356     }
357     strcat(programSrc, sample_read_image_kernel_pattern[1]);
358     for (i = 0; i < maxReadImages; i++)
359     {
360         sprintf(
361             readArgLine,
362             "\tresult[0] += read_imagef( srcimg%d, sampler, (int2)(0,0)).x;\n",
363             i);
364         strcat(programSrc, readArgLine);
365     }
366     strcat(programSrc, sample_read_image_kernel_pattern[2]);
367 
368     error =
369         create_single_kernel_helper(context, &program, &kernel, 1,
370                                     (const char **)&programSrc, "sample_test");
371     test_error(error, "Failed to create the program and kernel.");
372     free(programSrc);
373 
374     result = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float), NULL,
375                             &error);
376     test_error(error, "clCreateBufer failed");
377 
378     /* Create some I/O streams */
379     streams = new clMemWrapper[maxReadImages + 1];
380     for (i = 0; i < maxReadImages; i++)
381     {
382         image_data[0] = i;
383         image_result += image_data[0];
384         streams[i] =
385             create_image_2d(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
386                             &image_format_desc, 4, 4, 0, image_data, &error);
387         test_error(error, "Unable to allocate test image");
388     }
389 
390     error = clSetKernelArg(kernel, 0, sizeof(result), &result);
391     test_error(error, "Unable to set kernel arguments");
392 
393     /* Set the arguments */
394     for (i = 1; i < maxReadImages + 1; i++)
395     {
396         error =
397             clSetKernelArg(kernel, i, sizeof(streams[i - 1]), &streams[i - 1]);
398         test_error(error, "Unable to set kernel arguments");
399     }
400 
401     /* Now try running the kernel */
402     threads[0] = threads[1] = 1;
403     error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, threads, NULL, 0,
404                                    NULL, &event);
405     test_error(error, "clEnqueueNDRangeKernel failed");
406 
407     // Verify that the event does not return an error from the execution
408     error = clWaitForEvents(1, &event);
409     test_error(error, "clWaitForEvent failed");
410     error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
411                            sizeof(event_status), &event_status, NULL);
412     test_error(error,
413                "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
414     clReleaseEvent(event);
415     if (event_status < 0)
416         test_error(error, "Kernel execution event returned error");
417 
418     error = clEnqueueReadBuffer(queue, result, CL_TRUE, 0, sizeof(cl_float),
419                                 &actual_image_result, 0, NULL, NULL);
420     test_error(error, "clEnqueueReadBuffer failed");
421 
422     delete[] streams;
423 
424     if (actual_image_result != image_result)
425     {
426         log_error("Result failed to verify. Got %g, expected %g.\n",
427                   actual_image_result, image_result);
428         return 1;
429     }
430 
431     return 0;
432 }
433 
test_min_max_write_image_args(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)434 int test_min_max_write_image_args(cl_device_id deviceID, cl_context context,
435                                   cl_command_queue queue, int num_elements)
436 {
437     int error;
438     unsigned int maxWriteImages, i;
439     clProgramWrapper program;
440     char writeArgLine[128], *programSrc;
441     const char *writeArgPattern = ", write_only image2d_t dstimg%d";
442     clKernelWrapper kernel;
443     clMemWrapper *streams;
444     size_t threads[2];
445     cl_image_format image_format_desc;
446     size_t maxParameterSize;
447     cl_event event;
448     cl_int event_status;
449     cl_uint minRequiredWriteImages = gIsEmbedded ? 1 : 8;
450 
451 
452     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
453     image_format_desc.image_channel_order = CL_RGBA;
454     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
455 
456     /* Get the max read image arg count */
457     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WRITE_IMAGE_ARGS,
458                             sizeof(maxWriteImages), &maxWriteImages, NULL);
459     test_error(error, "Unable to get max write image arg count from device");
460 
461     if (maxWriteImages == 0)
462     {
463         log_info(
464             "WARNING: Device reports 0 for a max write image arg count (write "
465             "image arguments unsupported). Skipping test (implicitly passes). "
466             "This is only valid if the number of image formats is also 0.\n");
467         return 0;
468     }
469 
470     if (maxWriteImages < minRequiredWriteImages)
471     {
472         log_error("ERROR: Reported max write image arg count is less than "
473                   "required! (%d)\n",
474                   maxWriteImages);
475         return -1;
476     }
477 
478     log_info("Reported %d max write image args.\n", maxWriteImages);
479 
480     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
481                             sizeof(maxParameterSize), &maxParameterSize, NULL);
482     test_error(error, "Unable to get max parameter size from device");
483 
484     // Calculate the number we can use
485     if (maxParameterSize / sizeof(cl_mem) < maxWriteImages)
486     {
487         log_info("WARNING: Max parameter size of %d bytes limits test to %d "
488                  "max image arguments.\n",
489                  (int)maxParameterSize,
490                  (int)(maxParameterSize / sizeof(cl_mem)));
491         maxWriteImages = (unsigned int)(maxParameterSize / sizeof(cl_mem));
492     }
493 
494     /* Create a program with that many write args + 1 */
495     programSrc = (char *)malloc(
496         strlen(sample_write_image_kernel_pattern[0])
497         + (strlen(writeArgPattern) + 6) * (maxWriteImages + 1)
498         + strlen(sample_write_image_kernel_pattern[1]) + 1 + 40240);
499 
500     strcpy(programSrc, sample_write_image_kernel_pattern[0]);
501     strcat(programSrc, "write_only image2d_t dstimg0");
502     for (i = 1; i < maxWriteImages; i++)
503     {
504         sprintf(writeArgLine, writeArgPattern, i);
505         strcat(programSrc, writeArgLine);
506     }
507     strcat(programSrc, sample_write_image_kernel_pattern[1]);
508     for (i = 0; i < maxWriteImages; i++)
509     {
510         sprintf(writeArgLine,
511                 "\twrite_imagef( dstimg%d, (int2)(0,0), (float4)(0,0,0,0));\n",
512                 i);
513         strcat(programSrc, writeArgLine);
514     }
515     strcat(programSrc, sample_write_image_kernel_pattern[2]);
516 
517     error =
518         create_single_kernel_helper(context, &program, &kernel, 1,
519                                     (const char **)&programSrc, "sample_test");
520     test_error(error, "Failed to create the program and kernel.");
521     free(programSrc);
522 
523 
524     /* Create some I/O streams */
525     streams = new clMemWrapper[maxWriteImages + 1];
526     for (i = 0; i < maxWriteImages; i++)
527     {
528         streams[i] =
529             create_image_2d(context, CL_MEM_READ_WRITE, &image_format_desc, 16,
530                             16, 0, NULL, &error);
531         test_error(error, "Unable to allocate test image");
532     }
533 
534     /* Set the arguments */
535     for (i = 0; i < maxWriteImages; i++)
536     {
537         error = clSetKernelArg(kernel, i, sizeof(streams[i]), &streams[i]);
538         test_error(error, "Unable to set kernel arguments");
539     }
540 
541     /* Now try running the kernel */
542     threads[0] = threads[1] = 16;
543     error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, threads, NULL, 0,
544                                    NULL, &event);
545     test_error(error, "clEnqueueNDRangeKernel failed.");
546 
547     // Verify that the event does not return an error from the execution
548     error = clWaitForEvents(1, &event);
549     test_error(error, "clWaitForEvent failed");
550     error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
551                            sizeof(event_status), &event_status, NULL);
552     test_error(error,
553                "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
554     clReleaseEvent(event);
555     if (event_status < 0)
556         test_error(error, "Kernel execution event returned error");
557 
558     /* All done */
559     delete[] streams;
560     return 0;
561 }
562 
test_min_max_mem_alloc_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)563 int test_min_max_mem_alloc_size(cl_device_id deviceID, cl_context context,
564                                 cl_command_queue queue, int num_elements)
565 {
566     int error;
567     cl_ulong maxAllocSize, memSize, minSizeToTry;
568     clMemWrapper memHdl;
569 
570     cl_ulong requiredAllocSize;
571 
572     if (gIsEmbedded)
573         requiredAllocSize = 1 * 1024 * 1024;
574     else
575         requiredAllocSize = 128 * 1024 * 1024;
576 
577     /* Get the max mem alloc size */
578     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
579                             sizeof(maxAllocSize), &maxAllocSize, NULL);
580     test_error(error, "Unable to get max mem alloc size from device");
581 
582     error = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE,
583                             sizeof(memSize), &memSize, NULL);
584     test_error(error, "Unable to get global memory size from device");
585 
586     if (memSize > (cl_ulong)SIZE_MAX)
587     {
588         memSize = (cl_ulong)SIZE_MAX;
589     }
590 
591     if (maxAllocSize < requiredAllocSize)
592     {
593         log_error("ERROR: Reported max allocation size is less than required "
594                   "%lldMB! (%llu or %lluMB, from a total mem size of %lldMB)\n",
595                   (requiredAllocSize / 1024) / 1024, maxAllocSize,
596                   (maxAllocSize / 1024) / 1024, (memSize / 1024) / 1024);
597         return -1;
598     }
599 
600     requiredAllocSize = ((memSize / 4) > (1024 * 1024 * 1024))
601         ? 1024 * 1024 * 1024
602         : memSize / 4;
603 
604     if (gIsEmbedded)
605         requiredAllocSize = (requiredAllocSize < 1 * 1024 * 1024)
606             ? 1 * 1024 * 1024
607             : requiredAllocSize;
608     else
609         requiredAllocSize = (requiredAllocSize < 128 * 1024 * 1024)
610             ? 128 * 1024 * 1024
611             : requiredAllocSize;
612 
613     if (maxAllocSize < requiredAllocSize)
614     {
615         log_error(
616             "ERROR: Reported max allocation size is less than required of "
617             "total memory! (%llu or %lluMB, from a total mem size of %lluMB)\n",
618             maxAllocSize, (maxAllocSize / 1024) / 1024,
619             (requiredAllocSize / 1024) / 1024);
620         return -1;
621     }
622 
623     log_info("Reported max allocation size of %lld bytes (%gMB) and global mem "
624              "size of %lld bytes (%gMB).\n",
625              maxAllocSize, maxAllocSize / (1024.0 * 1024.0), requiredAllocSize,
626              requiredAllocSize / (1024.0 * 1024.0));
627 
628     if (memSize < maxAllocSize)
629     {
630         log_info("Global memory size is less than max allocation size, using "
631                  "that.\n");
632         maxAllocSize = memSize;
633     }
634 
635     minSizeToTry = maxAllocSize / 16;
636     while (maxAllocSize > (maxAllocSize / 4))
637     {
638 
639         log_info("Trying to create a buffer of size of %lld bytes (%gMB).\n",
640                  maxAllocSize, (double)maxAllocSize / (1024.0 * 1024.0));
641         memHdl = clCreateBuffer(context, CL_MEM_READ_ONLY, (size_t)maxAllocSize,
642                                 NULL, &error);
643         if (error == CL_MEM_OBJECT_ALLOCATION_FAILURE
644             || error == CL_OUT_OF_RESOURCES || error == CL_OUT_OF_HOST_MEMORY)
645         {
646             log_info("\tAllocation failed at size of %lld bytes (%gMB).\n",
647                      maxAllocSize, (double)maxAllocSize / (1024.0 * 1024.0));
648             maxAllocSize -= minSizeToTry;
649             continue;
650         }
651         test_error(error, "clCreateBuffer failed for maximum sized buffer.");
652         return 0;
653     }
654     log_error("Failed to allocate even %lld bytes (%gMB).\n", maxAllocSize,
655               (double)maxAllocSize / (1024.0 * 1024.0));
656     return -1;
657 }
658 
test_min_max_image_2d_width(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)659 int test_min_max_image_2d_width(cl_device_id deviceID, cl_context context,
660                                 cl_command_queue queue, int num_elements)
661 {
662     int error;
663     size_t maxDimension;
664     clMemWrapper streams[1];
665     cl_image_format image_format_desc;
666     cl_ulong maxAllocSize;
667     cl_uint minRequiredDimension;
668 
669     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
670 
671     auto version = get_device_cl_version(deviceID);
672     if (version == Version(1, 0))
673     {
674         minRequiredDimension = gIsEmbedded ? 2048 : 4096;
675     }
676     else
677     {
678         minRequiredDimension = gIsEmbedded ? 2048 : 8192;
679     }
680 
681 
682     /* Just get any ol format to test with */
683     error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE2D,
684                                    CL_MEM_READ_WRITE, 0, &image_format_desc);
685     test_error(error, "Unable to obtain suitable image format to test with!");
686 
687     /* Get the max 2d image width */
688     error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE2D_MAX_WIDTH,
689                             sizeof(maxDimension), &maxDimension, NULL);
690     test_error(error, "Unable to get max image 2d width from device");
691 
692     if (maxDimension < minRequiredDimension)
693     {
694         log_error(
695             "ERROR: Reported max image 2d width is less than required! (%d)\n",
696             (int)maxDimension);
697         return -1;
698     }
699     log_info("Max reported width is %ld.\n", maxDimension);
700 
701     /* Verify we can use the format */
702     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
703     image_format_desc.image_channel_order = CL_RGBA;
704     if (!is_image_format_supported(context, CL_MEM_READ_ONLY,
705                                    CL_MEM_OBJECT_IMAGE2D, &image_format_desc))
706     {
707         log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test.");
708         return -1;
709     }
710 
711     /* Verify that we can actually allocate an image that large */
712     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
713                             sizeof(maxAllocSize), &maxAllocSize, NULL);
714     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
715     if ((cl_ulong)maxDimension * 1 * 4 > maxAllocSize)
716     {
717         log_error("Can not allocate a large enough image (min size: %lld "
718                   "bytes, max allowed: %lld bytes) to test.\n",
719                   (cl_ulong)maxDimension * 1 * 4, maxAllocSize);
720         return -1;
721     }
722 
723     log_info("Attempting to create an image of size %d x 1 = %gMB.\n",
724              (int)maxDimension, ((float)maxDimension * 4 / 1024.0 / 1024.0));
725 
726     /* Try to allocate a very big image */
727     streams[0] = create_image_2d(context, CL_MEM_READ_ONLY, &image_format_desc,
728                                  maxDimension, 1, 0, NULL, &error);
729     if ((streams[0] == NULL) || (error != CL_SUCCESS))
730     {
731         print_error(error, "Image 2D creation failed for maximum width");
732         return -1;
733     }
734 
735     return 0;
736 }
737 
test_min_max_image_2d_height(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)738 int test_min_max_image_2d_height(cl_device_id deviceID, cl_context context,
739                                  cl_command_queue queue, int num_elements)
740 {
741     int error;
742     size_t maxDimension;
743     clMemWrapper streams[1];
744     cl_image_format image_format_desc;
745     cl_ulong maxAllocSize;
746     cl_uint minRequiredDimension;
747 
748     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
749 
750     auto version = get_device_cl_version(deviceID);
751     if (version == Version(1, 0))
752     {
753         minRequiredDimension = gIsEmbedded ? 2048 : 4096;
754     }
755     else
756     {
757         minRequiredDimension = gIsEmbedded ? 2048 : 8192;
758     }
759 
760     /* Just get any ol format to test with */
761     error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE2D,
762                                    CL_MEM_READ_WRITE, 0, &image_format_desc);
763     test_error(error, "Unable to obtain suitable image format to test with!");
764 
765     /* Get the max 2d image width */
766     error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
767                             sizeof(maxDimension), &maxDimension, NULL);
768     test_error(error, "Unable to get max image 2d height from device");
769 
770     if (maxDimension < minRequiredDimension)
771     {
772         log_error(
773             "ERROR: Reported max image 2d height is less than required! (%d)\n",
774             (int)maxDimension);
775         return -1;
776     }
777     log_info("Max reported height is %ld.\n", maxDimension);
778 
779     /* Verify we can use the format */
780     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
781     image_format_desc.image_channel_order = CL_RGBA;
782     if (!is_image_format_supported(context, CL_MEM_READ_ONLY,
783                                    CL_MEM_OBJECT_IMAGE2D, &image_format_desc))
784     {
785         log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test.");
786         return -1;
787     }
788 
789     /* Verify that we can actually allocate an image that large */
790     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
791                             sizeof(maxAllocSize), &maxAllocSize, NULL);
792     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
793     if ((cl_ulong)maxDimension * 1 * 4 > maxAllocSize)
794     {
795         log_error("Can not allocate a large enough image (min size: %lld "
796                   "bytes, max allowed: %lld bytes) to test.\n",
797                   (cl_ulong)maxDimension * 1 * 4, maxAllocSize);
798         return -1;
799     }
800 
801     log_info("Attempting to create an image of size 1 x %d = %gMB.\n",
802              (int)maxDimension, ((float)maxDimension * 4 / 1024.0 / 1024.0));
803 
804     /* Try to allocate a very big image */
805     streams[0] = create_image_2d(context, CL_MEM_READ_ONLY, &image_format_desc,
806                                  1, maxDimension, 0, NULL, &error);
807     if ((streams[0] == NULL) || (error != CL_SUCCESS))
808     {
809         print_error(error, "Image 2D creation failed for maximum height");
810         return -1;
811     }
812 
813     return 0;
814 }
815 
test_min_max_image_3d_width(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)816 int test_min_max_image_3d_width(cl_device_id deviceID, cl_context context,
817                                 cl_command_queue queue, int num_elements)
818 {
819     int error;
820     size_t maxDimension;
821     clMemWrapper streams[1];
822     cl_image_format image_format_desc;
823     cl_ulong maxAllocSize;
824 
825 
826     PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(deviceID)
827 
828     /* Just get any ol format to test with */
829     error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE3D,
830                                    CL_MEM_READ_ONLY, 0, &image_format_desc);
831     test_error(error, "Unable to obtain suitable image format to test with!");
832 
833     /* Get the max 2d image width */
834     error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE3D_MAX_WIDTH,
835                             sizeof(maxDimension), &maxDimension, NULL);
836     test_error(error, "Unable to get max image 3d width from device");
837 
838     if (maxDimension < 2048)
839     {
840         log_error(
841             "ERROR: Reported max image 3d width is less than required! (%d)\n",
842             (int)maxDimension);
843         return -1;
844     }
845     log_info("Max reported width is %ld.\n", maxDimension);
846 
847     /* Verify we can use the format */
848     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
849     image_format_desc.image_channel_order = CL_RGBA;
850     if (!is_image_format_supported(context, CL_MEM_READ_ONLY,
851                                    CL_MEM_OBJECT_IMAGE3D, &image_format_desc))
852     {
853         log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test.");
854         return -1;
855     }
856 
857     /* Verify that we can actually allocate an image that large */
858     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
859                             sizeof(maxAllocSize), &maxAllocSize, NULL);
860     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
861     if ((cl_ulong)maxDimension * 2 * 4 > maxAllocSize)
862     {
863         log_error("Can not allocate a large enough image (min size: %lld "
864                   "bytes, max allowed: %lld bytes) to test.\n",
865                   (cl_ulong)maxDimension * 2 * 4, maxAllocSize);
866         return -1;
867     }
868 
869     log_info("Attempting to create an image of size %d x 1 x 2 = %gMB.\n",
870              (int)maxDimension,
871              (2 * (float)maxDimension * 4 / 1024.0 / 1024.0));
872 
873     /* Try to allocate a very big image */
874     streams[0] = create_image_3d(context, CL_MEM_READ_ONLY, &image_format_desc,
875                                  maxDimension, 1, 2, 0, 0, NULL, &error);
876     if ((streams[0] == NULL) || (error != CL_SUCCESS))
877     {
878         print_error(error, "Image 3D creation failed for maximum width");
879         return -1;
880     }
881 
882     return 0;
883 }
884 
test_min_max_image_3d_height(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)885 int test_min_max_image_3d_height(cl_device_id deviceID, cl_context context,
886                                  cl_command_queue queue, int num_elements)
887 {
888     int error;
889     size_t maxDimension;
890     clMemWrapper streams[1];
891     cl_image_format image_format_desc;
892     cl_ulong maxAllocSize;
893 
894 
895     PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(deviceID)
896 
897     /* Just get any ol format to test with */
898     error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE3D,
899                                    CL_MEM_READ_ONLY, 0, &image_format_desc);
900     test_error(error, "Unable to obtain suitable image format to test with!");
901 
902     /* Get the max 2d image width */
903     error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE3D_MAX_HEIGHT,
904                             sizeof(maxDimension), &maxDimension, NULL);
905     test_error(error, "Unable to get max image 3d height from device");
906 
907     if (maxDimension < 2048)
908     {
909         log_error(
910             "ERROR: Reported max image 3d height is less than required! (%d)\n",
911             (int)maxDimension);
912         return -1;
913     }
914     log_info("Max reported height is %ld.\n", maxDimension);
915 
916     /* Verify we can use the format */
917     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
918     image_format_desc.image_channel_order = CL_RGBA;
919     if (!is_image_format_supported(context, CL_MEM_READ_ONLY,
920                                    CL_MEM_OBJECT_IMAGE3D, &image_format_desc))
921     {
922         log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test.");
923         return -1;
924     }
925 
926     /* Verify that we can actually allocate an image that large */
927     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
928                             sizeof(maxAllocSize), &maxAllocSize, NULL);
929     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
930     if ((cl_ulong)maxDimension * 2 * 4 > maxAllocSize)
931     {
932         log_error("Can not allocate a large enough image (min size: %lld "
933                   "bytes, max allowed: %lld bytes) to test.\n",
934                   (cl_ulong)maxDimension * 2 * 4, maxAllocSize);
935         return -1;
936     }
937 
938     log_info("Attempting to create an image of size 1 x %d x 2 = %gMB.\n",
939              (int)maxDimension,
940              (2 * (float)maxDimension * 4 / 1024.0 / 1024.0));
941 
942     /* Try to allocate a very big image */
943     streams[0] = create_image_3d(context, CL_MEM_READ_ONLY, &image_format_desc,
944                                  1, maxDimension, 2, 0, 0, NULL, &error);
945     if ((streams[0] == NULL) || (error != CL_SUCCESS))
946     {
947         print_error(error, "Image 3D creation failed for maximum height");
948         return -1;
949     }
950 
951     return 0;
952 }
953 
954 
test_min_max_image_3d_depth(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)955 int test_min_max_image_3d_depth(cl_device_id deviceID, cl_context context,
956                                 cl_command_queue queue, int num_elements)
957 {
958     int error;
959     size_t maxDimension;
960     clMemWrapper streams[1];
961     cl_image_format image_format_desc;
962     cl_ulong maxAllocSize;
963 
964 
965     PASSIVE_REQUIRE_3D_IMAGE_SUPPORT(deviceID)
966 
967     /* Just get any ol format to test with */
968     error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE3D,
969                                    CL_MEM_READ_ONLY, 0, &image_format_desc);
970     test_error(error, "Unable to obtain suitable image format to test with!");
971 
972     /* Get the max 2d image width */
973     error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE3D_MAX_DEPTH,
974                             sizeof(maxDimension), &maxDimension, NULL);
975     test_error(error, "Unable to get max image 3d depth from device");
976 
977     if (maxDimension < 2048)
978     {
979         log_error(
980             "ERROR: Reported max image 3d depth is less than required! (%d)\n",
981             (int)maxDimension);
982         return -1;
983     }
984     log_info("Max reported depth is %ld.\n", maxDimension);
985 
986     /* Verify we can use the format */
987     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
988     image_format_desc.image_channel_order = CL_RGBA;
989     if (!is_image_format_supported(context, CL_MEM_READ_ONLY,
990                                    CL_MEM_OBJECT_IMAGE3D, &image_format_desc))
991     {
992         log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test.");
993         return -1;
994     }
995 
996     /* Verify that we can actually allocate an image that large */
997     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
998                             sizeof(maxAllocSize), &maxAllocSize, NULL);
999     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
1000     if ((cl_ulong)maxDimension * 1 * 4 > maxAllocSize)
1001     {
1002         log_error("Can not allocate a large enough image (min size: %lld "
1003                   "bytes, max allowed: %lld bytes) to test.\n",
1004                   (cl_ulong)maxDimension * 1 * 4, maxAllocSize);
1005         return -1;
1006     }
1007 
1008     log_info("Attempting to create an image of size 1 x 1 x %d = %gMB.\n",
1009              (int)maxDimension, ((float)maxDimension * 4 / 1024.0 / 1024.0));
1010 
1011     /* Try to allocate a very big image */
1012     streams[0] = create_image_3d(context, CL_MEM_READ_ONLY, &image_format_desc,
1013                                  1, 1, maxDimension, 0, 0, NULL, &error);
1014     if ((streams[0] == NULL) || (error != CL_SUCCESS))
1015     {
1016         print_error(error, "Image 3D creation failed for maximum depth");
1017         return -1;
1018     }
1019 
1020     return 0;
1021 }
1022 
test_min_max_image_array_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1023 int test_min_max_image_array_size(cl_device_id deviceID, cl_context context,
1024                                   cl_command_queue queue, int num_elements)
1025 {
1026     int error;
1027     size_t maxDimension;
1028     clMemWrapper streams[1];
1029     cl_image_format image_format_desc;
1030     cl_ulong maxAllocSize;
1031     size_t minRequiredDimension = gIsEmbedded ? 256 : 2048;
1032 
1033     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID);
1034 
1035     /* Just get any ol format to test with */
1036     error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE2D_ARRAY,
1037                                    CL_MEM_READ_WRITE, 0, &image_format_desc);
1038     test_error(error, "Unable to obtain suitable image format to test with!");
1039 
1040     /* Get the max image array width */
1041     error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE,
1042                             sizeof(maxDimension), &maxDimension, NULL);
1043     test_error(error, "Unable to get max image array size from device");
1044 
1045     if (maxDimension < minRequiredDimension)
1046     {
1047         log_error("ERROR: Reported max image array size is less than required! "
1048                   "(%d)\n",
1049                   (int)maxDimension);
1050         return -1;
1051     }
1052     log_info("Max reported image array size is %ld.\n", maxDimension);
1053 
1054     /* Verify we can use the format */
1055     image_format_desc.image_channel_data_type = CL_UNORM_INT8;
1056     image_format_desc.image_channel_order = CL_RGBA;
1057     if (!is_image_format_supported(context, CL_MEM_READ_ONLY,
1058                                    CL_MEM_OBJECT_IMAGE2D_ARRAY,
1059                                    &image_format_desc))
1060     {
1061         log_error("CL_UNORM_INT8 CL_RGBA not supported. Can not test.");
1062         return -1;
1063     }
1064 
1065     /* Verify that we can actually allocate an image that large */
1066     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
1067                             sizeof(maxAllocSize), &maxAllocSize, NULL);
1068     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
1069     if ((cl_ulong)maxDimension * 1 * 4 > maxAllocSize)
1070     {
1071         log_error("Can not allocate a large enough image (min size: %lld "
1072                   "bytes, max allowed: %lld bytes) to test.\n",
1073                   (cl_ulong)maxDimension * 1 * 4, maxAllocSize);
1074         return -1;
1075     }
1076 
1077     log_info("Attempting to create an image of size 1 x 1 x %d = %gMB.\n",
1078              (int)maxDimension, ((float)maxDimension * 4 / 1024.0 / 1024.0));
1079 
1080     /* Try to allocate a very big image */
1081     streams[0] =
1082         create_image_2d_array(context, CL_MEM_READ_ONLY, &image_format_desc, 1,
1083                               1, maxDimension, 0, 0, NULL, &error);
1084     if ((streams[0] == NULL) || (error != CL_SUCCESS))
1085     {
1086         print_error(error,
1087                     "2D Image Array creation failed for maximum array size");
1088         return -1;
1089     }
1090 
1091     return 0;
1092 }
1093 
test_min_max_image_buffer_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1094 int test_min_max_image_buffer_size(cl_device_id deviceID, cl_context context,
1095                                    cl_command_queue queue, int num_elements)
1096 {
1097     int error;
1098     size_t maxDimensionPixels;
1099     clMemWrapper streams[2];
1100     cl_image_format image_format_desc = { 0 };
1101     cl_ulong maxAllocSize;
1102     size_t minRequiredDimension = gIsEmbedded ? 2048 : 65536;
1103     unsigned int i = 0;
1104     size_t pixelBytes = 0;
1105 
1106     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID);
1107 
1108     /* Get the max memory allocation size */
1109     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
1110                             sizeof(maxAllocSize), &maxAllocSize, NULL);
1111     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE.");
1112 
1113     /* Get the max image array width */
1114     error =
1115         clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE,
1116                         sizeof(maxDimensionPixels), &maxDimensionPixels, NULL);
1117     test_error(error, "Unable to get max image buffer size from device");
1118 
1119     if (maxDimensionPixels < minRequiredDimension)
1120     {
1121         log_error("ERROR: Reported max image buffer size is less than "
1122                   "required! (%d)\n",
1123                   (int)maxDimensionPixels);
1124         return -1;
1125     }
1126     log_info("Max reported image buffer size is %ld pixels.\n",
1127              maxDimensionPixels);
1128 
1129     pixelBytes = maxAllocSize / maxDimensionPixels;
1130     if (pixelBytes == 0)
1131     {
1132         log_error("Value of CL_DEVICE_IMAGE_MAX_BUFFER_SIZE is greater than "
1133                   "CL_MAX_MEM_ALLOC_SIZE so there is no way to allocate image "
1134                   "of maximum size!\n");
1135         return -1;
1136     }
1137 
1138     error = -1;
1139     for (i = pixelBytes; i > 0; --i)
1140     {
1141         error = get_8_bit_image_format(context, CL_MEM_OBJECT_IMAGE1D,
1142                                        CL_MEM_READ_ONLY, i, &image_format_desc);
1143         if (error == CL_SUCCESS)
1144         {
1145             pixelBytes = i;
1146             break;
1147         }
1148     }
1149     test_error(error,
1150                "Device does not support format to be used to allocate image of "
1151                "CL_DEVICE_IMAGE_MAX_BUFFER_SIZE\n");
1152 
1153     log_info("Attempting to create an 1D image with channel order %s from "
1154              "buffer of size %d = %gMB.\n",
1155              GetChannelOrderName(image_format_desc.image_channel_order),
1156              (int)maxDimensionPixels,
1157              ((float)maxDimensionPixels * pixelBytes / 1024.0 / 1024.0));
1158 
1159     /* Try to allocate a buffer */
1160     streams[0] = clCreateBuffer(context, CL_MEM_READ_ONLY,
1161                                 maxDimensionPixels * pixelBytes, NULL, &error);
1162     if ((streams[0] == NULL) || (error != CL_SUCCESS))
1163     {
1164         print_error(error,
1165                     "Buffer creation failed for maximum image buffer size");
1166         return -1;
1167     }
1168 
1169     /* Try to allocate a 1D image array from buffer */
1170     streams[1] =
1171         create_image_1d(context, CL_MEM_READ_ONLY, &image_format_desc,
1172                         maxDimensionPixels, 0, NULL, streams[0], &error);
1173     if ((streams[0] == NULL) || (error != CL_SUCCESS))
1174     {
1175         print_error(error,
1176                     "1D Image from buffer creation failed for maximum image "
1177                     "buffer size");
1178         return -1;
1179     }
1180 
1181     return 0;
1182 }
1183 
1184 
test_min_max_parameter_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1185 int test_min_max_parameter_size(cl_device_id deviceID, cl_context context,
1186                                 cl_command_queue queue, int num_elements)
1187 {
1188     int error, retVal, i;
1189     size_t maxSize;
1190     char *programSrc;
1191     char *ptr;
1192     size_t numberExpected;
1193     long numberOfIntParametersToTry;
1194     char *argumentLine, *codeLines;
1195     void *data;
1196     cl_long long_result, expectedResult;
1197     cl_int int_result;
1198     size_t decrement;
1199     cl_event event;
1200     cl_int event_status;
1201     bool embeddedNoLong = gIsEmbedded && !gHasLong;
1202 
1203 
1204     /* Get the max param size */
1205     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
1206                             sizeof(maxSize), &maxSize, NULL);
1207     test_error(error, "Unable to get max parameter size from device");
1208 
1209 
1210     if (((!gIsEmbedded) && (maxSize < 1024))
1211         || ((gIsEmbedded) && (maxSize < 256)))
1212     {
1213         log_error(
1214             "ERROR: Reported max parameter size is less than required! (%d)\n",
1215             (int)maxSize);
1216         return -1;
1217     }
1218 
1219     /* The embedded profile without cles_khr_int64 extension does not require
1220      * longs, so use ints */
1221     if (embeddedNoLong)
1222         numberOfIntParametersToTry = numberExpected =
1223             (maxSize - sizeof(cl_mem)) / sizeof(cl_int);
1224     else
1225         numberOfIntParametersToTry = numberExpected =
1226             (maxSize - sizeof(cl_mem)) / sizeof(cl_long);
1227 
1228     decrement = (size_t)(numberOfIntParametersToTry / 8);
1229     if (decrement < 1) decrement = 1;
1230     log_info("Reported max parameter size of %d bytes.\n", (int)maxSize);
1231 
1232     while (numberOfIntParametersToTry > 0)
1233     {
1234         // These need to be inside to be deallocated automatically on each loop
1235         // iteration.
1236         clProgramWrapper program;
1237         clMemWrapper mem;
1238         clKernelWrapper kernel;
1239 
1240         if (embeddedNoLong)
1241         {
1242             log_info(
1243                 "Trying a kernel with %ld int arguments (%ld bytes) and one "
1244                 "cl_mem (%ld bytes) for %ld bytes total.\n",
1245                 numberOfIntParametersToTry,
1246                 sizeof(cl_int) * numberOfIntParametersToTry, sizeof(cl_mem),
1247                 sizeof(cl_mem) + numberOfIntParametersToTry * sizeof(cl_int));
1248         }
1249         else
1250         {
1251             log_info(
1252                 "Trying a kernel with %ld long arguments (%ld bytes) and one "
1253                 "cl_mem (%ld bytes) for %ld bytes total.\n",
1254                 numberOfIntParametersToTry,
1255                 sizeof(cl_long) * numberOfIntParametersToTry, sizeof(cl_mem),
1256                 sizeof(cl_mem) + numberOfIntParametersToTry * sizeof(cl_long));
1257         }
1258 
1259         // Allocate memory for the program storage
1260         data = malloc(sizeof(cl_long) * numberOfIntParametersToTry);
1261 
1262         argumentLine =
1263             (char *)malloc(sizeof(char) * numberOfIntParametersToTry * 32);
1264         codeLines =
1265             (char *)malloc(sizeof(char) * numberOfIntParametersToTry * 32);
1266         programSrc = (char *)malloc(sizeof(char)
1267                                     * (numberOfIntParametersToTry * 64 + 1024));
1268         argumentLine[0] = '\0';
1269         codeLines[0] = '\0';
1270         programSrc[0] = '\0';
1271 
1272         // Generate our results
1273         expectedResult = 0;
1274         for (i = 0; i < (int)numberOfIntParametersToTry; i++)
1275         {
1276             if (gHasLong)
1277             {
1278                 ((cl_long *)data)[i] = i;
1279                 expectedResult += i;
1280             }
1281             else
1282             {
1283                 ((cl_int *)data)[i] = i;
1284                 expectedResult += i;
1285             }
1286         }
1287 
1288         // Build the program
1289         if (gHasLong)
1290             sprintf(argumentLine, "%s", "long arg0");
1291         else
1292             sprintf(argumentLine, "%s", "int arg0");
1293 
1294         sprintf(codeLines, "%s", "result[0] += arg0;");
1295         for (i = 1; i < (int)numberOfIntParametersToTry; i++)
1296         {
1297             if (gHasLong)
1298                 sprintf(argumentLine + strlen(argumentLine), ", long arg%d", i);
1299             else
1300                 sprintf(argumentLine + strlen(argumentLine), ", int arg%d", i);
1301 
1302             sprintf(codeLines + strlen(codeLines), "\nresult[0] += arg%d;", i);
1303         }
1304 
1305         /* Create a kernel to test with */
1306         sprintf(programSrc,
1307                 gHasLong ? sample_large_parmam_kernel_pattern[0]
1308                          : sample_large_int_parmam_kernel_pattern[0],
1309                 argumentLine, codeLines);
1310 
1311         ptr = programSrc;
1312         if (create_single_kernel_helper(context, &program, &kernel, 1,
1313                                         (const char **)&ptr, "sample_test")
1314             != 0)
1315         {
1316             log_info("Create program failed, decrementing number of parameters "
1317                      "to try.\n");
1318             numberOfIntParametersToTry -= decrement;
1319             continue;
1320         }
1321 
1322         /* Try to set a large argument to the kernel */
1323         retVal = 0;
1324 
1325         mem = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_long), NULL,
1326                              &error);
1327         test_error(error, "clCreateBuffer failed");
1328 
1329         for (i = 0; i < (int)numberOfIntParametersToTry; i++)
1330         {
1331             if (gHasLong)
1332                 error = clSetKernelArg(kernel, i, sizeof(cl_long),
1333                                        &(((cl_long *)data)[i]));
1334             else
1335                 error = clSetKernelArg(kernel, i, sizeof(cl_int),
1336                                        &(((cl_int *)data)[i]));
1337 
1338             if (error != CL_SUCCESS)
1339             {
1340                 log_info("clSetKernelArg failed (%s), decrementing number of "
1341                          "parameters to try.\n",
1342                          IGetErrorString(error));
1343                 numberOfIntParametersToTry -= decrement;
1344                 break;
1345             }
1346         }
1347         if (error != CL_SUCCESS) continue;
1348 
1349 
1350         error = clSetKernelArg(kernel, i, sizeof(cl_mem), &mem);
1351         if (error != CL_SUCCESS)
1352         {
1353             log_info("clSetKernelArg failed (%s), decrementing number of "
1354                      "parameters to try.\n",
1355                      IGetErrorString(error));
1356             numberOfIntParametersToTry -= decrement;
1357             continue;
1358         }
1359 
1360         size_t globalDim[3] = { 1, 1, 1 }, localDim[3] = { 1, 1, 1 };
1361         error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim,
1362                                        localDim, 0, NULL, &event);
1363         if (error != CL_SUCCESS)
1364         {
1365             log_info("clEnqueueNDRangeKernel failed (%s), decrementing number "
1366                      "of parameters to try.\n",
1367                      IGetErrorString(error));
1368             numberOfIntParametersToTry -= decrement;
1369             continue;
1370         }
1371 
1372         // Verify that the event does not return an error from the execution
1373         error = clWaitForEvents(1, &event);
1374         test_error(error, "clWaitForEvent failed");
1375         error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1376                                sizeof(event_status), &event_status, NULL);
1377         test_error(
1378             error,
1379             "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1380         clReleaseEvent(event);
1381         if (event_status < 0)
1382             test_error(error, "Kernel execution event returned error");
1383 
1384         if (gHasLong)
1385             error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_long),
1386                                         &long_result, 0, NULL, NULL);
1387         else
1388             error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_int),
1389                                         &int_result, 0, NULL, NULL);
1390 
1391         test_error(error, "clEnqueueReadBuffer failed")
1392 
1393             free(data);
1394         free(argumentLine);
1395         free(codeLines);
1396         free(programSrc);
1397 
1398         if (gHasLong)
1399         {
1400             if (long_result != expectedResult)
1401             {
1402                 log_error("Expected result (%lld) does not equal actual result "
1403                           "(%lld).\n",
1404                           expectedResult, long_result);
1405                 numberOfIntParametersToTry -= decrement;
1406                 continue;
1407             }
1408             else
1409             {
1410                 log_info("Results verified at %ld bytes of arguments.\n",
1411                          sizeof(cl_mem)
1412                              + numberOfIntParametersToTry * sizeof(cl_long));
1413                 break;
1414             }
1415         }
1416         else
1417         {
1418             if (int_result != expectedResult)
1419             {
1420                 log_error("Expected result (%lld) does not equal actual result "
1421                           "(%d).\n",
1422                           expectedResult, int_result);
1423                 numberOfIntParametersToTry -= decrement;
1424                 continue;
1425             }
1426             else
1427             {
1428                 log_info("Results verified at %ld bytes of arguments.\n",
1429                          sizeof(cl_mem)
1430                              + numberOfIntParametersToTry * sizeof(cl_int));
1431                 break;
1432             }
1433         }
1434     }
1435 
1436     if (numberOfIntParametersToTry == (long)numberExpected) return 0;
1437     return -1;
1438 }
1439 
test_min_max_samplers(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1440 int test_min_max_samplers(cl_device_id deviceID, cl_context context,
1441                           cl_command_queue queue, int num_elements)
1442 {
1443     int error;
1444     cl_uint maxSamplers, i;
1445     clProgramWrapper program;
1446     clKernelWrapper kernel;
1447     char *programSrc, samplerLine[1024];
1448     size_t maxParameterSize;
1449     cl_event event;
1450     cl_int event_status;
1451     cl_uint minRequiredSamplers = gIsEmbedded ? 8 : 16;
1452 
1453 
1454     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
1455 
1456     /* Get the max value */
1457     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_SAMPLERS,
1458                             sizeof(maxSamplers), &maxSamplers, NULL);
1459     test_error(error, "Unable to get max sampler count from device");
1460 
1461     if (maxSamplers < minRequiredSamplers)
1462     {
1463         log_error(
1464             "ERROR: Reported max sampler count is less than required! (%d)\n",
1465             (int)maxSamplers);
1466         return -1;
1467     }
1468 
1469     log_info("Reported max %d samplers.\n", maxSamplers);
1470 
1471     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
1472                             sizeof(maxParameterSize), &maxParameterSize, NULL);
1473     test_error(error, "Unable to get max parameter size from device");
1474 
1475     // Subtract the size of the result
1476     maxParameterSize -= 2 * sizeof(cl_mem);
1477 
1478     // Calculate the number we can use
1479     if (maxParameterSize / sizeof(cl_sampler) < maxSamplers)
1480     {
1481         log_info("WARNING: Max parameter size of %d bytes limits test to %d "
1482                  "max sampler arguments.\n",
1483                  (int)maxParameterSize,
1484                  (int)(maxParameterSize / sizeof(cl_sampler)));
1485         maxSamplers = (unsigned int)(maxParameterSize / sizeof(cl_sampler));
1486     }
1487 
1488     /* Create a kernel to test with */
1489     programSrc = (char *)malloc(
1490         (strlen(sample_sampler_kernel_pattern[1]) + 8) * (maxSamplers)
1491         + strlen(sample_sampler_kernel_pattern[0])
1492         + strlen(sample_sampler_kernel_pattern[2])
1493         + (strlen(sample_sampler_kernel_pattern[3]) + 8) * maxSamplers
1494         + strlen(sample_sampler_kernel_pattern[4]));
1495     strcpy(programSrc, sample_sampler_kernel_pattern[0]);
1496     for (i = 0; i < maxSamplers; i++)
1497     {
1498         sprintf(samplerLine, sample_sampler_kernel_pattern[1], i);
1499         strcat(programSrc, samplerLine);
1500     }
1501     strcat(programSrc, sample_sampler_kernel_pattern[2]);
1502     for (i = 0; i < maxSamplers; i++)
1503     {
1504         sprintf(samplerLine, sample_sampler_kernel_pattern[3], i);
1505         strcat(programSrc, samplerLine);
1506     }
1507     strcat(programSrc, sample_sampler_kernel_pattern[4]);
1508 
1509 
1510     error =
1511         create_single_kernel_helper(context, &program, &kernel, 1,
1512                                     (const char **)&programSrc, "sample_test");
1513     test_error(error, "Failed to create the program and kernel.");
1514 
1515     // We have to set up some fake parameters so it'll work
1516     clSamplerWrapper *samplers = new clSamplerWrapper[maxSamplers];
1517 
1518     cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
1519 
1520     clMemWrapper image = create_image_2d(context, CL_MEM_READ_WRITE, &format,
1521                                          16, 16, 0, NULL, &error);
1522     test_error(error, "Unable to create a test image");
1523 
1524     clMemWrapper stream =
1525         clCreateBuffer(context, CL_MEM_READ_WRITE, 16, NULL, &error);
1526     test_error(error, "Unable to create test buffer");
1527 
1528     error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &image);
1529     error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &stream);
1530     test_error(error, "Unable to set kernel arguments");
1531     for (i = 0; i < maxSamplers; i++)
1532     {
1533         samplers[i] = clCreateSampler(context, CL_FALSE, CL_ADDRESS_NONE,
1534                                       CL_FILTER_NEAREST, &error);
1535         test_error(error, "Unable to create sampler");
1536 
1537         error = clSetKernelArg(kernel, 2 + i, sizeof(cl_sampler), &samplers[i]);
1538         test_error(error, "Unable to set sampler argument");
1539     }
1540 
1541     size_t globalDim[3] = { 1, 1, 1 }, localDim[3] = { 1, 1, 1 };
1542     error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim, localDim,
1543                                    0, NULL, &event);
1544     test_error(
1545         error,
1546         "clEnqueueNDRangeKernel failed with maximum number of samplers.");
1547 
1548     // Verify that the event does not return an error from the execution
1549     error = clWaitForEvents(1, &event);
1550     test_error(error, "clWaitForEvent failed");
1551     error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1552                            sizeof(event_status), &event_status, NULL);
1553     test_error(error,
1554                "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1555     clReleaseEvent(event);
1556     if (event_status < 0)
1557         test_error(error, "Kernel execution event returned error");
1558 
1559     free(programSrc);
1560     delete[] samplers;
1561     return 0;
1562 }
1563 
1564 #define PASSING_FRACTION 4
test_min_max_constant_buffer_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1565 int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context,
1566                                       cl_command_queue queue, int num_elements)
1567 {
1568     int error;
1569     clProgramWrapper program;
1570     clKernelWrapper kernel;
1571     size_t threads[1], localThreads[1];
1572     cl_int *constantData, *resultData;
1573     cl_ulong maxSize, stepSize, currentSize, maxGlobalSize, maxAllocSize;
1574     int i;
1575     cl_event event;
1576     cl_int event_status;
1577     MTdata d;
1578 
1579     /* Verify our test buffer won't be bigger than allowed */
1580     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
1581                             sizeof(maxSize), &maxSize, 0);
1582     test_error(error, "Unable to get max constant buffer size");
1583 
1584     if ((0 == gIsEmbedded && maxSize < 64L * 1024L) || maxSize < 1L * 1024L)
1585     {
1586         log_error("ERROR: Reported max constant buffer size less than required "
1587                   "by OpenCL 1.0 (reported %d KB)\n",
1588                   (int)(maxSize / 1024L));
1589         return -1;
1590     }
1591 
1592     log_info("Reported max constant buffer size of %lld bytes.\n", maxSize);
1593 
1594     // Limit test buffer size to 1/8 of CL_DEVICE_GLOBAL_MEM_SIZE
1595     error = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE,
1596                             sizeof(maxGlobalSize), &maxGlobalSize, 0);
1597     test_error(error, "Unable to get CL_DEVICE_GLOBAL_MEM_SIZE");
1598 
1599     if (maxSize > maxGlobalSize / 8) maxSize = maxGlobalSize / 8;
1600 
1601     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
1602                             sizeof(maxAllocSize), &maxAllocSize, 0);
1603     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE ");
1604 
1605     if (maxSize > maxAllocSize) maxSize = maxAllocSize;
1606 
1607     /* Create a kernel to test with */
1608     if (create_single_kernel_helper(context, &program, &kernel, 1,
1609                                     sample_const_arg_kernel, "sample_test")
1610         != 0)
1611     {
1612         return -1;
1613     }
1614 
1615     /* Try the returned max size and decrease it until we get one that works. */
1616     stepSize = maxSize / 16;
1617     currentSize = maxSize;
1618     int allocPassed = 0;
1619     d = init_genrand(gRandomSeed);
1620     while (!allocPassed && currentSize >= maxSize / PASSING_FRACTION)
1621     {
1622         log_info("Attempting to allocate constant buffer of size %lld bytes\n",
1623                  maxSize);
1624 
1625         /* Create some I/O streams */
1626         size_t sizeToAllocate =
1627             ((size_t)currentSize / sizeof(cl_int)) * sizeof(cl_int);
1628         size_t numberOfInts = sizeToAllocate / sizeof(cl_int);
1629         constantData = (cl_int *)malloc(sizeToAllocate);
1630         if (constantData == NULL)
1631         {
1632             log_error("Failed to allocate memory for constantData!\n");
1633             free_mtdata(d);
1634             return EXIT_FAILURE;
1635         }
1636 
1637         for (i = 0; i < (int)(numberOfInts); i++)
1638             constantData[i] = (int)genrand_int32(d);
1639 
1640         clMemWrapper streams[3];
1641         streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
1642                                     sizeToAllocate, constantData, &error);
1643         test_error(error, "Creating test array failed");
1644         streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeToAllocate,
1645                                     NULL, &error);
1646         test_error(error, "Creating test array failed");
1647 
1648 
1649         /* Set the arguments */
1650         error = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]);
1651         test_error(error, "Unable to set indexed kernel arguments");
1652         error = clSetKernelArg(kernel, 1, sizeof(streams[1]), &streams[1]);
1653         test_error(error, "Unable to set indexed kernel arguments");
1654 
1655 
1656         /* Test running the kernel and verifying it */
1657         threads[0] = numberOfInts;
1658         localThreads[0] = 1;
1659         log_info("Filling constant buffer with %d cl_ints (%d bytes).\n",
1660                  (int)threads[0], (int)(threads[0] * sizeof(cl_int)));
1661 
1662         error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads,
1663                                        localThreads, 0, NULL, &event);
1664         /* If we failed due to a resource issue, reduce the size and try again.
1665          */
1666         if ((error == CL_OUT_OF_RESOURCES)
1667             || (error == CL_MEM_OBJECT_ALLOCATION_FAILURE)
1668             || (error == CL_OUT_OF_HOST_MEMORY))
1669         {
1670             log_info("Kernel enqueue failed at size %lld, trying at a reduced "
1671                      "size.\n",
1672                      currentSize);
1673             currentSize -= stepSize;
1674             free(constantData);
1675             continue;
1676         }
1677         test_error(
1678             error,
1679             "clEnqueueNDRangeKernel with maximum constant buffer size failed.");
1680 
1681         // Verify that the event does not return an error from the execution
1682         error = clWaitForEvents(1, &event);
1683         test_error(error, "clWaitForEvent failed");
1684         error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1685                                sizeof(event_status), &event_status, NULL);
1686         test_error(
1687             error,
1688             "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1689         clReleaseEvent(event);
1690         if (event_status < 0)
1691         {
1692             if ((event_status == CL_OUT_OF_RESOURCES)
1693                 || (event_status == CL_MEM_OBJECT_ALLOCATION_FAILURE)
1694                 || (event_status == CL_OUT_OF_HOST_MEMORY))
1695             {
1696                 log_info("Kernel event indicates failure at size %lld, trying "
1697                          "at a reduced size.\n",
1698                          currentSize);
1699                 currentSize -= stepSize;
1700                 free(constantData);
1701                 continue;
1702             }
1703             else
1704             {
1705                 test_error(error, "Kernel execution event returned error");
1706             }
1707         }
1708 
1709         /* Otherwise we did not fail due to resource issues. */
1710         allocPassed = 1;
1711 
1712         resultData = (cl_int *)malloc(sizeToAllocate);
1713         if (resultData == NULL)
1714         {
1715             log_error("Failed to allocate memory for resultData!\n");
1716             free(constantData);
1717             free_mtdata(d);
1718             return EXIT_FAILURE;
1719         }
1720 
1721         error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0,
1722                                     sizeToAllocate, resultData, 0, NULL, NULL);
1723         test_error(error, "clEnqueueReadBuffer failed");
1724 
1725         for (i = 0; i < (int)(numberOfInts); i++)
1726             if (constantData[i] != resultData[i])
1727             {
1728                 log_error("Data failed to verify: constantData[%d]=%d != "
1729                           "resultData[%d]=%d\n",
1730                           i, constantData[i], i, resultData[i]);
1731                 free(constantData);
1732                 free(resultData);
1733                 free_mtdata(d);
1734                 d = NULL;
1735                 return -1;
1736             }
1737 
1738         free(constantData);
1739         free(resultData);
1740     }
1741     free_mtdata(d);
1742     d = NULL;
1743 
1744     if (allocPassed)
1745     {
1746         if (currentSize < maxSize / PASSING_FRACTION)
1747         {
1748             log_error("Failed to allocate at least 1/8 of the reported "
1749                       "constant size.\n");
1750             return -1;
1751         }
1752         else if (currentSize != maxSize)
1753         {
1754             log_info("Passed at reduced size. (%lld of %lld bytes)\n",
1755                      currentSize, maxSize);
1756             return 0;
1757         }
1758         return 0;
1759     }
1760     return -1;
1761 }
1762 
test_min_max_constant_args(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1763 int test_min_max_constant_args(cl_device_id deviceID, cl_context context,
1764                                cl_command_queue queue, int num_elements)
1765 {
1766     int error;
1767     clProgramWrapper program;
1768     clKernelWrapper kernel;
1769     clMemWrapper *streams;
1770     size_t threads[1], localThreads[1];
1771     cl_uint i, maxArgs;
1772     cl_ulong maxSize;
1773     cl_ulong maxParameterSize;
1774     size_t individualBufferSize;
1775     char *programSrc, *constArgs, *str2;
1776     char str[512];
1777     const char *ptr;
1778     cl_event event;
1779     cl_int event_status;
1780 
1781 
1782     /* Verify our test buffer won't be bigger than allowed */
1783     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_CONSTANT_ARGS,
1784                             sizeof(maxArgs), &maxArgs, 0);
1785     test_error(error, "Unable to get max constant arg count");
1786 
1787     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
1788                             sizeof(maxParameterSize), &maxParameterSize, NULL);
1789     test_error(error, "Unable to get max parameter size from device");
1790 
1791     // Subtract the size of the result
1792     maxParameterSize -= sizeof(cl_mem);
1793 
1794     // Calculate the number we can use
1795     if (maxParameterSize / sizeof(cl_mem) < maxArgs)
1796     {
1797         log_info("WARNING: Max parameter size of %d bytes limits test to %d "
1798                  "max image arguments.\n",
1799                  (int)maxParameterSize,
1800                  (int)(maxParameterSize / sizeof(cl_mem)));
1801         maxArgs = (unsigned int)(maxParameterSize / sizeof(cl_mem));
1802     }
1803 
1804 
1805     if (maxArgs < (gIsEmbedded ? 4 : 8))
1806     {
1807         log_error("ERROR: Reported max constant arg count less than required "
1808                   "by OpenCL 1.0 (reported %d)\n",
1809                   (int)maxArgs);
1810         return -1;
1811     }
1812 
1813     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
1814                             sizeof(maxSize), &maxSize, 0);
1815     test_error(error, "Unable to get max constant buffer size");
1816     individualBufferSize = (maxSize / 2) / maxArgs;
1817 
1818     log_info(
1819         "Reported max constant arg count of %u and max constant buffer "
1820         "size of %llu. Test will attempt to allocate half of that, or %llu "
1821         "buffers of size %zu.\n",
1822         maxArgs, maxSize, maxArgs, individualBufferSize);
1823 
1824     str2 = (char *)malloc(sizeof(char) * 32 * (maxArgs + 2));
1825     constArgs = (char *)malloc(sizeof(char) * 32 * (maxArgs + 2));
1826     programSrc = (char *)malloc(sizeof(char) * 32 * 2 * (maxArgs + 2) + 1024);
1827 
1828     /* Create a test program */
1829     constArgs[0] = 0;
1830     str2[0] = 0;
1831     for (i = 0; i < maxArgs - 1; i++)
1832     {
1833         sprintf(str, ", __constant int *src%d", (int)(i + 2));
1834         strcat(constArgs, str);
1835         sprintf(str2 + strlen(str2), "\tdst[tid] += src%d[tid];\n",
1836                 (int)(i + 2));
1837         if (strlen(str2) > (sizeof(char) * 32 * (maxArgs + 2) - 32)
1838             || strlen(constArgs) > (sizeof(char) * 32 * (maxArgs + 2) - 32))
1839         {
1840             log_info("Limiting number of arguments tested to %d due to test "
1841                      "program allocation size.\n",
1842                      i);
1843             break;
1844         }
1845     }
1846     sprintf(programSrc, sample_const_max_arg_kernel_pattern, constArgs, str2);
1847 
1848     /* Create a kernel to test with */
1849     ptr = programSrc;
1850     if (create_single_kernel_helper(context, &program, &kernel, 1, &ptr,
1851                                     "sample_test")
1852         != 0)
1853     {
1854         return -1;
1855     }
1856 
1857     /* Create some I/O streams */
1858     streams = new clMemWrapper[maxArgs + 1];
1859     for (i = 0; i < maxArgs + 1; i++)
1860     {
1861         streams[i] = clCreateBuffer(context, CL_MEM_READ_WRITE,
1862                                     individualBufferSize, NULL, &error);
1863         test_error(error, "Creating test array failed");
1864     }
1865 
1866     /* Set the arguments */
1867     for (i = 0; i < maxArgs + 1; i++)
1868     {
1869         error = clSetKernelArg(kernel, i, sizeof(streams[i]), &streams[i]);
1870         test_error(error, "Unable to set kernel argument");
1871     }
1872 
1873     /* Test running the kernel and verifying it */
1874     threads[0] = (size_t)10;
1875     while (threads[0] * sizeof(cl_int) > individualBufferSize) threads[0]--;
1876 
1877     error = get_max_common_work_group_size(context, kernel, threads[0],
1878                                            &localThreads[0]);
1879     test_error(error, "Unable to get work group size to use");
1880 
1881     error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads,
1882                                    localThreads, 0, NULL, &event);
1883     test_error(error, "clEnqueueNDRangeKernel failed");
1884 
1885     // Verify that the event does not return an error from the execution
1886     error = clWaitForEvents(1, &event);
1887     test_error(error, "clWaitForEvent failed");
1888     error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1889                            sizeof(event_status), &event_status, NULL);
1890     test_error(error,
1891                "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1892     clReleaseEvent(event);
1893     if (event_status < 0)
1894         test_error(error, "Kernel execution event returned error");
1895 
1896     error = clFinish(queue);
1897     test_error(error, "clFinish failed.");
1898 
1899     delete[] streams;
1900     free(str2);
1901     free(constArgs);
1902     free(programSrc);
1903     return 0;
1904 }
1905 
test_min_max_compute_units(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1906 int test_min_max_compute_units(cl_device_id deviceID, cl_context context,
1907                                cl_command_queue queue, int num_elements)
1908 {
1909     int error;
1910     cl_uint value;
1911 
1912 
1913     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS,
1914                             sizeof(value), &value, 0);
1915     test_error(error, "Unable to get compute unit count");
1916 
1917     if (value < 1)
1918     {
1919         log_error("ERROR: Reported compute unit count less than required by "
1920                   "OpenCL 1.0 (reported %d)\n",
1921                   (int)value);
1922         return -1;
1923     }
1924 
1925     log_info("Reported %d max compute units.\n", value);
1926 
1927     return 0;
1928 }
1929 
test_min_max_address_bits(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1930 int test_min_max_address_bits(cl_device_id deviceID, cl_context context,
1931                               cl_command_queue queue, int num_elements)
1932 {
1933     int error;
1934     cl_uint value;
1935 
1936 
1937     error = clGetDeviceInfo(deviceID, CL_DEVICE_ADDRESS_BITS, sizeof(value),
1938                             &value, 0);
1939     test_error(error, "Unable to get address bit count");
1940 
1941     if (value != 32 && value != 64)
1942     {
1943         log_error("ERROR: Reported address bit count not valid by OpenCL 1.0 "
1944                   "(reported %d)\n",
1945                   (int)value);
1946         return -1;
1947     }
1948 
1949     log_info("Reported %d device address bits.\n", value);
1950 
1951     return 0;
1952 }
1953 
test_min_max_single_fp_config(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1954 int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context,
1955                                   cl_command_queue queue, int num_elements)
1956 {
1957     int error;
1958     cl_device_fp_config value;
1959     char profile[128] = "";
1960 
1961     error = clGetDeviceInfo(deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(value),
1962                             &value, 0);
1963     test_error(error, "Unable to get device single fp config");
1964 
1965     // Check to see if we are an embedded profile device
1966     if ((error = clGetDeviceInfo(deviceID, CL_DEVICE_PROFILE, sizeof(profile),
1967                                  profile, NULL)))
1968     {
1969         log_error("FAILURE: Unable to get CL_DEVICE_PROFILE: error %d\n",
1970                   error);
1971         return error;
1972     }
1973 
1974     if (0 == strcmp(profile, "EMBEDDED_PROFILE"))
1975     { // embedded device
1976 
1977         if (0 == (value & (CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO)))
1978         {
1979             log_error("FAILURE: embedded device supports neither "
1980                       "CL_FP_ROUND_TO_NEAREST or CL_FP_ROUND_TO_ZERO\n");
1981             return -1;
1982         }
1983     }
1984     else
1985     { // Full profile
1986         if ((value & (CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN))
1987             != (CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN))
1988         {
1989             log_error("ERROR: Reported single fp config doesn't meet minimum "
1990                       "set by OpenCL 1.0 (reported 0x%08x)\n",
1991                       (int)value);
1992             return -1;
1993         }
1994     }
1995     return 0;
1996 }
1997 
test_min_max_double_fp_config(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1998 int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context,
1999                                   cl_command_queue queue, int num_elements)
2000 {
2001     int error;
2002     cl_device_fp_config value;
2003 
2004     error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof(value),
2005                             &value, 0);
2006     test_error(error, "Unable to get device double fp config");
2007 
2008     if (value == 0) return 0;
2009 
2010     if ((value
2011          & (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO
2012             | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM))
2013         != (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO
2014             | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM))
2015     {
2016         log_error("ERROR: Reported double fp config doesn't meet minimum set "
2017                   "by OpenCL 1.0 (reported 0x%08x)\n",
2018                   (int)value);
2019         return -1;
2020     }
2021     return 0;
2022 }
2023 
test_min_max_local_mem_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2024 int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context,
2025                                 cl_command_queue queue, int num_elements)
2026 {
2027     int error;
2028     clProgramWrapper program;
2029     clKernelWrapper kernel;
2030     clMemWrapper streams[3];
2031     size_t threads[1], localThreads[1];
2032     cl_int *localData, *resultData;
2033     cl_ulong maxSize, kernelLocalUsage, min_max_local_mem_size;
2034     Version device_version;
2035     int i;
2036     int err = 0;
2037     MTdata d;
2038 
2039     /* Verify our test buffer won't be bigger than allowed */
2040     error = clGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(maxSize),
2041                             &maxSize, 0);
2042     test_error(error, "Unable to get max local buffer size");
2043 
2044     try
2045     {
2046         device_version = get_device_cl_version(deviceID);
2047     } catch (const std::runtime_error &e)
2048     {
2049         log_error("%s", e.what());
2050         return -1;
2051     }
2052 
2053     if (!gIsEmbedded)
2054     {
2055         if (device_version == Version(1, 0))
2056             min_max_local_mem_size = 16L * 1024L;
2057         else
2058             min_max_local_mem_size = 32L * 1024L;
2059     }
2060     else
2061     {
2062         min_max_local_mem_size = 1L * 1024L;
2063     }
2064 
2065     if (maxSize < min_max_local_mem_size)
2066     {
2067         const std::string version_as_string = device_version.to_string();
2068         log_error("ERROR: Reported local mem size less than required by OpenCL "
2069                   "%s (reported %d KB)\n",
2070                   version_as_string.c_str(), (int)(maxSize / 1024L));
2071         return -1;
2072     }
2073 
2074     log_info("Reported max local buffer size for device: %lld bytes.\n",
2075              maxSize);
2076 
2077     /* Create a kernel to test with */
2078     if (create_single_kernel_helper(context, &program, &kernel, 1,
2079                                     sample_local_arg_kernel, "sample_test")
2080         != 0)
2081     {
2082         return -1;
2083     }
2084 
2085     error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_MEM_SIZE,
2086                                      sizeof(kernelLocalUsage),
2087                                      &kernelLocalUsage, NULL);
2088     test_error(error,
2089                "clGetKernelWorkGroupInfo for CL_KERNEL_LOCAL_MEM_SIZE failed");
2090 
2091     log_info("Reported local buffer usage for kernel "
2092              "(CL_KERNEL_LOCAL_MEM_SIZE): %lld bytes.\n",
2093              kernelLocalUsage);
2094 
2095     /* Create some I/O streams */
2096     size_t sizeToAllocate =
2097         ((size_t)(maxSize - kernelLocalUsage) / sizeof(cl_int))
2098         * sizeof(cl_int);
2099     size_t numberOfInts = sizeToAllocate / sizeof(cl_int);
2100 
2101     log_info("Attempting to use %zu bytes of local memory.\n", sizeToAllocate);
2102 
2103     localData = (cl_int *)malloc(sizeToAllocate);
2104     d = init_genrand(gRandomSeed);
2105     for (i = 0; i < (int)(numberOfInts); i++)
2106         localData[i] = (int)genrand_int32(d);
2107     free_mtdata(d);
2108     d = NULL;
2109 
2110     streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeToAllocate,
2111                                 localData, &error);
2112     test_error(error, "Creating test array failed");
2113     streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeToAllocate,
2114                                 NULL, &error);
2115     test_error(error, "Creating test array failed");
2116 
2117 
2118     /* Set the arguments */
2119     error = clSetKernelArg(kernel, 0, sizeToAllocate, NULL);
2120     test_error(error, "Unable to set indexed kernel arguments");
2121     error = clSetKernelArg(kernel, 1, sizeof(streams[0]), &streams[0]);
2122     test_error(error, "Unable to set indexed kernel arguments");
2123     error = clSetKernelArg(kernel, 2, sizeof(streams[1]), &streams[1]);
2124     test_error(error, "Unable to set indexed kernel arguments");
2125 
2126 
2127     /* Test running the kernel and verifying it */
2128     threads[0] = numberOfInts;
2129     localThreads[0] = 1;
2130     log_info("Creating local buffer with %zu cl_ints (%zu bytes).\n",
2131              numberOfInts, sizeToAllocate);
2132 
2133     cl_event evt;
2134     cl_int evt_err;
2135     error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads,
2136                                    localThreads, 0, NULL, &evt);
2137     test_error(error, "clEnqueueNDRangeKernel failed");
2138 
2139     error = clFinish(queue);
2140     test_error(error, "clFinish failed");
2141 
2142     error = clGetEventInfo(evt, CL_EVENT_COMMAND_EXECUTION_STATUS,
2143                            sizeof evt_err, &evt_err, NULL);
2144     test_error(error, "clGetEventInfo with maximum local buffer size failed.");
2145 
2146     if (evt_err != CL_COMPLETE)
2147     {
2148         print_error(evt_err, "Kernel event returned error");
2149         clReleaseEvent(evt);
2150         return -1;
2151     }
2152 
2153     resultData = (cl_int *)malloc(sizeToAllocate);
2154 
2155     error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, sizeToAllocate,
2156                                 resultData, 0, NULL, NULL);
2157     test_error(error, "clEnqueueReadBuffer failed");
2158 
2159     for (i = 0; i < (int)(numberOfInts); i++)
2160         if (localData[i] != resultData[i])
2161         {
2162             clReleaseEvent(evt);
2163             free(localData);
2164             free(resultData);
2165             log_error("Results failed to verify.\n");
2166             return -1;
2167         }
2168     clReleaseEvent(evt);
2169     free(localData);
2170     free(resultData);
2171 
2172     return err;
2173 }
2174 
test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2175 int test_min_max_kernel_preferred_work_group_size_multiple(
2176     cl_device_id deviceID, cl_context context, cl_command_queue queue,
2177     int num_elements)
2178 {
2179     int err;
2180     clProgramWrapper program;
2181     clKernelWrapper kernel;
2182 
2183     size_t max_local_workgroup_size[3];
2184     size_t max_workgroup_size = 0, preferred_workgroup_size = 0;
2185 
2186     err = create_single_kernel_helper(context, &program, &kernel, 1,
2187                                       sample_local_arg_kernel, "sample_test");
2188     test_error(err, "Failed to build kernel/program.");
2189 
2190     err = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE,
2191                                    sizeof(max_workgroup_size),
2192                                    &max_workgroup_size, NULL);
2193     test_error(err, "clGetKernelWorkgroupInfo failed.");
2194 
2195     err = clGetKernelWorkGroupInfo(
2196         kernel, deviceID, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,
2197         sizeof(preferred_workgroup_size), &preferred_workgroup_size, NULL);
2198     test_error(err, "clGetKernelWorkgroupInfo failed.");
2199 
2200     err = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES,
2201                           sizeof(max_local_workgroup_size),
2202                           max_local_workgroup_size, NULL);
2203     test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES");
2204 
2205     // Since the preferred size is only a performance hint, we can only really
2206     // check that we get a sane value back
2207     log_info("size: %ld     preferred: %ld      max: %ld\n", max_workgroup_size,
2208              preferred_workgroup_size, max_local_workgroup_size[0]);
2209 
2210     if (preferred_workgroup_size > max_workgroup_size)
2211     {
2212         log_error("ERROR: Reported preferred workgroup multiple larger than "
2213                   "max workgroup size (preferred %ld, max %ld)\n",
2214                   preferred_workgroup_size, max_workgroup_size);
2215         return -1;
2216     }
2217 
2218     return 0;
2219 }
2220 
test_min_max_execution_capabilities(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2221 int test_min_max_execution_capabilities(cl_device_id deviceID,
2222                                         cl_context context,
2223                                         cl_command_queue queue,
2224                                         int num_elements)
2225 {
2226     int error;
2227     cl_device_exec_capabilities value;
2228 
2229 
2230     error = clGetDeviceInfo(deviceID, CL_DEVICE_EXECUTION_CAPABILITIES,
2231                             sizeof(value), &value, 0);
2232     test_error(error, "Unable to get execution capabilities");
2233 
2234     if ((value & CL_EXEC_KERNEL) != CL_EXEC_KERNEL)
2235     {
2236         log_error("ERROR: Reported execution capabilities less than required "
2237                   "by OpenCL 1.0 (reported 0x%08x)\n",
2238                   (int)value);
2239         return -1;
2240     }
2241     return 0;
2242 }
2243 
test_min_max_queue_properties(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2244 int test_min_max_queue_properties(cl_device_id deviceID, cl_context context,
2245                                   cl_command_queue queue, int num_elements)
2246 {
2247     int error;
2248     cl_command_queue_properties value;
2249 
2250 
2251     error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
2252                             sizeof(value), &value, 0);
2253     test_error(error, "Unable to get queue properties");
2254 
2255     if ((value & CL_QUEUE_PROFILING_ENABLE) != CL_QUEUE_PROFILING_ENABLE)
2256     {
2257         log_error("ERROR: Reported queue properties less than required by "
2258                   "OpenCL 1.0 (reported 0x%08x)\n",
2259                   (int)value);
2260         return -1;
2261     }
2262     return 0;
2263 }
2264 
test_min_max_device_version(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2265 int test_min_max_device_version(cl_device_id deviceID, cl_context context,
2266                                 cl_command_queue queue, int num_elements)
2267 {
2268     // Query for the device version.
2269     Version device_cl_version = get_device_cl_version(deviceID);
2270     log_info("Returned version %s.\n", device_cl_version.to_string().c_str());
2271 
2272     // Make sure 2.x devices support required extensions for 2.x
2273     // note: these extensions are **not** required for devices
2274     // supporting OpenCL-3.0
2275     const char *requiredExtensions2x[] = {
2276         "cl_khr_3d_image_writes",
2277         "cl_khr_image2d_from_buffer",
2278         "cl_khr_depth_images",
2279     };
2280 
2281     // Make sure 1.1 devices support required extensions for 1.1
2282     const char *requiredExtensions11[] = {
2283         "cl_khr_global_int32_base_atomics",
2284         "cl_khr_global_int32_extended_atomics",
2285         "cl_khr_local_int32_base_atomics",
2286         "cl_khr_local_int32_extended_atomics",
2287         "cl_khr_byte_addressable_store",
2288     };
2289 
2290 
2291     if (device_cl_version >= Version(1, 1))
2292     {
2293         log_info("Checking for required extensions for OpenCL 1.1 and later "
2294                  "devices...\n");
2295         for (int i = 0; i < ARRAY_SIZE(requiredExtensions11); i++)
2296         {
2297             if (!is_extension_available(deviceID, requiredExtensions11[i]))
2298             {
2299                 log_error("ERROR: Required extension for 1.1 and greater "
2300                           "devices is not in extension string: %s\n",
2301                           requiredExtensions11[i]);
2302                 return -1;
2303             }
2304             else
2305                 log_info("\t%s\n", requiredExtensions11[i]);
2306         }
2307 
2308         if (device_cl_version >= Version(1, 2))
2309         {
2310             log_info("Checking for required extensions for OpenCL 1.2 and "
2311                      "later devices...\n");
2312             // The only required extension for an OpenCL-1.2 device is
2313             // cl_khr_fp64 and it is only required if double precision is
2314             // supported.
2315             cl_device_fp_config doubles_supported;
2316             cl_int error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG,
2317                                            sizeof(doubles_supported),
2318                                            &doubles_supported, 0);
2319             test_error(error, "Unable to get device double fp config");
2320             if (doubles_supported)
2321             {
2322                 if (!is_extension_available(deviceID, "cl_khr_fp64"))
2323                 {
2324                     log_error(
2325                         "ERROR: Required extension for 1.2 and greater devices "
2326                         "is not in extension string: cl_khr_fp64\n");
2327                 }
2328                 else
2329                 {
2330                     log_info("\t%s\n", "cl_khr_fp64");
2331                 }
2332             }
2333         }
2334 
2335         if (device_cl_version >= Version(2, 0)
2336             && device_cl_version < Version(3, 0))
2337         {
2338             log_info("Checking for required extensions for OpenCL 2.0, 2.1 and "
2339                      "2.2 devices...\n");
2340             for (int i = 0; i < ARRAY_SIZE(requiredExtensions2x); i++)
2341             {
2342                 if (!is_extension_available(deviceID, requiredExtensions2x[i]))
2343                 {
2344                     log_error("ERROR: Required extension for 2.0, 2.1 and 2.2 "
2345                               "devices is not in extension string: %s\n",
2346                               requiredExtensions2x[i]);
2347                     return -1;
2348                 }
2349                 else
2350                 {
2351                     log_info("\t%s\n", requiredExtensions2x[i]);
2352                 }
2353             }
2354         }
2355     }
2356     else
2357         log_info("WARNING: skipping required extension test -- OpenCL 1.0 "
2358                  "device.\n");
2359     return 0;
2360 }
2361 
test_min_max_language_version(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2362 int test_min_max_language_version(cl_device_id deviceID, cl_context context,
2363                                   cl_command_queue queue, int num_elements)
2364 {
2365     cl_int error;
2366     cl_char buffer[4098];
2367     size_t length;
2368 
2369     // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*"
2370     error = clGetDeviceInfo(deviceID, CL_DEVICE_OPENCL_C_VERSION,
2371                             sizeof(buffer), buffer, &length);
2372     test_error(error, "Unable to get device opencl c version string");
2373     if (memcmp(buffer, "OpenCL C ", strlen("OpenCL C ")) != 0)
2374     {
2375         log_error("ERROR: Initial part of device language version string does "
2376                   "not match required format! (returned: \"%s\")\n",
2377                   (char *)buffer);
2378         return -1;
2379     }
2380 
2381     log_info("Returned version \"%s\".\n", buffer);
2382 
2383     char *p1 = (char *)buffer + strlen("OpenCL C ");
2384     while (*p1 == ' ') p1++;
2385     char *p2 = p1;
2386     if (!isdigit(*p2))
2387     {
2388         log_error("ERROR: Major revision number must follow space behind "
2389                   "OpenCL C! (returned %s)\n",
2390                   (char *)buffer);
2391         return -1;
2392     }
2393     while (isdigit(*p2)) p2++;
2394     if (*p2 != '.')
2395     {
2396         log_error("ERROR: Version number must contain a decimal point! "
2397                   "(returned: %s)\n",
2398                   (char *)buffer);
2399         return -1;
2400     }
2401     char *p3 = p2 + 1;
2402     if (!isdigit(*p3))
2403     {
2404         log_error("ERROR: Minor revision number is missing or does not abut "
2405                   "the decimal point! (returned %s)\n",
2406                   (char *)buffer);
2407         return -1;
2408     }
2409     while (isdigit(*p3)) p3++;
2410     if (*p3 != ' ')
2411     {
2412         log_error("ERROR: A space must appear after the minor version! "
2413                   "(returned: %s)\n",
2414                   (char *)buffer);
2415         return -1;
2416     }
2417     *p2 = ' '; // Put in a space for atoi below.
2418     p2++;
2419 
2420     int major = atoi(p1);
2421     int minor = atoi(p2);
2422     int minor_revision = 2;
2423 
2424     if (major * 10 + minor < 10 + minor_revision)
2425     {
2426         // If the language version did not match, check to see if
2427         // OPENCL_1_0_DEVICE is set.
2428         if (getenv("OPENCL_1_0_DEVICE"))
2429         {
2430             log_info("WARNING: This test was run with OPENCL_1_0_DEVICE "
2431                      "defined!  This is not a OpenCL 1.1 or OpenCL 1.2 "
2432                      "compatible device!!!\n");
2433         }
2434         else if (getenv("OPENCL_1_1_DEVICE"))
2435         {
2436             log_info(
2437                 "WARNING: This test was run with OPENCL_1_1_DEVICE defined!  "
2438                 "This is not a OpenCL 1.2 compatible device!!!\n");
2439         }
2440         else
2441         {
2442             log_error("ERROR: OpenCL device language version returned is less "
2443                       "than 1.%d! (Returned: %s)\n",
2444                       minor_revision, (char *)buffer);
2445             return -1;
2446         }
2447     }
2448 
2449     // Sanity checks on the returned values
2450     if (length != (strlen((char *)buffer) + 1))
2451     {
2452         log_error("ERROR: Returned length of version string does not match "
2453                   "actual length (actual: %d, returned: %d)\n",
2454                   (int)strlen((char *)buffer), (int)length);
2455         return -1;
2456     }
2457 
2458     return 0;
2459 }
2460