• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         printf("Extension cl_khr_image2d_from_buffer not available");
73         return TEST_SKIPPED_ITSELF;
74     }
75 
76     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
77     {
78         printf("Extension cl_ext_image_requirements_info not available");
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 flag : 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, flag)
100                 || formatList.size() == 0)
101             {
102                 test_fail("Failure to get supported formats list");
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                 flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE)
125                     ? CL_MEM_READ_WRITE
126                     : flag;
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, 0, &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");
147                 }
148 
149                 if (row_pitch_alignment > row_pitch_alignment_2d * element_size)
150                 {
151                     test_fail("Unexpected row_pitch_alignment");
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         printf("Extension cl_ext_image_requirements_info not available");
171         return TEST_SKIPPED_ITSELF;
172     }
173 
174     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
175     {
176         printf("Extension cl_ext_image_from_buffer not available");
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 flag : 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, flag)
198                 || formatList.size() == 0)
199             {
200                 test_fail("Failure to get supported formats list");
201             }
202 
203             for (auto format : formatList)
204             {
205                 cl_image_desc image_desc = { 0 };
206                 image_desc_init(&image_desc, imageType);
207 
208                 flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE)
209                     ? CL_MEM_READ_WRITE
210                     : flag;
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, 0, &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("Unexpected CL_MEM_ASSOCIATED_MEMOBJECT buffer");
253                 }
254 
255                 err = clReleaseMemObject(buffer);
256                 test_error(err, "Unable to release buffer");
257 
258                 err = clReleaseMemObject(image_buffer);
259                 test_error(err, "Unable to release image");
260             }
261         }
262     }
263 
264     return TEST_PASS;
265 }
266 
267 /**
268  * Test clGetImageInfo
269  * Check that the returned values for CL_IMAGE_ROW_PITCH and
270  * CL_IMAGE_SLICE_PITCH are correct.
271  */
imageInfo_image_from_buffer_positive(cl_device_id device,cl_context context,cl_command_queue queue)272 int imageInfo_image_from_buffer_positive(cl_device_id device,
273                                          cl_context context,
274                                          cl_command_queue queue)
275 {
276     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
277     {
278         printf("Extension cl_ext_image_requirements_info not available");
279         return TEST_SKIPPED_ITSELF;
280     }
281 
282     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
283     {
284         printf("Extension cl_ext_image_from_buffer not available");
285         return TEST_SKIPPED_ITSELF;
286     }
287 
288     std::vector<cl_mem_object_type> imageTypes{
289         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
290         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
291         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
292     };
293 
294     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
295                                          CL_MEM_READ_WRITE,
296                                          CL_MEM_KERNEL_READ_AND_WRITE };
297 
298     for (auto flag : flagTypes)
299     {
300         for (auto imageType : imageTypes)
301         {
302             /* Get the list of supported image formats */
303             std::vector<cl_image_format> formatList;
304             if (TEST_PASS
305                     != get_format_list(context, imageType, formatList, flag)
306                 || formatList.size() == 0)
307             {
308                 test_fail("Failure to get supported formats list");
309             }
310 
311             for (auto format : formatList)
312             {
313                 cl_image_desc image_desc = { 0 };
314                 image_desc_init(&image_desc, imageType);
315 
316                 flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE)
317                     ? CL_MEM_READ_WRITE
318                     : flag;
319 
320                 size_t row_pitch_alignment = 0;
321                 size_t slice_pitch_alignment = 0;
322 
323                 int get_error = get_image_requirement_alignment(
324                     device, context, 0, &format, &image_desc,
325                     &row_pitch_alignment, &slice_pitch_alignment, nullptr);
326                 if (TEST_PASS != get_error)
327                 {
328                     return get_error;
329                 }
330 
331                 const size_t element_size =
332                     get_format_size(context, &format, imageType, flag);
333 
334                 const size_t row_pitch = aligned_size(
335                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
336                 const size_t slice_pitch = aligned_size(
337                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
338 
339                 const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
340 
341                 cl_int err = CL_SUCCESS;
342                 cl_mem buffer =
343                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
344                 test_error(err, "Unable to create buffer");
345 
346                 image_desc.buffer = buffer;
347 
348                 if (imageType == CL_MEM_OBJECT_IMAGE2D
349                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
350                 {
351                     image_desc.image_row_pitch = row_pitch;
352                 }
353                 else if (imageType == CL_MEM_OBJECT_IMAGE3D
354                          || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
355                 {
356                     image_desc.image_row_pitch = row_pitch;
357                     image_desc.image_slice_pitch = slice_pitch;
358                 }
359 
360                 cl_mem image_buffer = clCreateImage(context, flag, &format,
361                                                     &image_desc, nullptr, &err);
362                 test_error(err, "Unable to create image");
363 
364                 if (imageType == CL_MEM_OBJECT_IMAGE3D
365                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY
366                     || imageType == CL_MEM_OBJECT_IMAGE2D
367                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
368                 {
369                     size_t returned_row_pitch = 0;
370                     err = clGetImageInfo(image_buffer, CL_IMAGE_ROW_PITCH,
371                                          sizeof(returned_row_pitch),
372                                          &returned_row_pitch, nullptr);
373                     test_error(err, "Error clGetImageInfo");
374 
375                     if (returned_row_pitch != row_pitch)
376                     {
377                         test_fail(
378                             "Unexpected row pitch "
379                             "CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT");
380                     }
381                 }
382 
383                 if (imageType == CL_MEM_OBJECT_IMAGE3D
384                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
385                 {
386                     size_t returned_slice_pitch = 0;
387                     err = clGetImageInfo(image_buffer, CL_IMAGE_SLICE_PITCH,
388                                          sizeof(returned_slice_pitch),
389                                          &returned_slice_pitch, nullptr);
390                     test_error(err, "Error clGetImageInfo");
391 
392                     if (returned_slice_pitch != slice_pitch)
393                     {
394                         test_fail(
395                             "Unexpected row pitch "
396                             "CL_IMAGE_REQUIREMENTS_SLICE_PITCH_ALIGNMENT_EXT");
397                     }
398                 }
399 
400                 err = clReleaseMemObject(buffer);
401                 test_error(err, "Unable to release buffer");
402 
403                 err = clReleaseMemObject(image_buffer);
404                 test_error(err, "Unable to release image");
405             }
406         }
407     }
408 
409     return TEST_PASS;
410 }
411 
412 /**
413  * Negative testing for clCreateImage and wrong alignment
414  * - Create an image from a buffer with invalid row pitch (not a multiple of
415  * required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is returned.
416  * - Create an image from a buffer with invalid slice pitch (not a multiple of
417  * required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is returned.
418  * - Create an image from a buffer with invalid base address alignment (not a
419  * multiple of required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is
420  * returned
421  */
image_from_buffer_alignment_negative(cl_device_id device,cl_context context,cl_command_queue queue)422 int image_from_buffer_alignment_negative(cl_device_id device,
423                                          cl_context context,
424                                          cl_command_queue queue)
425 {
426     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
427     {
428         printf("Extension cl_ext_image_requirements_info not available");
429         return TEST_SKIPPED_ITSELF;
430     }
431 
432     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
433     {
434         printf("Extension cl_ext_image_from_buffer not available");
435         return TEST_SKIPPED_ITSELF;
436     }
437 
438     std::vector<cl_mem_object_type> imageTypes{
439         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
440         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
441         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
442     };
443 
444     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
445                                          CL_MEM_READ_WRITE,
446                                          CL_MEM_KERNEL_READ_AND_WRITE };
447 
448     for (auto flag : flagTypes)
449     {
450         for (auto imageType : imageTypes)
451         {
452             /* Get the list of supported image formats */
453             std::vector<cl_image_format> formatList;
454             if (TEST_PASS
455                     != get_format_list(context, imageType, formatList, flag)
456                 || formatList.size() == 0)
457             {
458                 test_fail("Failure to get supported formats list");
459             }
460 
461             for (auto format : formatList)
462             {
463                 cl_image_desc image_desc = { 0 };
464                 image_desc_init(&image_desc, imageType);
465 
466                 flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE)
467                     ? CL_MEM_READ_WRITE
468                     : flag;
469 
470                 size_t row_pitch_alignment = 0;
471                 size_t slice_pitch_alignment = 0;
472                 size_t base_address_alignment = 0;
473 
474                 int get_error = get_image_requirement_alignment(
475                     device, context, 0, &format, &image_desc,
476                     &row_pitch_alignment, &slice_pitch_alignment,
477                     &base_address_alignment);
478                 if (TEST_PASS != get_error)
479                 {
480                     return get_error;
481                 }
482 
483                 const size_t element_size =
484                     get_format_size(context, &format, imageType, flag);
485 
486                 const size_t row_pitch = aligned_size(
487                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
488                 const size_t slice_pitch = aligned_size(
489                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
490 
491                 const size_t buffer_size = (slice_pitch + 1)
492                     * TEST_IMAGE_SIZE; /* For bigger row/slice pitch */
493 
494                 cl_int err = CL_SUCCESS;
495                 cl_mem buffer =
496                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
497                 test_error(err, "Unable to create buffer");
498 
499                 /* Test Row pitch images */
500                 if (imageType == CL_MEM_OBJECT_IMAGE2D
501                     || imageType == CL_MEM_OBJECT_IMAGE3D
502                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY
503                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
504                 {
505                     image_desc.buffer = buffer;
506                     image_desc.image_row_pitch =
507                         row_pitch + 1; /* wrong row pitch */
508 
509                     clCreateImage(context, flag, &format, &image_desc, nullptr,
510                                   &err);
511                     test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
512                                        "Unexpected clCreateImage return");
513                 }
514 
515                 /* Test Slice pitch images */
516                 if (imageType == CL_MEM_OBJECT_IMAGE3D
517                     || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
518                 {
519                     image_desc.buffer = buffer;
520                     image_desc.image_row_pitch = row_pitch;
521                     image_desc.image_slice_pitch =
522                         slice_pitch + 1; /* wrong slice pitch */
523 
524                     clCreateImage(context, flag, &format, &image_desc, nullptr,
525                                   &err);
526                     test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
527                                        "Unexpected clCreateImage return");
528                 }
529 
530                 /* Test buffer from host ptr to test base address alignment */
531                 const size_t aligned_buffer_size =
532                     aligned_size(buffer_size, base_address_alignment);
533                 /* Create buffer with host ptr and additional size for the wrong
534                  * alignment */
535                 void* const host_ptr =
536                     malloc(aligned_buffer_size + base_address_alignment);
537                 void* non_aligned_host_ptr =
538                     (void*)((char*)(aligned_ptr(host_ptr,
539                                                 base_address_alignment))
540                             + 1); /* wrong alignment */
541 
542                 cl_mem buffer_host = clCreateBuffer(
543                     context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE,
544                     buffer_size, non_aligned_host_ptr, &err);
545                 test_error(err, "Unable to create buffer");
546 
547                 image_desc.buffer = buffer_host;
548 
549                 clCreateImage(context, flag, &format, &image_desc, nullptr,
550                               &err);
551                 test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR,
552                                    "Unexpected clCreateImage return");
553 
554                 free(host_ptr);
555 
556                 err = clReleaseMemObject(buffer);
557                 test_error(err, "Unable to release buffer");
558 
559                 err = clReleaseMemObject(buffer_host);
560                 test_error(err, "Unable to release buffer");
561             }
562         }
563     }
564 
565     return TEST_PASS;
566 }
567 
568 /**
569  * Negative testing for clCreateImage (buffer size).
570  * Create a buffer too small and check that image creation from that buffer is
571  * rejected
572  */
image_from_small_buffer_negative(cl_device_id device,cl_context context,cl_command_queue queue)573 int image_from_small_buffer_negative(cl_device_id device, cl_context context,
574                                      cl_command_queue queue)
575 {
576     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
577     {
578         printf("Extension cl_ext_image_requirements_info not available");
579         return TEST_SKIPPED_ITSELF;
580     }
581 
582     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
583     {
584         printf("Extension cl_ext_image_from_buffer not available");
585         return TEST_SKIPPED_ITSELF;
586     }
587 
588     std::vector<cl_mem_object_type> imageTypes{
589         CL_MEM_OBJECT_IMAGE1D,        CL_MEM_OBJECT_IMAGE2D,
590         CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE3D,
591         CL_MEM_OBJECT_IMAGE1D_ARRAY,  CL_MEM_OBJECT_IMAGE2D_ARRAY
592     };
593 
594     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
595                                          CL_MEM_READ_WRITE,
596                                          CL_MEM_KERNEL_READ_AND_WRITE };
597 
598     for (auto flag : flagTypes)
599     {
600         for (auto imageType : imageTypes)
601         {
602             /* Get the list of supported image formats */
603             std::vector<cl_image_format> formatList;
604             if (TEST_PASS
605                     != get_format_list(context, imageType, formatList, flag)
606                 || formatList.size() == 0)
607             {
608                 test_fail("Failure to get supported formats list");
609             }
610 
611             for (auto format : formatList)
612             {
613                 cl_image_desc image_desc = { 0 };
614                 image_desc_init(&image_desc, imageType);
615 
616                 flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE)
617                     ? CL_MEM_READ_WRITE
618                     : flag;
619 
620                 /* Invalid buffer size */
621                 cl_int err;
622                 cl_mem buffer = clCreateBuffer(
623                     context, flag, TEST_IMAGE_SIZE / 2, nullptr, &err);
624                 test_error(err, "Unable to create buffer");
625 
626                 image_desc.buffer = buffer;
627 
628                 clCreateImage(context, flag, &format, &image_desc, nullptr,
629                               &err);
630                 test_failure_error(err, CL_INVALID_MEM_OBJECT,
631                                    "Unexpected clCreateImage return");
632 
633                 err = clReleaseMemObject(buffer);
634                 test_error(err, "Unable to release buffer");
635             }
636         }
637     }
638 
639     return TEST_PASS;
640 }
641 
image_from_buffer_fill_check(cl_command_queue queue,cl_mem image,size_t * region,size_t element_size,char pattern)642 static int image_from_buffer_fill_check(cl_command_queue queue, cl_mem image,
643                                         size_t* region, size_t element_size,
644                                         char pattern)
645 {
646     /* read the image from buffer and check the pattern */
647     const size_t image_size = region[0] * region[1] * region[2] * element_size;
648     size_t origin[3] = { 0, 0, 0 };
649     std::vector<char> read_buffer(image_size);
650 
651     cl_int error =
652         clEnqueueReadImage(queue, image, CL_BLOCKING, origin, region, 0, 0,
653                            read_buffer.data(), 0, nullptr, nullptr);
654     test_error(error, "Error clEnqueueReadImage");
655 
656     for (size_t line = 0; line < region[0]; line++)
657     {
658         for (size_t row = 0; row < region[1]; row++)
659         {
660             for (size_t depth = 0; depth < region[2]; depth++)
661             {
662                 for (size_t elmt = 0; elmt < element_size; elmt++)
663                 {
664                     size_t index = line * row * depth * elmt;
665 
666                     if (read_buffer[index] != pattern)
667                     {
668                         test_fail("Image pattern check failed");
669                     }
670                 }
671             }
672         }
673     }
674 
675     return TEST_PASS;
676 }
677 
678 /**
679  * Use fill buffer to fill the image from buffer
680  */
image_from_buffer_fill_positive(cl_device_id device,cl_context context,cl_command_queue queue)681 int image_from_buffer_fill_positive(cl_device_id device, cl_context context,
682                                     cl_command_queue queue)
683 {
684     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
685     {
686         printf("Extension cl_ext_image_requirements_info not available");
687         return TEST_SKIPPED_ITSELF;
688     }
689 
690     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
691     {
692         printf("Extension cl_ext_image_from_buffer not available");
693         return TEST_SKIPPED_ITSELF;
694     }
695 
696     std::vector<cl_mem_object_type> imageTypes{
697         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
698         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
699         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
700     };
701 
702     std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY,
703                                          CL_MEM_READ_WRITE,
704                                          CL_MEM_KERNEL_READ_AND_WRITE };
705 
706     for (auto flag : flagTypes)
707     {
708         for (auto imageType : imageTypes)
709         {
710             /* Get the list of supported image formats */
711             std::vector<cl_image_format> formatList;
712             if (TEST_PASS
713                     != get_format_list(context, imageType, formatList, flag)
714                 || formatList.size() == 0)
715             {
716                 test_fail("Failure to get supported formats list");
717             }
718 
719             for (auto format : formatList)
720             {
721                 cl_image_desc image_desc = { 0 };
722                 image_desc_init(&image_desc, imageType);
723 
724                 flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE)
725                     ? CL_MEM_READ_WRITE
726                     : flag;
727 
728                 size_t row_pitch_alignment = 0;
729                 size_t slice_pitch_alignment = 0;
730 
731                 int get_error = get_image_requirement_alignment(
732                     device, context, 0, &format, &image_desc,
733                     &row_pitch_alignment, &slice_pitch_alignment, nullptr);
734                 if (TEST_PASS != get_error)
735                 {
736                     return get_error;
737                 }
738 
739                 const size_t element_size =
740                     get_format_size(context, &format, imageType, flag);
741 
742                 const size_t row_pitch = aligned_size(
743                     TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
744                 const size_t slice_pitch = aligned_size(
745                     row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
746 
747                 const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
748 
749                 cl_int err = CL_SUCCESS;
750                 cl_mem buffer =
751                     clCreateBuffer(context, flag, buffer_size, nullptr, &err);
752                 test_error(err, "Unable to create buffer");
753 
754                 /* fill the buffer with a pattern */
755                 const char pattern = 0x55;
756                 err = clEnqueueFillBuffer(queue, buffer, &pattern,
757                                           sizeof(pattern), 0, buffer_size, 0,
758                                           nullptr, nullptr);
759                 test_error(err, "Error clEnqueueFillBuffer");
760 
761                 err = clFinish(queue);
762                 test_error(err, "Error clFinish");
763 
764                 cl_mem image1d_buffer;
765                 if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER)
766                 {
767                     image1d_buffer = clCreateBuffer(context, flag, buffer_size,
768                                                     nullptr, &err);
769                     test_error(err, "Unable to create buffer");
770 
771                     image_desc.buffer = image1d_buffer;
772                 }
773 
774                 cl_mem image = clCreateImage(context, flag, &format,
775                                              &image_desc, nullptr, &err);
776                 test_error(err, "Unable to create image");
777 
778                 /* Check the image from buffer */
779                 image_desc.buffer = buffer;
780 
781                 if (imageType == CL_MEM_OBJECT_IMAGE2D
782                     || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
783                 {
784                     image_desc.image_row_pitch = row_pitch;
785                 }
786                 else if (imageType == CL_MEM_OBJECT_IMAGE3D
787                          || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
788                 {
789                     image_desc.image_row_pitch = row_pitch;
790                     image_desc.image_slice_pitch = slice_pitch;
791                 }
792 
793                 cl_mem image_from_buffer = clCreateImage(
794                     context, flag, &format, &image_desc, nullptr, &err);
795                 test_error(err, "Unable to create image");
796 
797                 size_t origin[3] = { 0, 0, 0 };
798                 size_t region[3] = { 1, 1, 1 };
799 
800                 region[0] = TEST_IMAGE_SIZE;
801                 if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType
802                     && CL_MEM_OBJECT_IMAGE1D != imageType)
803                 {
804                     region[1] = TEST_IMAGE_SIZE;
805                 }
806                 if (CL_MEM_OBJECT_IMAGE3D == imageType
807                     || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType)
808                 {
809                     region[2] = TEST_IMAGE_SIZE;
810                 }
811 
812                 /* Check the copy of the image from buffer */
813                 err =
814                     clEnqueueCopyImage(queue, image_from_buffer, image, origin,
815                                        origin, region, 0, nullptr, nullptr);
816                 test_error(err, "Error clEnqueueCopyImage");
817 
818                 err = clFinish(queue);
819                 test_error(err, "Error clFinish");
820 
821                 int fill_error = image_from_buffer_fill_check(
822                     queue, image_from_buffer, region, element_size, pattern);
823                 if (TEST_PASS != fill_error)
824                 {
825                     return fill_error;
826                 }
827 
828                 fill_error = image_from_buffer_fill_check(
829                     queue, image, region, element_size, pattern);
830                 if (TEST_PASS != fill_error)
831                 {
832                     return fill_error;
833                 }
834 
835                 err = clReleaseMemObject(buffer);
836                 test_error(err, "Unable to release buffer");
837 
838                 err = clReleaseMemObject(image);
839                 test_error(err, "Unable to release image");
840 
841                 err = clReleaseMemObject(image_from_buffer);
842                 test_error(err, "Unable to release image");
843 
844                 if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER)
845                 {
846                     err = clReleaseMemObject(image1d_buffer);
847                     test_error(err, "Unable to release image");
848                 }
849             }
850         }
851     }
852 
853     return TEST_PASS;
854 }
855 
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)856 static int image_from_buffer_read_check(cl_command_queue queue, cl_mem buffer,
857                                         const size_t buffer_size,
858                                         size_t* region, size_t element_size,
859                                         char pattern, size_t row_pitch,
860                                         size_t slice_pitch)
861 {
862     /* read the buffer and check the pattern */
863     std::vector<char> host_buffer(buffer_size);
864     char* host_ptr = host_buffer.data();
865     char* host_ptr_slice = host_ptr;
866 
867     cl_int error =
868         clEnqueueReadBuffer(queue, buffer, CL_BLOCKING, 0, buffer_size,
869                             host_buffer.data(), 0, nullptr, nullptr);
870     test_error(error, "Error clEnqueueReadBuffer");
871 
872     for (size_t k = 0; k < region[2]; k++)
873     {
874         for (size_t i = 0; i < region[1]; i++)
875         {
876             for (size_t j = 0; j < region[0] * element_size; j++)
877             {
878                 if (host_ptr[j] != pattern)
879                 {
880                     test_fail("Image pattern check failed");
881                 }
882             }
883             host_ptr = host_ptr + row_pitch;
884         }
885         host_ptr_slice = host_ptr_slice + slice_pitch;
886         host_ptr = host_ptr_slice;
887     }
888 
889     return TEST_PASS;
890 }
891 
892 /**
893  * Use fill image to fill the buffer that was used to create the image
894  */
image_from_buffer_read_positive(cl_device_id device,cl_context context,cl_command_queue queue)895 int image_from_buffer_read_positive(cl_device_id device, cl_context context,
896                                     cl_command_queue queue)
897 {
898     if (!is_extension_available(device, "cl_ext_image_requirements_info"))
899     {
900         printf("Extension cl_ext_image_requirements_info not available");
901         return TEST_SKIPPED_ITSELF;
902     }
903 
904     if (!is_extension_available(device, "cl_ext_image_from_buffer"))
905     {
906         printf("Extension cl_ext_image_from_buffer not available");
907         return TEST_SKIPPED_ITSELF;
908     }
909 
910     std::vector<cl_mem_object_type> imageTypes{
911         CL_MEM_OBJECT_IMAGE1D,       CL_MEM_OBJECT_IMAGE2D,
912         CL_MEM_OBJECT_IMAGE3D,       CL_MEM_OBJECT_IMAGE1D_BUFFER,
913         CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY
914     };
915 
916     for (auto imageType : imageTypes)
917     {
918         cl_image_desc image_desc = { 0 };
919         image_desc_init(&image_desc, imageType);
920 
921         /* Non normalized format so we can read it back directly from
922          * clEnqueueFillImage */
923         cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT8 };
924         const char pattern = 0x55;
925 
926         const size_t element_size =
927             get_format_size(context, &format, imageType, CL_MEM_READ_WRITE);
928 
929         size_t row_pitch_alignment = 0;
930         size_t slice_pitch_alignment = 0;
931 
932         int get_error = get_image_requirement_alignment(
933             device, context, CL_MEM_READ_WRITE, &format, &image_desc,
934             &row_pitch_alignment, &slice_pitch_alignment, nullptr);
935         if (TEST_PASS != get_error)
936         {
937             return get_error;
938         }
939 
940         const size_t row_pitch =
941             aligned_size(TEST_IMAGE_SIZE * element_size, row_pitch_alignment);
942         const size_t slice_pitch =
943             aligned_size(row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment);
944 
945         const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE;
946 
947         cl_int err = CL_SUCCESS;
948         cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_size,
949                                        nullptr, &err);
950         test_error(err, "Unable to create buffer");
951 
952         /* Check the image from buffer */
953         image_desc.buffer = buffer;
954 
955         if (imageType == CL_MEM_OBJECT_IMAGE2D
956             || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY)
957         {
958             image_desc.image_row_pitch = row_pitch;
959         }
960         else if (imageType == CL_MEM_OBJECT_IMAGE3D
961                  || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY)
962         {
963             image_desc.image_row_pitch = row_pitch;
964             image_desc.image_slice_pitch = slice_pitch;
965         }
966 
967         cl_mem image = clCreateImage(context, CL_MEM_READ_WRITE, &format,
968                                      &image_desc, nullptr, &err);
969         test_error(err, "Unable to create image");
970 
971         size_t origin[3] = { 0, 0, 0 };
972         size_t region[3] = { 1, 1, 1 };
973 
974         region[0] = TEST_IMAGE_SIZE;
975         if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType
976             && CL_MEM_OBJECT_IMAGE1D != imageType)
977         {
978             region[1] = TEST_IMAGE_SIZE;
979         }
980         if (CL_MEM_OBJECT_IMAGE3D == imageType
981             || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType)
982         {
983             region[2] = TEST_IMAGE_SIZE;
984         }
985 
986         /* fill the image with a pattern */
987         cl_uint fill_color[4] = { pattern, pattern, pattern, pattern };
988         err = clEnqueueFillImage(queue, image, fill_color, origin, region, 0,
989                                  nullptr, nullptr);
990         test_error(err, "Error clEnqueueFillImage");
991 
992         err = clFinish(queue);
993         test_error(err, "Error clFinish");
994 
995         int read_error = image_from_buffer_read_check(
996             queue, buffer, buffer_size, region, element_size, pattern,
997             (imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) ? slice_pitch
998                                                        : row_pitch,
999             slice_pitch);
1000         if (TEST_PASS != read_error)
1001         {
1002             return read_error;
1003         }
1004 
1005         err = clReleaseMemObject(buffer);
1006         test_error(err, "Unable to release buffer");
1007 
1008         err = clReleaseMemObject(image);
1009         test_error(err, "Unable to release image");
1010     }
1011 
1012     return TEST_PASS;
1013 }