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 }