xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/api/test_api_min_max.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
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, 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         mem = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_long), NULL,
1324                              &error);
1325         test_error(error, "clCreateBuffer failed");
1326 
1327         for (i = 0; i < (int)numberOfIntParametersToTry; i++)
1328         {
1329             if (gHasLong)
1330                 error = clSetKernelArg(kernel, i, sizeof(cl_long),
1331                                        &(((cl_long *)data)[i]));
1332             else
1333                 error = clSetKernelArg(kernel, i, sizeof(cl_int),
1334                                        &(((cl_int *)data)[i]));
1335 
1336             if (error != CL_SUCCESS)
1337             {
1338                 log_info("clSetKernelArg failed (%s), decrementing number of "
1339                          "parameters to try.\n",
1340                          IGetErrorString(error));
1341                 numberOfIntParametersToTry -= decrement;
1342                 break;
1343             }
1344         }
1345         if (error != CL_SUCCESS) continue;
1346 
1347 
1348         error = clSetKernelArg(kernel, i, sizeof(cl_mem), &mem);
1349         if (error != CL_SUCCESS)
1350         {
1351             log_info("clSetKernelArg failed (%s), decrementing number of "
1352                      "parameters to try.\n",
1353                      IGetErrorString(error));
1354             numberOfIntParametersToTry -= decrement;
1355             continue;
1356         }
1357 
1358         size_t globalDim[3] = { 1, 1, 1 }, localDim[3] = { 1, 1, 1 };
1359         error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim,
1360                                        localDim, 0, NULL, &event);
1361         if (error != CL_SUCCESS)
1362         {
1363             log_info("clEnqueueNDRangeKernel failed (%s), decrementing number "
1364                      "of parameters to try.\n",
1365                      IGetErrorString(error));
1366             numberOfIntParametersToTry -= decrement;
1367             continue;
1368         }
1369 
1370         // Verify that the event does not return an error from the execution
1371         error = clWaitForEvents(1, &event);
1372         test_error(error, "clWaitForEvent failed");
1373         error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1374                                sizeof(event_status), &event_status, NULL);
1375         test_error(
1376             error,
1377             "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1378         clReleaseEvent(event);
1379         if (event_status < 0)
1380             test_error(error, "Kernel execution event returned error");
1381 
1382         if (gHasLong)
1383             error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_long),
1384                                         &long_result, 0, NULL, NULL);
1385         else
1386             error = clEnqueueReadBuffer(queue, mem, CL_TRUE, 0, sizeof(cl_int),
1387                                         &int_result, 0, NULL, NULL);
1388 
1389         test_error(error, "clEnqueueReadBuffer failed")
1390 
1391             free(data);
1392         free(argumentLine);
1393         free(codeLines);
1394         free(programSrc);
1395 
1396         if (gHasLong)
1397         {
1398             if (long_result != expectedResult)
1399             {
1400                 log_error("Expected result (%lld) does not equal actual result "
1401                           "(%lld).\n",
1402                           expectedResult, long_result);
1403                 numberOfIntParametersToTry -= decrement;
1404                 continue;
1405             }
1406             else
1407             {
1408                 log_info("Results verified at %ld bytes of arguments.\n",
1409                          sizeof(cl_mem)
1410                              + numberOfIntParametersToTry * sizeof(cl_long));
1411                 break;
1412             }
1413         }
1414         else
1415         {
1416             if (int_result != expectedResult)
1417             {
1418                 log_error("Expected result (%lld) does not equal actual result "
1419                           "(%d).\n",
1420                           expectedResult, int_result);
1421                 numberOfIntParametersToTry -= decrement;
1422                 continue;
1423             }
1424             else
1425             {
1426                 log_info("Results verified at %ld bytes of arguments.\n",
1427                          sizeof(cl_mem)
1428                              + numberOfIntParametersToTry * sizeof(cl_int));
1429                 break;
1430             }
1431         }
1432     }
1433 
1434     if (numberOfIntParametersToTry == (long)numberExpected) return 0;
1435     return -1;
1436 }
1437 
test_min_max_samplers(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1438 int test_min_max_samplers(cl_device_id deviceID, cl_context context,
1439                           cl_command_queue queue, int num_elements)
1440 {
1441     int error;
1442     cl_uint maxSamplers, i;
1443     clProgramWrapper program;
1444     clKernelWrapper kernel;
1445     char *programSrc, samplerLine[1024];
1446     size_t maxParameterSize;
1447     cl_event event;
1448     cl_int event_status;
1449     cl_uint minRequiredSamplers = gIsEmbedded ? 8 : 16;
1450 
1451 
1452     PASSIVE_REQUIRE_IMAGE_SUPPORT(deviceID)
1453 
1454     /* Get the max value */
1455     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_SAMPLERS,
1456                             sizeof(maxSamplers), &maxSamplers, NULL);
1457     test_error(error, "Unable to get max sampler count from device");
1458 
1459     if (maxSamplers < minRequiredSamplers)
1460     {
1461         log_error(
1462             "ERROR: Reported max sampler count is less than required! (%d)\n",
1463             (int)maxSamplers);
1464         return -1;
1465     }
1466 
1467     log_info("Reported max %d samplers.\n", maxSamplers);
1468 
1469     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
1470                             sizeof(maxParameterSize), &maxParameterSize, NULL);
1471     test_error(error, "Unable to get max parameter size from device");
1472 
1473     // Subtract the size of the result
1474     maxParameterSize -= 2 * sizeof(cl_mem);
1475 
1476     // Calculate the number we can use
1477     if (maxParameterSize / sizeof(cl_sampler) < maxSamplers)
1478     {
1479         log_info("WARNING: Max parameter size of %d bytes limits test to %d "
1480                  "max sampler arguments.\n",
1481                  (int)maxParameterSize,
1482                  (int)(maxParameterSize / sizeof(cl_sampler)));
1483         maxSamplers = (unsigned int)(maxParameterSize / sizeof(cl_sampler));
1484     }
1485 
1486     /* Create a kernel to test with */
1487     programSrc = (char *)malloc(
1488         (strlen(sample_sampler_kernel_pattern[1]) + 8) * (maxSamplers)
1489         + strlen(sample_sampler_kernel_pattern[0])
1490         + strlen(sample_sampler_kernel_pattern[2])
1491         + (strlen(sample_sampler_kernel_pattern[3]) + 8) * maxSamplers
1492         + strlen(sample_sampler_kernel_pattern[4]));
1493     strcpy(programSrc, sample_sampler_kernel_pattern[0]);
1494     for (i = 0; i < maxSamplers; i++)
1495     {
1496         sprintf(samplerLine, sample_sampler_kernel_pattern[1], i);
1497         strcat(programSrc, samplerLine);
1498     }
1499     strcat(programSrc, sample_sampler_kernel_pattern[2]);
1500     for (i = 0; i < maxSamplers; i++)
1501     {
1502         sprintf(samplerLine, sample_sampler_kernel_pattern[3], i);
1503         strcat(programSrc, samplerLine);
1504     }
1505     strcat(programSrc, sample_sampler_kernel_pattern[4]);
1506 
1507 
1508     error =
1509         create_single_kernel_helper(context, &program, &kernel, 1,
1510                                     (const char **)&programSrc, "sample_test");
1511     test_error(error, "Failed to create the program and kernel.");
1512 
1513     // We have to set up some fake parameters so it'll work
1514     clSamplerWrapper *samplers = new clSamplerWrapper[maxSamplers];
1515 
1516     cl_image_format format = { CL_RGBA, CL_SIGNED_INT8 };
1517 
1518     clMemWrapper image = create_image_2d(context, CL_MEM_READ_WRITE, &format,
1519                                          16, 16, 0, NULL, &error);
1520     test_error(error, "Unable to create a test image");
1521 
1522     clMemWrapper stream =
1523         clCreateBuffer(context, CL_MEM_READ_WRITE, 16, NULL, &error);
1524     test_error(error, "Unable to create test buffer");
1525 
1526     error = clSetKernelArg(kernel, 0, sizeof(cl_mem), &image);
1527     error |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &stream);
1528     test_error(error, "Unable to set kernel arguments");
1529     for (i = 0; i < maxSamplers; i++)
1530     {
1531         samplers[i] = clCreateSampler(context, CL_FALSE, CL_ADDRESS_NONE,
1532                                       CL_FILTER_NEAREST, &error);
1533         test_error(error, "Unable to create sampler");
1534 
1535         error = clSetKernelArg(kernel, 2 + i, sizeof(cl_sampler), &samplers[i]);
1536         test_error(error, "Unable to set sampler argument");
1537     }
1538 
1539     size_t globalDim[3] = { 1, 1, 1 }, localDim[3] = { 1, 1, 1 };
1540     error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalDim, localDim,
1541                                    0, NULL, &event);
1542     test_error(
1543         error,
1544         "clEnqueueNDRangeKernel failed with maximum number of samplers.");
1545 
1546     // Verify that the event does not return an error from the execution
1547     error = clWaitForEvents(1, &event);
1548     test_error(error, "clWaitForEvent failed");
1549     error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1550                            sizeof(event_status), &event_status, NULL);
1551     test_error(error,
1552                "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1553     clReleaseEvent(event);
1554     if (event_status < 0)
1555         test_error(error, "Kernel execution event returned error");
1556 
1557     free(programSrc);
1558     delete[] samplers;
1559     return 0;
1560 }
1561 
1562 #define PASSING_FRACTION 4
test_min_max_constant_buffer_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1563 int test_min_max_constant_buffer_size(cl_device_id deviceID, cl_context context,
1564                                       cl_command_queue queue, int num_elements)
1565 {
1566     int error;
1567     clProgramWrapper program;
1568     clKernelWrapper kernel;
1569     size_t threads[1], localThreads[1];
1570     cl_int *constantData, *resultData;
1571     cl_ulong maxSize, stepSize, currentSize, maxGlobalSize, maxAllocSize;
1572     int i;
1573     cl_event event;
1574     cl_int event_status;
1575     MTdata d;
1576 
1577     /* Verify our test buffer won't be bigger than allowed */
1578     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
1579                             sizeof(maxSize), &maxSize, 0);
1580     test_error(error, "Unable to get max constant buffer size");
1581 
1582     if ((0 == gIsEmbedded && maxSize < 64L * 1024L) || maxSize < 1L * 1024L)
1583     {
1584         log_error("ERROR: Reported max constant buffer size less than required "
1585                   "by OpenCL 1.0 (reported %d KB)\n",
1586                   (int)(maxSize / 1024L));
1587         return -1;
1588     }
1589 
1590     log_info("Reported max constant buffer size of %lld bytes.\n", maxSize);
1591 
1592     // Limit test buffer size to 1/8 of CL_DEVICE_GLOBAL_MEM_SIZE
1593     error = clGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE,
1594                             sizeof(maxGlobalSize), &maxGlobalSize, 0);
1595     test_error(error, "Unable to get CL_DEVICE_GLOBAL_MEM_SIZE");
1596 
1597     if (maxSize > maxGlobalSize / 8) maxSize = maxGlobalSize / 8;
1598 
1599     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_MEM_ALLOC_SIZE,
1600                             sizeof(maxAllocSize), &maxAllocSize, 0);
1601     test_error(error, "Unable to get CL_DEVICE_MAX_MEM_ALLOC_SIZE ");
1602 
1603     if (maxSize > maxAllocSize) maxSize = maxAllocSize;
1604 
1605     /* Create a kernel to test with */
1606     if (create_single_kernel_helper(context, &program, &kernel, 1,
1607                                     sample_const_arg_kernel, "sample_test")
1608         != 0)
1609     {
1610         return -1;
1611     }
1612 
1613     /* Try the returned max size and decrease it until we get one that works. */
1614     stepSize = maxSize / 16;
1615     currentSize = maxSize;
1616     int allocPassed = 0;
1617     d = init_genrand(gRandomSeed);
1618     while (!allocPassed && currentSize >= maxSize / PASSING_FRACTION)
1619     {
1620         log_info("Attempting to allocate constant buffer of size %lld bytes\n",
1621                  maxSize);
1622 
1623         /* Create some I/O streams */
1624         size_t sizeToAllocate =
1625             ((size_t)currentSize / sizeof(cl_int)) * sizeof(cl_int);
1626         size_t numberOfInts = sizeToAllocate / sizeof(cl_int);
1627         constantData = (cl_int *)malloc(sizeToAllocate);
1628         if (constantData == NULL)
1629         {
1630             log_error("Failed to allocate memory for constantData!\n");
1631             free_mtdata(d);
1632             return EXIT_FAILURE;
1633         }
1634 
1635         for (i = 0; i < (int)(numberOfInts); i++)
1636             constantData[i] = (int)genrand_int32(d);
1637 
1638         clMemWrapper streams[3];
1639         streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
1640                                     sizeToAllocate, constantData, &error);
1641         test_error(error, "Creating test array failed");
1642         streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeToAllocate,
1643                                     NULL, &error);
1644         test_error(error, "Creating test array failed");
1645 
1646 
1647         /* Set the arguments */
1648         error = clSetKernelArg(kernel, 0, sizeof(streams[0]), &streams[0]);
1649         test_error(error, "Unable to set indexed kernel arguments");
1650         error = clSetKernelArg(kernel, 1, sizeof(streams[1]), &streams[1]);
1651         test_error(error, "Unable to set indexed kernel arguments");
1652 
1653 
1654         /* Test running the kernel and verifying it */
1655         threads[0] = numberOfInts;
1656         localThreads[0] = 1;
1657         log_info("Filling constant buffer with %d cl_ints (%d bytes).\n",
1658                  (int)threads[0], (int)(threads[0] * sizeof(cl_int)));
1659 
1660         error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads,
1661                                        localThreads, 0, NULL, &event);
1662         /* If we failed due to a resource issue, reduce the size and try again.
1663          */
1664         if ((error == CL_OUT_OF_RESOURCES)
1665             || (error == CL_MEM_OBJECT_ALLOCATION_FAILURE)
1666             || (error == CL_OUT_OF_HOST_MEMORY))
1667         {
1668             log_info("Kernel enqueue failed at size %lld, trying at a reduced "
1669                      "size.\n",
1670                      currentSize);
1671             currentSize -= stepSize;
1672             free(constantData);
1673             continue;
1674         }
1675         test_error(
1676             error,
1677             "clEnqueueNDRangeKernel with maximum constant buffer size failed.");
1678 
1679         // Verify that the event does not return an error from the execution
1680         error = clWaitForEvents(1, &event);
1681         test_error(error, "clWaitForEvent failed");
1682         error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1683                                sizeof(event_status), &event_status, NULL);
1684         test_error(
1685             error,
1686             "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1687         clReleaseEvent(event);
1688         if (event_status < 0)
1689         {
1690             if ((event_status == CL_OUT_OF_RESOURCES)
1691                 || (event_status == CL_MEM_OBJECT_ALLOCATION_FAILURE)
1692                 || (event_status == CL_OUT_OF_HOST_MEMORY))
1693             {
1694                 log_info("Kernel event indicates failure at size %lld, trying "
1695                          "at a reduced size.\n",
1696                          currentSize);
1697                 currentSize -= stepSize;
1698                 free(constantData);
1699                 continue;
1700             }
1701             else
1702             {
1703                 test_error(error, "Kernel execution event returned error");
1704             }
1705         }
1706 
1707         /* Otherwise we did not fail due to resource issues. */
1708         allocPassed = 1;
1709 
1710         resultData = (cl_int *)malloc(sizeToAllocate);
1711         if (resultData == NULL)
1712         {
1713             log_error("Failed to allocate memory for resultData!\n");
1714             free(constantData);
1715             free_mtdata(d);
1716             return EXIT_FAILURE;
1717         }
1718 
1719         error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0,
1720                                     sizeToAllocate, resultData, 0, NULL, NULL);
1721         test_error(error, "clEnqueueReadBuffer failed");
1722 
1723         for (i = 0; i < (int)(numberOfInts); i++)
1724             if (constantData[i] != resultData[i])
1725             {
1726                 log_error("Data failed to verify: constantData[%d]=%d != "
1727                           "resultData[%d]=%d\n",
1728                           i, constantData[i], i, resultData[i]);
1729                 free(constantData);
1730                 free(resultData);
1731                 free_mtdata(d);
1732                 d = NULL;
1733                 return -1;
1734             }
1735 
1736         free(constantData);
1737         free(resultData);
1738     }
1739     free_mtdata(d);
1740     d = NULL;
1741 
1742     if (allocPassed)
1743     {
1744         if (currentSize < maxSize / PASSING_FRACTION)
1745         {
1746             log_error("Failed to allocate at least 1/8 of the reported "
1747                       "constant size.\n");
1748             return -1;
1749         }
1750         else if (currentSize != maxSize)
1751         {
1752             log_info("Passed at reduced size. (%lld of %lld bytes)\n",
1753                      currentSize, maxSize);
1754             return 0;
1755         }
1756         return 0;
1757     }
1758     return -1;
1759 }
1760 
test_min_max_constant_args(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1761 int test_min_max_constant_args(cl_device_id deviceID, cl_context context,
1762                                cl_command_queue queue, int num_elements)
1763 {
1764     int error;
1765     clProgramWrapper program;
1766     clKernelWrapper kernel;
1767     clMemWrapper *streams;
1768     size_t threads[1], localThreads[1];
1769     cl_uint i, maxArgs;
1770     cl_ulong maxSize;
1771     cl_ulong maxParameterSize;
1772     size_t individualBufferSize;
1773     char *programSrc, *constArgs, *str2;
1774     char str[512];
1775     const char *ptr;
1776     cl_event event;
1777     cl_int event_status;
1778 
1779 
1780     /* Verify our test buffer won't be bigger than allowed */
1781     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_CONSTANT_ARGS,
1782                             sizeof(maxArgs), &maxArgs, 0);
1783     test_error(error, "Unable to get max constant arg count");
1784 
1785     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PARAMETER_SIZE,
1786                             sizeof(maxParameterSize), &maxParameterSize, NULL);
1787     test_error(error, "Unable to get max parameter size from device");
1788 
1789     // Subtract the size of the result
1790     maxParameterSize -= sizeof(cl_mem);
1791 
1792     // Calculate the number we can use
1793     if (maxParameterSize / sizeof(cl_mem) < maxArgs)
1794     {
1795         log_info("WARNING: Max parameter size of %d bytes limits test to %d "
1796                  "max image arguments.\n",
1797                  (int)maxParameterSize,
1798                  (int)(maxParameterSize / sizeof(cl_mem)));
1799         maxArgs = (unsigned int)(maxParameterSize / sizeof(cl_mem));
1800     }
1801 
1802 
1803     if (maxArgs < (gIsEmbedded ? 4 : 8))
1804     {
1805         log_error("ERROR: Reported max constant arg count less than required "
1806                   "by OpenCL 1.0 (reported %d)\n",
1807                   (int)maxArgs);
1808         return -1;
1809     }
1810 
1811     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
1812                             sizeof(maxSize), &maxSize, 0);
1813     test_error(error, "Unable to get max constant buffer size");
1814     individualBufferSize = (maxSize / 2) / maxArgs;
1815 
1816     log_info(
1817         "Reported max constant arg count of %u and max constant buffer "
1818         "size of %llu. Test will attempt to allocate half of that, or %llu "
1819         "buffers of size %zu.\n",
1820         maxArgs, maxSize, maxArgs, individualBufferSize);
1821 
1822     str2 = (char *)malloc(sizeof(char) * 32 * (maxArgs + 2));
1823     constArgs = (char *)malloc(sizeof(char) * 32 * (maxArgs + 2));
1824     programSrc = (char *)malloc(sizeof(char) * 32 * 2 * (maxArgs + 2) + 1024);
1825 
1826     /* Create a test program */
1827     constArgs[0] = 0;
1828     str2[0] = 0;
1829     for (i = 0; i < maxArgs - 1; i++)
1830     {
1831         sprintf(str, ", __constant int *src%d", (int)(i + 2));
1832         strcat(constArgs, str);
1833         sprintf(str2 + strlen(str2), "\tdst[tid] += src%d[tid];\n",
1834                 (int)(i + 2));
1835         if (strlen(str2) > (sizeof(char) * 32 * (maxArgs + 2) - 32)
1836             || strlen(constArgs) > (sizeof(char) * 32 * (maxArgs + 2) - 32))
1837         {
1838             log_info("Limiting number of arguments tested to %d due to test "
1839                      "program allocation size.\n",
1840                      i);
1841             break;
1842         }
1843     }
1844     sprintf(programSrc, sample_const_max_arg_kernel_pattern, constArgs, str2);
1845 
1846     /* Create a kernel to test with */
1847     ptr = programSrc;
1848     if (create_single_kernel_helper(context, &program, &kernel, 1, &ptr,
1849                                     "sample_test")
1850         != 0)
1851     {
1852         return -1;
1853     }
1854 
1855     /* Create some I/O streams */
1856     streams = new clMemWrapper[maxArgs + 1];
1857     for (i = 0; i < maxArgs + 1; i++)
1858     {
1859         streams[i] = clCreateBuffer(context, CL_MEM_READ_WRITE,
1860                                     individualBufferSize, NULL, &error);
1861         test_error(error, "Creating test array failed");
1862     }
1863 
1864     /* Set the arguments */
1865     for (i = 0; i < maxArgs + 1; i++)
1866     {
1867         error = clSetKernelArg(kernel, i, sizeof(streams[i]), &streams[i]);
1868         test_error(error, "Unable to set kernel argument");
1869     }
1870 
1871     /* Test running the kernel and verifying it */
1872     threads[0] = (size_t)10;
1873     while (threads[0] * sizeof(cl_int) > individualBufferSize) threads[0]--;
1874 
1875     error = get_max_common_work_group_size(context, kernel, threads[0],
1876                                            &localThreads[0]);
1877     test_error(error, "Unable to get work group size to use");
1878 
1879     error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads,
1880                                    localThreads, 0, NULL, &event);
1881     test_error(error, "clEnqueueNDRangeKernel failed");
1882 
1883     // Verify that the event does not return an error from the execution
1884     error = clWaitForEvents(1, &event);
1885     test_error(error, "clWaitForEvent failed");
1886     error = clGetEventInfo(event, CL_EVENT_COMMAND_EXECUTION_STATUS,
1887                            sizeof(event_status), &event_status, NULL);
1888     test_error(error,
1889                "clGetEventInfo for CL_EVENT_COMMAND_EXECUTION_STATUS failed");
1890     clReleaseEvent(event);
1891     if (event_status < 0)
1892         test_error(error, "Kernel execution event returned error");
1893 
1894     error = clFinish(queue);
1895     test_error(error, "clFinish failed.");
1896 
1897     delete[] streams;
1898     free(str2);
1899     free(constArgs);
1900     free(programSrc);
1901     return 0;
1902 }
1903 
test_min_max_compute_units(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1904 int test_min_max_compute_units(cl_device_id deviceID, cl_context context,
1905                                cl_command_queue queue, int num_elements)
1906 {
1907     int error;
1908     cl_uint value;
1909 
1910 
1911     error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS,
1912                             sizeof(value), &value, 0);
1913     test_error(error, "Unable to get compute unit count");
1914 
1915     if (value < 1)
1916     {
1917         log_error("ERROR: Reported compute unit count less than required by "
1918                   "OpenCL 1.0 (reported %d)\n",
1919                   (int)value);
1920         return -1;
1921     }
1922 
1923     log_info("Reported %d max compute units.\n", value);
1924 
1925     return 0;
1926 }
1927 
test_min_max_address_bits(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1928 int test_min_max_address_bits(cl_device_id deviceID, cl_context context,
1929                               cl_command_queue queue, int num_elements)
1930 {
1931     int error;
1932     cl_uint value;
1933 
1934 
1935     error = clGetDeviceInfo(deviceID, CL_DEVICE_ADDRESS_BITS, sizeof(value),
1936                             &value, 0);
1937     test_error(error, "Unable to get address bit count");
1938 
1939     if (value != 32 && value != 64)
1940     {
1941         log_error("ERROR: Reported address bit count not valid by OpenCL 1.0 "
1942                   "(reported %d)\n",
1943                   (int)value);
1944         return -1;
1945     }
1946 
1947     log_info("Reported %d device address bits.\n", value);
1948 
1949     return 0;
1950 }
1951 
test_min_max_single_fp_config(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1952 int test_min_max_single_fp_config(cl_device_id deviceID, cl_context context,
1953                                   cl_command_queue queue, int num_elements)
1954 {
1955     int error;
1956     cl_device_fp_config value;
1957     char profile[128] = "";
1958 
1959     error = clGetDeviceInfo(deviceID, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(value),
1960                             &value, 0);
1961     test_error(error, "Unable to get device single fp config");
1962 
1963     // Check to see if we are an embedded profile device
1964     if ((error = clGetDeviceInfo(deviceID, CL_DEVICE_PROFILE, sizeof(profile),
1965                                  profile, NULL)))
1966     {
1967         log_error("FAILURE: Unable to get CL_DEVICE_PROFILE: error %d\n",
1968                   error);
1969         return error;
1970     }
1971 
1972     if (0 == strcmp(profile, "EMBEDDED_PROFILE"))
1973     { // embedded device
1974 
1975         if (0 == (value & (CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO)))
1976         {
1977             log_error("FAILURE: embedded device supports neither "
1978                       "CL_FP_ROUND_TO_NEAREST or CL_FP_ROUND_TO_ZERO\n");
1979             return -1;
1980         }
1981     }
1982     else
1983     { // Full profile
1984         if ((value & (CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN))
1985             != (CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN))
1986         {
1987             log_error("ERROR: Reported single fp config doesn't meet minimum "
1988                       "set by OpenCL 1.0 (reported 0x%08x)\n",
1989                       (int)value);
1990             return -1;
1991         }
1992     }
1993     return 0;
1994 }
1995 
test_min_max_double_fp_config(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)1996 int test_min_max_double_fp_config(cl_device_id deviceID, cl_context context,
1997                                   cl_command_queue queue, int num_elements)
1998 {
1999     int error;
2000     cl_device_fp_config value;
2001 
2002     error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG, sizeof(value),
2003                             &value, 0);
2004     test_error(error, "Unable to get device double fp config");
2005 
2006     if (value == 0) return 0;
2007 
2008     if ((value
2009          & (CL_FP_FMA | CL_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO
2010             | CL_FP_ROUND_TO_INF | CL_FP_INF_NAN | CL_FP_DENORM))
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     {
2014         log_error("ERROR: Reported double fp config doesn't meet minimum set "
2015                   "by OpenCL 1.0 (reported 0x%08x)\n",
2016                   (int)value);
2017         return -1;
2018     }
2019     return 0;
2020 }
2021 
test_min_max_local_mem_size(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2022 int test_min_max_local_mem_size(cl_device_id deviceID, cl_context context,
2023                                 cl_command_queue queue, int num_elements)
2024 {
2025     int error;
2026     clProgramWrapper program;
2027     clKernelWrapper kernel;
2028     clMemWrapper streams[3];
2029     size_t threads[1], localThreads[1];
2030     cl_int *localData, *resultData;
2031     cl_ulong maxSize, kernelLocalUsage, min_max_local_mem_size;
2032     Version device_version;
2033     int i;
2034     int err = 0;
2035     MTdata d;
2036 
2037     /* Verify our test buffer won't be bigger than allowed */
2038     error = clGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(maxSize),
2039                             &maxSize, 0);
2040     test_error(error, "Unable to get max local buffer size");
2041 
2042     try
2043     {
2044         device_version = get_device_cl_version(deviceID);
2045     } catch (const std::runtime_error &e)
2046     {
2047         log_error("%s", e.what());
2048         return -1;
2049     }
2050 
2051     if (!gIsEmbedded)
2052     {
2053         if (device_version == Version(1, 0))
2054             min_max_local_mem_size = 16L * 1024L;
2055         else
2056             min_max_local_mem_size = 32L * 1024L;
2057     }
2058     else
2059     {
2060         min_max_local_mem_size = 1L * 1024L;
2061     }
2062 
2063     if (maxSize < min_max_local_mem_size)
2064     {
2065         const std::string version_as_string = device_version.to_string();
2066         log_error("ERROR: Reported local mem size less than required by OpenCL "
2067                   "%s (reported %d KB)\n",
2068                   version_as_string.c_str(), (int)(maxSize / 1024L));
2069         return -1;
2070     }
2071 
2072     log_info("Reported max local buffer size for device: %lld bytes.\n",
2073              maxSize);
2074 
2075     /* Create a kernel to test with */
2076     if (create_single_kernel_helper(context, &program, &kernel, 1,
2077                                     sample_local_arg_kernel, "sample_test")
2078         != 0)
2079     {
2080         return -1;
2081     }
2082 
2083     error = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_LOCAL_MEM_SIZE,
2084                                      sizeof(kernelLocalUsage),
2085                                      &kernelLocalUsage, NULL);
2086     test_error(error,
2087                "clGetKernelWorkGroupInfo for CL_KERNEL_LOCAL_MEM_SIZE failed");
2088 
2089     log_info("Reported local buffer usage for kernel "
2090              "(CL_KERNEL_LOCAL_MEM_SIZE): %lld bytes.\n",
2091              kernelLocalUsage);
2092 
2093     /* Create some I/O streams */
2094     size_t sizeToAllocate =
2095         ((size_t)(maxSize - kernelLocalUsage) / sizeof(cl_int))
2096         * sizeof(cl_int);
2097     size_t numberOfInts = sizeToAllocate / sizeof(cl_int);
2098 
2099     log_info("Attempting to use %zu bytes of local memory.\n", sizeToAllocate);
2100 
2101     localData = (cl_int *)malloc(sizeToAllocate);
2102     d = init_genrand(gRandomSeed);
2103     for (i = 0; i < (int)(numberOfInts); i++)
2104         localData[i] = (int)genrand_int32(d);
2105     free_mtdata(d);
2106     d = NULL;
2107 
2108     streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeToAllocate,
2109                                 localData, &error);
2110     test_error(error, "Creating test array failed");
2111     streams[1] = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeToAllocate,
2112                                 NULL, &error);
2113     test_error(error, "Creating test array failed");
2114 
2115 
2116     /* Set the arguments */
2117     error = clSetKernelArg(kernel, 0, sizeToAllocate, NULL);
2118     test_error(error, "Unable to set indexed kernel arguments");
2119     error = clSetKernelArg(kernel, 1, sizeof(streams[0]), &streams[0]);
2120     test_error(error, "Unable to set indexed kernel arguments");
2121     error = clSetKernelArg(kernel, 2, sizeof(streams[1]), &streams[1]);
2122     test_error(error, "Unable to set indexed kernel arguments");
2123 
2124 
2125     /* Test running the kernel and verifying it */
2126     threads[0] = numberOfInts;
2127     localThreads[0] = 1;
2128     log_info("Creating local buffer with %zu cl_ints (%zu bytes).\n",
2129              numberOfInts, sizeToAllocate);
2130 
2131     cl_event evt;
2132     cl_int evt_err;
2133     error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, threads,
2134                                    localThreads, 0, NULL, &evt);
2135     test_error(error, "clEnqueueNDRangeKernel failed");
2136 
2137     error = clFinish(queue);
2138     test_error(error, "clFinish failed");
2139 
2140     error = clGetEventInfo(evt, CL_EVENT_COMMAND_EXECUTION_STATUS,
2141                            sizeof evt_err, &evt_err, NULL);
2142     test_error(error, "clGetEventInfo with maximum local buffer size failed.");
2143 
2144     if (evt_err != CL_COMPLETE)
2145     {
2146         print_error(evt_err, "Kernel event returned error");
2147         clReleaseEvent(evt);
2148         return -1;
2149     }
2150 
2151     resultData = (cl_int *)malloc(sizeToAllocate);
2152 
2153     error = clEnqueueReadBuffer(queue, streams[1], CL_TRUE, 0, sizeToAllocate,
2154                                 resultData, 0, NULL, NULL);
2155     test_error(error, "clEnqueueReadBuffer failed");
2156 
2157     for (i = 0; i < (int)(numberOfInts); i++)
2158         if (localData[i] != resultData[i])
2159         {
2160             clReleaseEvent(evt);
2161             free(localData);
2162             free(resultData);
2163             log_error("Results failed to verify.\n");
2164             return -1;
2165         }
2166     clReleaseEvent(evt);
2167     free(localData);
2168     free(resultData);
2169 
2170     return err;
2171 }
2172 
test_min_max_kernel_preferred_work_group_size_multiple(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2173 int test_min_max_kernel_preferred_work_group_size_multiple(
2174     cl_device_id deviceID, cl_context context, cl_command_queue queue,
2175     int num_elements)
2176 {
2177     int err;
2178     clProgramWrapper program;
2179     clKernelWrapper kernel;
2180 
2181     size_t max_local_workgroup_size[3];
2182     size_t max_workgroup_size = 0, preferred_workgroup_size = 0;
2183 
2184     err = create_single_kernel_helper(context, &program, &kernel, 1,
2185                                       sample_local_arg_kernel, "sample_test");
2186     test_error(err, "Failed to build kernel/program.");
2187 
2188     err = clGetKernelWorkGroupInfo(kernel, deviceID, CL_KERNEL_WORK_GROUP_SIZE,
2189                                    sizeof(max_workgroup_size),
2190                                    &max_workgroup_size, NULL);
2191     test_error(err, "clGetKernelWorkgroupInfo failed.");
2192 
2193     err = clGetKernelWorkGroupInfo(
2194         kernel, deviceID, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,
2195         sizeof(preferred_workgroup_size), &preferred_workgroup_size, NULL);
2196     test_error(err, "clGetKernelWorkgroupInfo failed.");
2197 
2198     err = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_WORK_ITEM_SIZES,
2199                           sizeof(max_local_workgroup_size),
2200                           max_local_workgroup_size, NULL);
2201     test_error(err, "clGetDeviceInfo failed for CL_DEVICE_MAX_WORK_ITEM_SIZES");
2202 
2203     // Since the preferred size is only a performance hint, we can only really
2204     // check that we get a sane value back
2205     log_info("size: %ld     preferred: %ld      max: %ld\n", max_workgroup_size,
2206              preferred_workgroup_size, max_local_workgroup_size[0]);
2207 
2208     if (preferred_workgroup_size > max_workgroup_size)
2209     {
2210         log_error("ERROR: Reported preferred workgroup multiple larger than "
2211                   "max workgroup size (preferred %ld, max %ld)\n",
2212                   preferred_workgroup_size, max_workgroup_size);
2213         return -1;
2214     }
2215 
2216     return 0;
2217 }
2218 
test_min_max_execution_capabilities(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2219 int test_min_max_execution_capabilities(cl_device_id deviceID,
2220                                         cl_context context,
2221                                         cl_command_queue queue,
2222                                         int num_elements)
2223 {
2224     int error;
2225     cl_device_exec_capabilities value;
2226 
2227 
2228     error = clGetDeviceInfo(deviceID, CL_DEVICE_EXECUTION_CAPABILITIES,
2229                             sizeof(value), &value, 0);
2230     test_error(error, "Unable to get execution capabilities");
2231 
2232     if ((value & CL_EXEC_KERNEL) != CL_EXEC_KERNEL)
2233     {
2234         log_error("ERROR: Reported execution capabilities less than required "
2235                   "by OpenCL 1.0 (reported 0x%08x)\n",
2236                   (int)value);
2237         return -1;
2238     }
2239     return 0;
2240 }
2241 
test_min_max_queue_properties(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2242 int test_min_max_queue_properties(cl_device_id deviceID, cl_context context,
2243                                   cl_command_queue queue, int num_elements)
2244 {
2245     int error;
2246     cl_command_queue_properties value;
2247 
2248 
2249     error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
2250                             sizeof(value), &value, 0);
2251     test_error(error, "Unable to get queue properties");
2252 
2253     if ((value & CL_QUEUE_PROFILING_ENABLE) != CL_QUEUE_PROFILING_ENABLE)
2254     {
2255         log_error("ERROR: Reported queue properties less than required by "
2256                   "OpenCL 1.0 (reported 0x%08x)\n",
2257                   (int)value);
2258         return -1;
2259     }
2260     return 0;
2261 }
2262 
test_min_max_device_version(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2263 int test_min_max_device_version(cl_device_id deviceID, cl_context context,
2264                                 cl_command_queue queue, int num_elements)
2265 {
2266     // Query for the device version.
2267     Version device_cl_version = get_device_cl_version(deviceID);
2268     log_info("Returned version %s.\n", device_cl_version.to_string().c_str());
2269 
2270     // Make sure 2.x devices support required extensions for 2.x
2271     // note: these extensions are **not** required for devices
2272     // supporting OpenCL-3.0
2273     const char *requiredExtensions2x[] = {
2274         "cl_khr_3d_image_writes",
2275         "cl_khr_image2d_from_buffer",
2276         "cl_khr_depth_images",
2277     };
2278 
2279     // Make sure 1.1 devices support required extensions for 1.1
2280     const char *requiredExtensions11[] = {
2281         "cl_khr_global_int32_base_atomics",
2282         "cl_khr_global_int32_extended_atomics",
2283         "cl_khr_local_int32_base_atomics",
2284         "cl_khr_local_int32_extended_atomics",
2285         "cl_khr_byte_addressable_store",
2286     };
2287 
2288 
2289     if (device_cl_version >= Version(1, 1))
2290     {
2291         log_info("Checking for required extensions for OpenCL 1.1 and later "
2292                  "devices...\n");
2293         for (size_t i = 0; i < ARRAY_SIZE(requiredExtensions11); i++)
2294         {
2295             if (!is_extension_available(deviceID, requiredExtensions11[i]))
2296             {
2297                 log_error("ERROR: Required extension for 1.1 and greater "
2298                           "devices is not in extension string: %s\n",
2299                           requiredExtensions11[i]);
2300                 return -1;
2301             }
2302             else
2303                 log_info("\t%s\n", requiredExtensions11[i]);
2304         }
2305 
2306         if (device_cl_version >= Version(1, 2))
2307         {
2308             log_info("Checking for required extensions for OpenCL 1.2 and "
2309                      "later devices...\n");
2310             // The only required extension for an OpenCL-1.2 device is
2311             // cl_khr_fp64 and it is only required if double precision is
2312             // supported.
2313             cl_device_fp_config doubles_supported;
2314             cl_int error = clGetDeviceInfo(deviceID, CL_DEVICE_DOUBLE_FP_CONFIG,
2315                                            sizeof(doubles_supported),
2316                                            &doubles_supported, 0);
2317             test_error(error, "Unable to get device double fp config");
2318             if (doubles_supported)
2319             {
2320                 if (!is_extension_available(deviceID, "cl_khr_fp64"))
2321                 {
2322                     log_error(
2323                         "ERROR: Required extension for 1.2 and greater devices "
2324                         "is not in extension string: cl_khr_fp64\n");
2325                 }
2326                 else
2327                 {
2328                     log_info("\t%s\n", "cl_khr_fp64");
2329                 }
2330             }
2331         }
2332 
2333         if (device_cl_version >= Version(2, 0)
2334             && device_cl_version < Version(3, 0))
2335         {
2336             log_info("Checking for required extensions for OpenCL 2.0, 2.1 and "
2337                      "2.2 devices...\n");
2338             for (size_t i = 0; i < ARRAY_SIZE(requiredExtensions2x); i++)
2339             {
2340                 if (!is_extension_available(deviceID, requiredExtensions2x[i]))
2341                 {
2342                     log_error("ERROR: Required extension for 2.0, 2.1 and 2.2 "
2343                               "devices is not in extension string: %s\n",
2344                               requiredExtensions2x[i]);
2345                     return -1;
2346                 }
2347                 else
2348                 {
2349                     log_info("\t%s\n", requiredExtensions2x[i]);
2350                 }
2351             }
2352         }
2353     }
2354     else
2355         log_info("WARNING: skipping required extension test -- OpenCL 1.0 "
2356                  "device.\n");
2357     return 0;
2358 }
2359 
test_min_max_language_version(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)2360 int test_min_max_language_version(cl_device_id deviceID, cl_context context,
2361                                   cl_command_queue queue, int num_elements)
2362 {
2363     cl_int error;
2364     cl_char buffer[4098];
2365     size_t length;
2366 
2367     // Device version should fit the regex "OpenCL [0-9]+\.[0-9]+ *.*"
2368     error = clGetDeviceInfo(deviceID, CL_DEVICE_OPENCL_C_VERSION,
2369                             sizeof(buffer), buffer, &length);
2370     test_error(error, "Unable to get device opencl c version string");
2371     if (memcmp(buffer, "OpenCL C ", strlen("OpenCL C ")) != 0)
2372     {
2373         log_error("ERROR: Initial part of device language version string does "
2374                   "not match required format! (returned: \"%s\")\n",
2375                   (char *)buffer);
2376         return -1;
2377     }
2378 
2379     log_info("Returned version \"%s\".\n", buffer);
2380 
2381     char *p1 = (char *)buffer + strlen("OpenCL C ");
2382     while (*p1 == ' ') p1++;
2383     char *p2 = p1;
2384     if (!isdigit(*p2))
2385     {
2386         log_error("ERROR: Major revision number must follow space behind "
2387                   "OpenCL C! (returned %s)\n",
2388                   (char *)buffer);
2389         return -1;
2390     }
2391     while (isdigit(*p2)) p2++;
2392     if (*p2 != '.')
2393     {
2394         log_error("ERROR: Version number must contain a decimal point! "
2395                   "(returned: %s)\n",
2396                   (char *)buffer);
2397         return -1;
2398     }
2399     char *p3 = p2 + 1;
2400     if (!isdigit(*p3))
2401     {
2402         log_error("ERROR: Minor revision number is missing or does not abut "
2403                   "the decimal point! (returned %s)\n",
2404                   (char *)buffer);
2405         return -1;
2406     }
2407     while (isdigit(*p3)) p3++;
2408     if (*p3 != ' ')
2409     {
2410         log_error("ERROR: A space must appear after the minor version! "
2411                   "(returned: %s)\n",
2412                   (char *)buffer);
2413         return -1;
2414     }
2415     *p2 = ' '; // Put in a space for atoi below.
2416     p2++;
2417 
2418     int major = atoi(p1);
2419     int minor = atoi(p2);
2420     int minor_revision = 2;
2421 
2422     if (major * 10 + minor < 10 + minor_revision)
2423     {
2424         // If the language version did not match, check to see if
2425         // OPENCL_1_0_DEVICE is set.
2426         if (getenv("OPENCL_1_0_DEVICE"))
2427         {
2428             log_info("WARNING: This test was run with OPENCL_1_0_DEVICE "
2429                      "defined!  This is not a OpenCL 1.1 or OpenCL 1.2 "
2430                      "compatible device!!!\n");
2431         }
2432         else if (getenv("OPENCL_1_1_DEVICE"))
2433         {
2434             log_info(
2435                 "WARNING: This test was run with OPENCL_1_1_DEVICE defined!  "
2436                 "This is not a OpenCL 1.2 compatible device!!!\n");
2437         }
2438         else
2439         {
2440             log_error("ERROR: OpenCL device language version returned is less "
2441                       "than 1.%d! (Returned: %s)\n",
2442                       minor_revision, (char *)buffer);
2443             return -1;
2444         }
2445     }
2446 
2447     // Sanity checks on the returned values
2448     if (length != (strlen((char *)buffer) + 1))
2449     {
2450         log_error("ERROR: Returned length of version string does not match "
2451                   "actual length (actual: %d, returned: %d)\n",
2452                   (int)strlen((char *)buffer), (int)length);
2453         return -1;
2454     }
2455 
2456     return 0;
2457 }
2458