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