1 //
2 // Copyright (c) 2022 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 
17 #include "../testBase.h"
18 #include "../common.h"
19 #include "test_cl_ext_image_buffer.hpp"
20 
get_image_requirement_alignment(cl_device_id device,cl_context context,cl_mem_flags flags,const cl_image_format * image_format,const cl_image_desc * image_desc,size_t * row_pitch_alignment,size_t * slice_pitch_alignment,size_t * base_address_alignment)21 static int get_image_requirement_alignment(
22     cl_device_id device, cl_context context, cl_mem_flags flags,
23     const cl_image_format* image_format, const cl_image_desc* image_desc,
24     size_t* row_pitch_alignment, size_t* slice_pitch_alignment,
25     size_t* base_address_alignment)
26 {
27     cl_platform_id platform = getPlatformFromDevice(device);
28     GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT);
29 
30     cl_int err = CL_SUCCESS;
31     if (nullptr != row_pitch_alignment)
32     {
33         err = clGetImageRequirementsInfoEXT(
34             context, nullptr, flags, image_format, image_desc,
35             CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT,
36             sizeof(*row_pitch_alignment), row_pitch_alignment, nullptr);
37         test_error(err, "Error getting alignment");
38     }
39 
40     if (nullptr != slice_pitch_alignment && CL_SUCCESS == err)
41     {
42         err = clGetImageRequirementsInfoEXT(
43             context, nullptr, flags, image_format, image_desc,
44             CL_IMAGE_REQUIREMENTS_SLICE_PITCH_ALIGNMENT_EXT,
45             sizeof(*slice_pitch_alignment), slice_pitch_alignment, nullptr);
46         test_error(err, "Error getting alignment");
47     }
48 
49     if (nullptr != base_address_alignment && CL_SUCCESS == err)
50     {
51         err = clGetImageRequirementsInfoEXT(
52             context, nullptr, flags, image_format, image_desc,
53             CL_IMAGE_REQUIREMENTS_BASE_ADDRESS_ALIGNMENT_EXT,
54             sizeof(*base_address_alignment), base_address_alignment, nullptr);
55         test_error(err, "Error getting alignment");
56     }
57 
58     return TEST_PASS;
59 }
60 
61 /**
62  * Consistency with alignment requirements as returned by
63  * cl_khr_image2d_from_buffer Check that the returned values for
64  * CL_DEVICE_IMAGE_PITCH_ALIGNMENT and CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT
65  * are correct.
66  */
image2d_from_buffer_positive(cl_device_id device,cl_context context,cl_command_queue queue)67 int image2d_from_buffer_positive(cl_device_id device, cl_context context,
68                                  cl_command_queue queue)
69 {
70     if (!is_extension_available(device, "cl_khr_image2d_from_buffer"))
71     {
72         log_info("Extension cl_khr_image2d_from_buffer not available\n");
73         return TEST_SKIPPED_ITSELF;
74     }
75 
76     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
77     {
78         log_info("Extension cl_ext_image_requirements_info not available\n");
79         return TEST_SKIPPED_ITSELF;
80     }
81 
82     std::vector<cl_mem_object_type> imageTypes{
83         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
84         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
85         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
86     };
87 
88     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
89                                          CL_MEM_READ_WRITE,
90                                          CL_MEM_KERNEL_READ_AND_WRITE };
91 
92     for (auto flagType : flagTypes)
93     {
94         for (auto imageType : imageTypes)
95         {
96             /* Get the list of supported image formats */
97             std::vector<cl_image_format> formatList;
98             if (TEST_PASS
99                     != get_format_list(context, imageType, formatList, flagType)
100                 || formatList.size() == 0)
101             {
102                 test_fail("Failure to get supported formats list\n");
103             }
104 
105             cl_uint row_pitch_alignment_2d = 0;
106             cl_int err =
107                 clGetDeviceInfo(device, CL_DEVICE_IMAGE_PITCH_ALIGNMENT,
108                                 sizeof(row_pitch_alignment_2d),
109                                 &row_pitch_alignment_2d, nullptr);
110             test_error(err, "Error clGetDeviceInfo");
111 
112             cl_uint base_address_alignment_2d = 0;
113             err =
114                 clGetDeviceInfo(device, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT,
115                                 sizeof(base_address_alignment_2d),
116                                 &base_address_alignment_2d, nullptr);
117             test_error(err, "Error clGetDeviceInfo");
118 
119             for (auto format : formatList)
120             {
121                 cl_image_desc image_desc = { 0 };
122                 image_desc_init(&image_desc, imageType);
123 
124                 cl_mem_flags flag = (flagType == CL_MEM_KERNEL_READ_AND_WRITE)
125                     ? CL_MEM_READ_WRITE
126                     : flagType;
127 
128                 size_t row_pitch_alignment = 0;
129                 size_t base_address_alignment = 0;
130 
131                 int get_error = get_image_requirement_alignment(
132                     device, context, flag, &format, &image_desc,
133                     &row_pitch_alignment, nullptr, &base_address_alignment);
134                 if (TEST_PASS != get_error)
135                 {
136                     return get_error;
137                 }
138 
139                 const size_t element_size =
140                     get_format_size(context, &format, imageType, flag);
141 
142                 /*  Alignements in pixels vs bytes */
143                 if (base_address_alignment
144                     > base_address_alignment_2d * element_size)
145                 {
146                     test_fail("Unexpected base_address_alignment\n");
147                 }
148 
149                 if (row_pitch_alignment > row_pitch_alignment_2d * element_size)
150                 {
151                     test_fail("Unexpected row_pitch_alignment\n");
152                 }
153             }
154         }
155     }
156 
157     return TEST_PASS;
158 }
159 
160 /**
161  * Test clGetMemObjectInfo
162  * Check that CL_MEM_ASSOCIATED_MEMOBJECT correctly returns the buffer that was
163  * used.
164  */
memInfo_image_from_buffer_positive(cl_device_id device,cl_context context,cl_command_queue queue)165 int memInfo_image_from_buffer_positive(cl_device_id device, cl_context context,
166                                        cl_command_queue queue)
167 {
168     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
169     {
170         log_info("Extension cl_ext_image_requirements_info not available\n");
171         return TEST_SKIPPED_ITSELF;
172     }
173 
174     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
175     {
176         log_info("Extension cl_ext_image_from_buffer not available\n");
177         return TEST_SKIPPED_ITSELF;
178     }
179 
180     std::vector<cl_mem_object_type> imageTypes{
181         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
182         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
183         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
184     };
185 
186     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
187                                          CL_MEM_READ_WRITE,
188                                          CL_MEM_KERNEL_READ_AND_WRITE };
189 
190     for (auto flagType : flagTypes)
191     {
192         for (auto imageType : imageTypes)
193         {
194             /* Get the list of supported image formats */
195             std::vector<cl_image_format> formatList;
196             if (TEST_PASS
197                     != get_format_list(context, imageType, formatList, flagType)
198                 || formatList.size() == 0)
199             {
200                 test_fail("Failure to get supported formats list\n");
201             }
202 
203             for (auto format : formatList)
204             {
205                 cl_image_desc image_desc = { 0 };
206                 image_desc_init(&image_desc, imageType);
207 
208                 cl_mem_flags flag = (flagType == CL_MEM_KERNEL_READ_AND_WRITE)
209                     ? CL_MEM_READ_WRITE
210                     : flagType;
211 
212                 size_t row_pitch_alignment = 0;
213                 size_t slice_pitch_alignment = 0;
214 
215                 int get_error = get_image_requirement_alignment(
216                     device, context, flag, &format, &image_desc,
217                     &row_pitch_alignment, &slice_pitch_alignment, nullptr);
218                 if (TEST_PASS != get_error)
219                 {
220                     return get_error;
221                 }
222 
223                 const size_t element_size =
224                     get_format_size(context, &format, imageType, flag);
225 
226                 const size_t row_pitch = aligned_size(
227                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
228                 const size_t slice_pitch = aligned_size(
229                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
230 
231                 const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
232 
233                 cl_int err = CL_SUCCESS;
234                 cl_mem buffer =
235                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
236                 test_error(err, "Unable to create buffer");
237 
238                 image_desc.buffer = buffer;
239 
240                 cl_mem image_buffer = clCreateImage(context, flag, &format,
241                                                     &image_desc, nullptr, &err);
242                 test_error(err, "Unable to create image");
243 
244                 cl_mem returned_buffer;
245                 err = clGetMemObjectInfo(
246                     image_buffer, CL_MEM_ASSOCIATED_MEMOBJECT,
247                     sizeof(returned_buffer), &returned_buffer, nullptr);
248                 test_error(err, "Error clGetMemObjectInfo");
249 
250                 if (returned_buffer != buffer)
251                 {
252                     test_fail(
253                         "Unexpected CL_MEM_ASSOCIATED_MEMOBJECT buffer\n");
254                 }
255 
256                 err = clReleaseMemObject(buffer);
257                 test_error(err, "Unable to release buffer");
258 
259                 err = clReleaseMemObject(image_buffer);
260                 test_error(err, "Unable to release image");
261             }
262         }
263     }
264 
265     return TEST_PASS;
266 }
267 
268 /**
269  * Test clGetImageInfo
270  * Check that the returned values for CL_IMAGE_ROW_PITCH and
271  * CL_IMAGE_SLICE_PITCH are correct.
272  */
imageInfo_image_from_buffer_positive(cl_device_id device,cl_context context,cl_command_queue queue)273 int imageInfo_image_from_buffer_positive(cl_device_id device,
274                                          cl_context context,
275                                          cl_command_queue queue)
276 {
277     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
278     {
279         log_info("Extension cl_ext_image_requirements_info not available\n");
280         return TEST_SKIPPED_ITSELF;
281     }
282 
283     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
284     {
285         log_info("Extension cl_ext_image_from_buffer not available\n");
286         return TEST_SKIPPED_ITSELF;
287     }
288 
289     std::vector<cl_mem_object_type> imageTypes{
290         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
291         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
292         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
293     };
294 
295     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
296                                          CL_MEM_READ_WRITE,
297                                          CL_MEM_KERNEL_READ_AND_WRITE };
298 
299     for (auto flagType : flagTypes)
300     {
301         for (auto imageType : imageTypes)
302         {
303             /* Get the list of supported image formats */
304             std::vector<cl_image_format> formatList;
305             if (TEST_PASS
306                     != get_format_list(context, imageType, formatList, flagType)
307                 || formatList.size() == 0)
308             {
309                 test_fail("Failure to get supported formats list\n");
310             }
311 
312             for (auto format : formatList)
313             {
314                 cl_image_desc image_desc = { 0 };
315                 image_desc_init(&image_desc, imageType);
316 
317                 cl_mem_flags flag = (flagType == CL_MEM_KERNEL_READ_AND_WRITE)
318                     ? CL_MEM_READ_WRITE
319                     : flagType;
320 
321                 size_t row_pitch_alignment = 0;
322                 size_t slice_pitch_alignment = 0;
323 
324                 int get_error = get_image_requirement_alignment(
325                     device, context, flag, &format, &image_desc,
326                     &row_pitch_alignment, &slice_pitch_alignment, nullptr);
327                 if (TEST_PASS != get_error)
328                 {
329                     return get_error;
330                 }
331 
332                 const size_t element_size =
333                     get_format_size(context, &format, imageType, flag);
334 
335                 const size_t row_pitch = aligned_size(
336                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
337                 const size_t slice_pitch = aligned_size(
338                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
339 
340                 const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
341 
342                 cl_int err = CL_SUCCESS;
343                 cl_mem buffer =
344                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
345                 test_error(err, "Unable to create buffer");
346 
347                 image_desc.buffer = buffer;
348 
349                 if (imageType == CL_MEM_OBJECT_IMAGE2D
350                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
351                 {
352                     image_desc.image_row_pitch = row_pitch;
353                 }
354                 else if (imageType == CL_MEM_OBJECT_IMAGE3D
355                          || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
356                 {
357                     image_desc.image_row_pitch = row_pitch;
358                     image_desc.image_slice_pitch = slice_pitch;
359                 }
360 
361                 cl_mem image_buffer = clCreateImage(context, flag, &format,
362                                                     &image_desc, nullptr, &err);
363                 test_error(err, "Unable to create image");
364 
365                 if (imageType == CL_MEM_OBJECT_IMAGE3D
366                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY
367                     || imageType == CL_MEM_OBJECT_IMAGE2D
368                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
369                 {
370                     size_t returned_row_pitch = 0;
371                     err = clGetImageInfo(image_buffer, CL_IMAGE_ROW_PITCH,
372                                          sizeof(returned_row_pitch),
373                                          &returned_row_pitch, nullptr);
374                     test_error(err, "Error clGetImageInfo");
375 
376                     if (returned_row_pitch != row_pitch)
377                     {
378                         test_fail(
379                             "Unexpected row pitch "
380                             "CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT\n");
381                     }
382                 }
383 
384                 if (imageType == CL_MEM_OBJECT_IMAGE3D
385                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
386                 {
387                     size_t returned_slice_pitch = 0;
388                     err = clGetImageInfo(image_buffer, CL_IMAGE_SLICE_PITCH,
389                                          sizeof(returned_slice_pitch),
390                                          &returned_slice_pitch, nullptr);
391                     test_error(err, "Error clGetImageInfo");
392 
393                     if (returned_slice_pitch != slice_pitch)
394                     {
395                         test_fail("Unexpected row pitch "
396                                   "CL_IMAGE_REQUIREMENTS_SLICE_PITCH_ALIGNMENT_"
397                                   "EXT\n");
398                     }
399                 }
400 
401                 err = clReleaseMemObject(buffer);
402                 test_error(err, "Unable to release buffer");
403 
404                 err = clReleaseMemObject(image_buffer);
405                 test_error(err, "Unable to release image");
406             }
407         }
408     }
409 
410     return TEST_PASS;
411 }
412 
413 /**
414  * Negative testing for clCreateImage and wrong alignment
415  * - Create an image from a buffer with invalid row pitch (not a multiple of
416  * required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is returned.
417  * - Create an image from a buffer with invalid slice pitch (not a multiple of
418  * required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is returned.
419  * - Create an image from a buffer with invalid base address alignment (not a
420  * multiple of required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is
421  * returned
422  */
image_from_buffer_alignment_negative(cl_device_id device,cl_context context,cl_command_queue queue)423 int image_from_buffer_alignment_negative(cl_device_id device,
424                                          cl_context context,
425                                          cl_command_queue queue)
426 {
427     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
428     {
429         log_info("Extension cl_ext_image_requirements_info not available\n");
430         return TEST_SKIPPED_ITSELF;
431     }
432 
433     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
434     {
435         log_info("Extension cl_ext_image_from_buffer not available\n");
436         return TEST_SKIPPED_ITSELF;
437     }
438 
439     std::vector<cl_mem_object_type> imageTypes{
440         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
441         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
442         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
443     };
444 
445     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
446                                          CL_MEM_READ_WRITE,
447                                          CL_MEM_KERNEL_READ_AND_WRITE };
448 
449     for (auto flagType : flagTypes)
450     {
451         for (auto imageType : imageTypes)
452         {
453             /* Get the list of supported image formats */
454             std::vector<cl_image_format> formatList;
455             if (TEST_PASS
456                     != get_format_list(context, imageType, formatList, flagType)
457                 || formatList.size() == 0)
458             {
459                 test_fail("Failure to get supported formats list\n");
460             }
461 
462             for (auto format : formatList)
463             {
464                 cl_image_desc image_desc = { 0 };
465                 image_desc_init(&image_desc, imageType);
466 
467                 cl_mem_flags flag = (flagType == CL_MEM_KERNEL_READ_AND_WRITE)
468                     ? CL_MEM_READ_WRITE
469                     : flagType;
470 
471                 size_t row_pitch_alignment = 0;
472                 size_t slice_pitch_alignment = 0;
473                 size_t base_address_alignment = 0;
474 
475                 int get_error = get_image_requirement_alignment(
476                     device, context, flag, &format, &image_desc,
477                     &row_pitch_alignment, &slice_pitch_alignment,
478                     &base_address_alignment);
479                 if (TEST_PASS != get_error)
480                 {
481                     return get_error;
482                 }
483 
484                 const size_t element_size =
485                     get_format_size(context, &format, imageType, flag);
486 
487                 const size_t row_pitch = aligned_size(
488                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
489                 const size_t slice_pitch = aligned_size(
490                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
491 
492                 const size_t buffer_size = (slice_pitch + 1)
493                     * TEST_IMAGE_SIZE; /* For bigger row/slice pitch */
494 
495                 cl_int err = CL_SUCCESS;
496                 cl_mem buffer =
497                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
498                 test_error(err, "Unable to create buffer");
499 
500                 /* Test Row pitch images */
501                 if (imageType == CL_MEM_OBJECT_IMAGE2D
502                     || imageType == CL_MEM_OBJECT_IMAGE3D
503                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY
504                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
505                 {
506                     image_desc.buffer = buffer;
507                     image_desc.image_row_pitch =
508                         row_pitch + 1; /* wrong row pitch */
509 
510                     clCreateImage(context, flag, &format, &image_desc, nullptr,
511                                   &err);
512                     test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
513                                        "Unexpected clCreateImage return");
514                 }
515 
516                 /* Test Slice pitch images */
517                 if (imageType == CL_MEM_OBJECT_IMAGE3D
518                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
519                 {
520                     image_desc.buffer = buffer;
521                     image_desc.image_row_pitch = row_pitch;
522                     image_desc.image_slice_pitch =
523                         slice_pitch + 1; /* wrong slice pitch */
524 
525                     clCreateImage(context, flag, &format, &image_desc, nullptr,
526                                   &err);
527                     test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
528                                        "Unexpected clCreateImage return");
529                 }
530 
531                 /* Test buffer from host ptr to test base address alignment */
532                 const size_t aligned_buffer_size =
533                     aligned_size(buffer_size, base_address_alignment);
534                 /* Create buffer with host ptr and additional size for the wrong
535                  * alignment */
536                 void* const host_ptr =
537                     malloc(aligned_buffer_size + base_address_alignment);
538                 void* non_aligned_host_ptr =
539                     (void*)((char*)(aligned_ptr(host_ptr,
540                                                 base_address_alignment))
541                             + 1); /* wrong alignment */
542 
543                 cl_mem buffer_host = clCreateBuffer(
544                     context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE,
545                     buffer_size, non_aligned_host_ptr, &err);
546                 test_error(err, "Unable to create buffer");
547 
548                 image_desc.buffer = buffer_host;
549 
550                 clCreateImage(context, flag, &format, &image_desc, nullptr,
551                               &err);
552                 test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
553                                    "Unexpected clCreateImage return");
554 
555                 free(host_ptr);
556 
557                 err = clReleaseMemObject(buffer);
558                 test_error(err, "Unable to release buffer");
559 
560                 err = clReleaseMemObject(buffer_host);
561                 test_error(err, "Unable to release buffer");
562             }
563         }
564     }
565 
566     return TEST_PASS;
567 }
568 
569 /**
570  * Negative testing for clCreateImage (buffer size).
571  * Create a buffer too small and check that image creation from that buffer is
572  * rejected
573  */
image_from_small_buffer_negative(cl_device_id device,cl_context context,cl_command_queue queue)574 int image_from_small_buffer_negative(cl_device_id device, cl_context context,
575                                      cl_command_queue queue)
576 {
577     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
578     {
579         log_info("Extension cl_ext_image_requirements_info not available\n");
580         return TEST_SKIPPED_ITSELF;
581     }
582 
583     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
584     {
585         log_info("Extension cl_ext_image_from_buffer not available\n");
586         return TEST_SKIPPED_ITSELF;
587     }
588 
589     std::vector<cl_mem_object_type> imageTypes{
590         CL_MEM_OBJECT_IMAGE1D,        CL_MEM_OBJECT_IMAGE2D,
591         CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE3D,
592         CL_MEM_OBJECT_IMAGE1D_ARRAY,  CL_MEM_OBJECT_IMAGE2D_ARRAY
593     };
594 
595     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
596                                          CL_MEM_READ_WRITE,
597                                          CL_MEM_KERNEL_READ_AND_WRITE };
598 
599     for (auto flagType : flagTypes)
600     {
601         for (auto imageType : imageTypes)
602         {
603             /* Get the list of supported image formats */
604             std::vector<cl_image_format> formatList;
605             if (TEST_PASS
606                     != get_format_list(context, imageType, formatList, flagType)
607                 || formatList.size() == 0)
608             {
609                 test_fail("Failure to get supported formats list\n");
610             }
611 
612             for (auto format : formatList)
613             {
614                 cl_image_desc image_desc = { 0 };
615                 image_desc_init(&image_desc, imageType);
616 
617                 cl_mem_flags flag = (flagType == CL_MEM_KERNEL_READ_AND_WRITE)
618                     ? CL_MEM_READ_WRITE
619                     : flagType;
620 
621                 /* Invalid buffer size */
622                 cl_int err;
623                 cl_mem buffer = clCreateBuffer(
624                     context, flag, TEST_IMAGE_SIZE / 2, nullptr, &err);
625                 test_error(err, "Unable to create buffer");
626 
627                 image_desc.buffer = buffer;
628 
629                 clCreateImage(context, flag, &format, &image_desc, nullptr,
630                               &err);
631                 test_failure_error(err, CL_INVALID_MEM_OBJECT,
632                                    "Unexpected clCreateImage return");
633 
634                 err = clReleaseMemObject(buffer);
635                 test_error(err, "Unable to release buffer");
636             }
637         }
638     }
639 
640     return TEST_PASS;
641 }
642 
image_from_buffer_fill_check(cl_command_queue queue,cl_mem image,size_t * region,size_t element_size,char pattern)643 static int image_from_buffer_fill_check(cl_command_queue queue, cl_mem image,
644                                         size_t* region, size_t element_size,
645                                         char pattern)
646 {
647     /* read the image from buffer and check the pattern */
648     const size_t image_size = region[0] * region[1] * region[2] * element_size;
649     size_t origin[3] = { 0, 0, 0 };
650     std::vector<char> read_buffer(image_size);
651 
652     cl_int error =
653         clEnqueueReadImage(queue, image, CL_BLOCKING, origin, region, 0, 0,
654                            read_buffer.data(), 0, nullptr, nullptr);
655     test_error(error, "Error clEnqueueReadImage");
656 
657     for (size_t line = 0; line < region[0]; line++)
658     {
659         for (size_t row = 0; row < region[1]; row++)
660         {
661             for (size_t depth = 0; depth < region[2]; depth++)
662             {
663                 for (size_t elmt = 0; elmt < element_size; elmt++)
664                 {
665                     size_t index = line * row * depth * elmt;
666 
667                     if (read_buffer[index] != pattern)
668                     {
669                         test_fail("Image pattern check failed\n");
670                     }
671                 }
672             }
673         }
674     }
675 
676     return TEST_PASS;
677 }
678 
679 /**
680  * Use fill buffer to fill the image from buffer
681  */
image_from_buffer_fill_positive(cl_device_id device,cl_context context,cl_command_queue queue)682 int image_from_buffer_fill_positive(cl_device_id device, cl_context context,
683                                     cl_command_queue queue)
684 {
685     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
686     {
687         log_info("Extension cl_ext_image_requirements_info not available\n");
688         return TEST_SKIPPED_ITSELF;
689     }
690 
691     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
692     {
693         log_info("Extension cl_ext_image_from_buffer not available\n");
694         return TEST_SKIPPED_ITSELF;
695     }
696 
697     std::vector<cl_mem_object_type> imageTypes{
698         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
699         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
700         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
701     };
702 
703     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
704                                          CL_MEM_READ_WRITE,
705                                          CL_MEM_KERNEL_READ_AND_WRITE };
706 
707     for (auto flagType : flagTypes)
708     {
709         for (auto imageType : imageTypes)
710         {
711             /* Get the list of supported image formats */
712             std::vector<cl_image_format> formatList;
713             if (TEST_PASS
714                     != get_format_list(context, imageType, formatList, flagType)
715                 || formatList.size() == 0)
716             {
717                 test_fail("Failure to get supported formats list\n");
718             }
719 
720             for (auto format : formatList)
721             {
722                 if (!IsChannelOrderSupported(format.image_channel_order)
723                     || !IsChannelTypeSupported(format.image_channel_data_type))
724                 {
725                     continue;
726                 }
727 
728                 cl_image_desc image_desc = { 0 };
729                 image_desc_init(&image_desc, imageType);
730 
731                 cl_mem_flags flag = (flagType == CL_MEM_KERNEL_READ_AND_WRITE)
732                     ? CL_MEM_READ_WRITE
733                     : flagType;
734 
735                 size_t row_pitch_alignment = 0;
736                 size_t slice_pitch_alignment = 0;
737 
738                 int get_error = get_image_requirement_alignment(
739                     device, context, flag, &format, &image_desc,
740                     &row_pitch_alignment, &slice_pitch_alignment, nullptr);
741                 if (TEST_PASS != get_error)
742                 {
743                     return get_error;
744                 }
745 
746                 const size_t element_size =
747                     get_format_size(context, &format, imageType, flag);
748 
749                 const size_t row_pitch = aligned_size(
750                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
751                 const size_t slice_pitch = aligned_size(
752                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
753 
754                 const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
755 
756                 cl_int err = CL_SUCCESS;
757                 cl_mem buffer =
758                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
759                 test_error(err, "Unable to create buffer");
760 
761                 /* fill the buffer with a pattern */
762                 const char pattern = 0x55;
763                 err = clEnqueueFillBuffer(queue, buffer, &pattern,
764                                           sizeof(pattern), 0, buffer_size, 0,
765                                           nullptr, nullptr);
766                 test_error(err, "Error clEnqueueFillBuffer");
767 
768                 err = clFinish(queue);
769                 test_error(err, "Error clFinish");
770 
771                 cl_mem image1d_buffer;
772                 if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER)
773                 {
774                     image1d_buffer = clCreateBuffer(context, flag, buffer_size,
775                                                     nullptr, &err);
776                     test_error(err, "Unable to create buffer");
777 
778                     image_desc.buffer = image1d_buffer;
779                 }
780 
781                 cl_mem image = clCreateImage(context, flag, &format,
782                                              &image_desc, nullptr, &err);
783                 test_error(err, "Unable to create image");
784 
785                 /* Check the image from buffer */
786                 image_desc.buffer = buffer;
787 
788                 if (imageType == CL_MEM_OBJECT_IMAGE2D
789                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
790                 {
791                     image_desc.image_row_pitch = row_pitch;
792                 }
793                 else if (imageType == CL_MEM_OBJECT_IMAGE3D
794                          || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
795                 {
796                     image_desc.image_row_pitch = row_pitch;
797                     image_desc.image_slice_pitch = slice_pitch;
798                 }
799 
800                 cl_mem image_from_buffer = clCreateImage(
801                     context, flag, &format, &image_desc, nullptr, &err);
802                 test_error(err, "Unable to create image");
803 
804                 size_t origin[3] = { 0, 0, 0 };
805                 size_t region[3] = { 1, 1, 1 };
806 
807                 region[0] = TEST_IMAGE_SIZE;
808                 if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType
809                     && CL_MEM_OBJECT_IMAGE1D != imageType)
810                 {
811                     region[1] = TEST_IMAGE_SIZE;
812                 }
813                 if (CL_MEM_OBJECT_IMAGE3D == imageType
814                     || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType)
815                 {
816                     region[2] = TEST_IMAGE_SIZE;
817                 }
818 
819                 /* Check the copy of the image from buffer */
820                 err =
821                     clEnqueueCopyImage(queue, image_from_buffer, image, origin,
822                                        origin, region, 0, nullptr, nullptr);
823                 test_error(err, "Error clEnqueueCopyImage");
824 
825                 err = clFinish(queue);
826                 test_error(err, "Error clFinish");
827 
828                 int fill_error = image_from_buffer_fill_check(
829                     queue, image_from_buffer, region, element_size, pattern);
830                 if (TEST_PASS != fill_error)
831                 {
832                     return fill_error;
833                 }
834 
835                 fill_error = image_from_buffer_fill_check(
836                     queue, image, region, element_size, pattern);
837                 if (TEST_PASS != fill_error)
838                 {
839                     return fill_error;
840                 }
841 
842                 err = clReleaseMemObject(buffer);
843                 test_error(err, "Unable to release buffer");
844 
845                 err = clReleaseMemObject(image);
846                 test_error(err, "Unable to release image");
847 
848                 err = clReleaseMemObject(image_from_buffer);
849                 test_error(err, "Unable to release image");
850 
851                 if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER)
852                 {
853                     err = clReleaseMemObject(image1d_buffer);
854                     test_error(err, "Unable to release image");
855                 }
856             }
857         }
858     }
859 
860     return TEST_PASS;
861 }
862 
image_from_buffer_read_check(cl_command_queue queue,cl_mem buffer,const size_t buffer_size,size_t * region,size_t element_size,char pattern,size_t row_pitch,size_t slice_pitch)863 static int image_from_buffer_read_check(cl_command_queue queue, cl_mem buffer,
864                                         const size_t buffer_size,
865                                         size_t* region, size_t element_size,
866                                         char pattern, size_t row_pitch,
867                                         size_t slice_pitch)
868 {
869     /* read the buffer and check the pattern */
870     std::vector<char> host_buffer(buffer_size);
871     char* host_ptr = host_buffer.data();
872     char* host_ptr_slice = host_ptr;
873 
874     cl_int error =
875         clEnqueueReadBuffer(queue, buffer, CL_BLOCKING, 0, buffer_size,
876                             host_buffer.data(), 0, nullptr, nullptr);
877     test_error(error, "Error clEnqueueReadBuffer");
878 
879     for (size_t k = 0; k < region[2]; k++)
880     {
881         for (size_t i = 0; i < region[1]; i++)
882         {
883             for (size_t j = 0; j < region[0] * element_size; j++)
884             {
885                 if (host_ptr[j] != pattern)
886                 {
887                     test_fail("Image pattern check failed\n");
888                 }
889             }
890             host_ptr = host_ptr + row_pitch;
891         }
892         host_ptr_slice = host_ptr_slice + slice_pitch;
893         host_ptr = host_ptr_slice;
894     }
895 
896     return TEST_PASS;
897 }
898 
899 /**
900  * Use fill image to fill the buffer that was used to create the image
901  */
image_from_buffer_read_positive(cl_device_id device,cl_context context,cl_command_queue queue)902 int image_from_buffer_read_positive(cl_device_id device, cl_context context,
903                                     cl_command_queue queue)
904 {
905     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
906     {
907         log_info("Extension cl_ext_image_requirements_info not available\n");
908         return TEST_SKIPPED_ITSELF;
909     }
910 
911     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
912     {
913         log_info("Extension cl_ext_image_from_buffer not available\n");
914         return TEST_SKIPPED_ITSELF;
915     }
916 
917     std::vector<cl_mem_object_type> imageTypes{
918         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
919         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
920         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
921     };
922 
923     for (auto imageType : imageTypes)
924     {
925         cl_image_desc image_desc = { 0 };
926         image_desc_init(&image_desc, imageType);
927 
928         /* Non normalized format so we can read it back directly from
929          * clEnqueueFillImage */
930         cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT8 };
931         const char pattern = 0x55;
932 
933         const size_t element_size =
934             get_format_size(context, &format, imageType, CL_MEM_READ_WRITE);
935 
936         size_t row_pitch_alignment = 0;
937         size_t slice_pitch_alignment = 0;
938 
939         int get_error = get_image_requirement_alignment(
940             device, context, CL_MEM_READ_WRITE, &format, &image_desc,
941             &row_pitch_alignment, &slice_pitch_alignment, nullptr);
942         if (TEST_PASS != get_error)
943         {
944             return get_error;
945         }
946 
947         const size_t row_pitch =
948             aligned_size(TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
949         const size_t slice_pitch = aligned_size(
950             row_pitch
951                 * (imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY ? 1
952                                                             : TEST_IMAGE_SIZE),
953             slice_pitch_alignment);
954 
955         const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
956 
957         cl_int err = CL_SUCCESS;
958         cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_size,
959                                        nullptr, &err);
960         test_error(err, "Unable to create buffer");
961 
962         /* Check the image from buffer */
963         image_desc.buffer = buffer;
964 
965         if (imageType == CL_MEM_OBJECT_IMAGE2D
966             || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
967         {
968             image_desc.image_row_pitch = row_pitch;
969         }
970         else if (imageType == CL_MEM_OBJECT_IMAGE3D
971                  || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
972         {
973             image_desc.image_row_pitch = row_pitch;
974             image_desc.image_slice_pitch = slice_pitch;
975         }
976 
977         cl_mem image = clCreateImage(context, CL_MEM_READ_WRITE, &format,
978                                      &image_desc, nullptr, &err);
979         test_error(err, "Unable to create image");
980 
981         size_t origin[3] = { 0, 0, 0 };
982         size_t region[3] = { 1, 1, 1 };
983 
984         region[0] = TEST_IMAGE_SIZE;
985         if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType
986             && CL_MEM_OBJECT_IMAGE1D != imageType)
987         {
988             region[1] = TEST_IMAGE_SIZE;
989         }
990         if (CL_MEM_OBJECT_IMAGE3D == imageType
991             || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType)
992         {
993             region[2] = TEST_IMAGE_SIZE;
994         }
995 
996         /* fill the image with a pattern */
997         cl_uint fill_color[4] = { pattern, pattern, pattern, pattern };
998         err = clEnqueueFillImage(queue, image, fill_color, origin, region, 0,
999                                  nullptr, nullptr);
1000         test_error(err, "Error clEnqueueFillImage");
1001 
1002         err = clFinish(queue);
1003         test_error(err, "Error clFinish");
1004 
1005         int read_error = image_from_buffer_read_check(
1006             queue, buffer, buffer_size, region, element_size, pattern,
1007             (imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) ? slice_pitch
1008                                                        : row_pitch,
1009             slice_pitch);
1010         if (TEST_PASS != read_error)
1011         {
1012             return read_error;
1013         }
1014 
1015         err = clReleaseMemObject(buffer);
1016         test_error(err, "Unable to release buffer");
1017 
1018         err = clReleaseMemObject(image);
1019         test_error(err, "Unable to release image");
1020     }
1021 
1022     return TEST_PASS;
1023 }
1024