diff options
author | Kévin Petit <kevin.petit@arm.com> | 2022-09-13 17:58:24 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-13 09:58:24 -0700 |
commit | c0a10f4e12c1a4866a37449c5697a2f4c5e82e25 (patch) | |
tree | a4aa67363b62f5df7fd829c1262b58eda0dd9a69 | |
parent | 426097cf7c2e0e4b6c659bd0b744e6f51e61805d (diff) | |
download | OpenCL-CTS-c0a10f4e12c1a4866a37449c5697a2f4c5e82e25.tar.gz |
Tests for cl-ext-image-from-buffer and cl-ext-image-requirements-info (#1438)
* Add CTS tests for cl_ext_image_requirements_info
Change-Id: I20c1c77ff5ba88eb475801bafba30ef9caf82601
* Add CTS tests for cl_ext_image_from_buffer
Change-Id: Ic30429d77a1317d0fea7d9ecc6d603267fa6602f
* Fixes for image_from_buffer and image_requirements extension
* Use CL_MEM_READ_WRITE flag when creating images that support CL_MEM_KERNEL_READ_AND_WRITE (#1447)
* format fixes
Change-Id: I04d69720730440cb61e64fed2cb5065b2ff8bf90
Co-authored-by: Oualid Khelifi <oualid.khelifi@arm.com>
Co-authored-by: oramirez <oramirez@qti.qualcomm.com>
Co-authored-by: Sreelakshmi Haridas Maruthur <sharidas@quicinc.com>
5 files changed, 1753 insertions, 5 deletions
diff --git a/test_conformance/images/kernel_read_write/CMakeLists.txt b/test_conformance/images/kernel_read_write/CMakeLists.txt index 54449875..6eb5dc7f 100644 --- a/test_conformance/images/kernel_read_write/CMakeLists.txt +++ b/test_conformance/images/kernel_read_write/CMakeLists.txt @@ -14,6 +14,8 @@ set(${MODULE_NAME}_SOURCES test_write_1D_array.cpp test_write_2D_array.cpp test_write_3D.cpp + test_cl_ext_image_requirements_info.cpp + test_cl_ext_image_from_buffer.cpp ../common.cpp ) diff --git a/test_conformance/images/kernel_read_write/main.cpp b/test_conformance/images/kernel_read_write/main.cpp index 31dceb33..0a93a974 100644 --- a/test_conformance/images/kernel_read_write/main.cpp +++ b/test_conformance/images/kernel_read_write/main.cpp @@ -53,6 +53,43 @@ static void printUsage( const char *execName ); extern int test_image_set( cl_device_id device, cl_context context, cl_command_queue queue, test_format_set_fn formatTestFn, cl_mem_object_type imageType ); +extern int cl_image_requirements_size_ext_negative(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int cl_image_requirements_size_ext_consistency(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int clGetImageRequirementsInfoEXT_negative(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int cl_image_requirements_max_val_ext_negative(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int cl_image_requirements_max_val_ext_positive(cl_device_id device, + cl_context context, + cl_command_queue queue); + +extern int image2d_from_buffer_positive(cl_device_id device, cl_context context, + cl_command_queue queue); +extern int memInfo_image_from_buffer_positive(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int imageInfo_image_from_buffer_positive(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int image_from_buffer_alignment_negative(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int image_from_small_buffer_negative(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int image_from_buffer_fill_positive(cl_device_id device, + cl_context context, + cl_command_queue queue); +extern int image_from_buffer_read_positive(cl_device_id device, + cl_context context, + cl_command_queue queue); + /** read_write images only support sampler-less read buildt-ins which require special settings * for some global parameters. This pair of functions temporarily overwrite those global parameters * and then recover them after completing a read_write test. @@ -246,12 +283,108 @@ int test_2Darray(cl_device_id device, cl_context context, cl_command_queue queue return doTest( device, context, queue, CL_MEM_OBJECT_IMAGE2D_ARRAY ); } +int test_cl_image_requirements_size_ext_negative(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return cl_image_requirements_size_ext_negative(device, context, queue); +} +int test_cl_image_requirements_size_ext_consistency(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return cl_image_requirements_size_ext_consistency(device, context, queue); +} +int test_clGetImageRequirementsInfoEXT_negative(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return clGetImageRequirementsInfoEXT_negative(device, context, queue); +} +int test_cl_image_requirements_max_val_ext_negative(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return cl_image_requirements_max_val_ext_negative(device, context, queue); +} +int test_cl_image_requirements_max_val_ext_positive(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return cl_image_requirements_max_val_ext_positive(device, context, queue); +} + +int test_image2d_from_buffer_positive(cl_device_id device, cl_context context, + cl_command_queue queue, int num_elements) +{ + return image2d_from_buffer_positive(device, context, queue); +} +int test_memInfo_image_from_buffer_positive(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return memInfo_image_from_buffer_positive(device, context, queue); +} +int test_imageInfo_image_from_buffer_positive(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return imageInfo_image_from_buffer_positive(device, context, queue); +} +int test_image_from_buffer_alignment_negative(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return image_from_buffer_alignment_negative(device, context, queue); +} +int test_image_from_small_buffer_negative(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return image_from_small_buffer_negative(device, context, queue); +} +int test_image_from_buffer_fill_positive(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return image_from_buffer_fill_positive(device, context, queue); +} +int test_image_from_buffer_read_positive(cl_device_id device, + cl_context context, + cl_command_queue queue, + int num_elements) +{ + return image_from_buffer_read_positive(device, context, queue); +} + test_definition test_list[] = { - ADD_TEST( 1D ), - ADD_TEST( 2D ), - ADD_TEST( 3D ), - ADD_TEST( 1Darray ), - ADD_TEST( 2Darray ), + ADD_TEST(1D), + ADD_TEST(2D), + ADD_TEST(3D), + ADD_TEST(1Darray), + ADD_TEST(2Darray), + ADD_TEST_VERSION(cl_image_requirements_size_ext_negative, Version(3, 0)), + ADD_TEST_VERSION(cl_image_requirements_size_ext_consistency, Version(3, 0)), + ADD_TEST_VERSION(clGetImageRequirementsInfoEXT_negative, Version(3, 0)), + ADD_TEST_VERSION(cl_image_requirements_max_val_ext_negative, Version(3, 0)), + ADD_TEST_VERSION(cl_image_requirements_max_val_ext_positive, Version(3, 0)), + ADD_TEST_VERSION(image2d_from_buffer_positive, Version(3, 0)), + ADD_TEST_VERSION(memInfo_image_from_buffer_positive, Version(3, 0)), + ADD_TEST_VERSION(imageInfo_image_from_buffer_positive, Version(3, 0)), + ADD_TEST_VERSION(image_from_buffer_alignment_negative, Version(3, 0)), + ADD_TEST_VERSION(image_from_small_buffer_negative, Version(3, 0)), + ADD_TEST_VERSION(image_from_buffer_fill_positive, Version(3, 0)), + ADD_TEST_VERSION(image_from_buffer_read_positive, Version(3, 0)), }; const int test_num = ARRAY_SIZE( test_list ); diff --git a/test_conformance/images/kernel_read_write/test_cl_ext_image_buffer.hpp b/test_conformance/images/kernel_read_write/test_cl_ext_image_buffer.hpp new file mode 100644 index 00000000..c6646330 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_cl_ext_image_buffer.hpp @@ -0,0 +1,124 @@ +// +// Copyright (c) 2022 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef _TEST_CL_EXT_IMAGE_BUFFER +#define _TEST_CL_EXT_IMAGE_BUFFER + +#define TEST_IMAGE_SIZE 20 + +#define GET_EXTENSION_FUNC(platform, function_name) \ + function_name##_fn function_name = reinterpret_cast<function_name##_fn>( \ + clGetExtensionFunctionAddressForPlatform(platform, #function_name)); \ + if (function_name == nullptr) \ + { \ + return TEST_FAIL; \ + } \ + do \ + { \ + } while (false) + +static inline size_t aligned_size(size_t size, size_t alignment) +{ + return (size + alignment - 1) & ~(alignment - 1); +} + +static inline void* aligned_ptr(void* ptr, size_t alignment) +{ + return (void*)(((uintptr_t)ptr + alignment - 1) & ~(alignment - 1)); +} + +static inline size_t get_format_size(cl_context context, + cl_image_format* format, + cl_mem_object_type imageType, + cl_mem_flags flags) +{ + cl_image_desc image_desc = { 0 }; + image_desc.image_type = imageType; + + /* Size 1 only to query element size */ + image_desc.image_width = 1; + if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType + && CL_MEM_OBJECT_IMAGE1D != imageType) + { + image_desc.image_height = 1; + } + if (CL_MEM_OBJECT_IMAGE3D == imageType + || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType) + { + image_desc.image_depth = 1; + } + if (CL_MEM_OBJECT_IMAGE1D_ARRAY == imageType + || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType) + { + image_desc.image_array_size = 1; + } + + cl_int error = 0; + cl_mem buffer; + if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER) + { + buffer = clCreateBuffer(context, flags, + get_pixel_size(format) * image_desc.image_width, + NULL, &error); + test_error(error, "Unable to create buffer"); + + image_desc.buffer = buffer; + } + + cl_mem image = + clCreateImage(context, flags, format, &image_desc, nullptr, &error); + test_error(error, "Unable to create image"); + + size_t element_size = 0; + error = clGetImageInfo(image, CL_IMAGE_ELEMENT_SIZE, sizeof(element_size), + &element_size, nullptr); + test_error(error, "Error clGetImageInfo"); + + error = clReleaseMemObject(image); + test_error(error, "Unable to release image"); + + if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER) + { + error = clReleaseMemObject(buffer); + test_error(error, "Unable to release buffer"); + } + + return element_size; +} + +static inline void image_desc_init(cl_image_desc* desc, + cl_mem_object_type imageType) +{ + desc->image_type = imageType; + desc->image_width = TEST_IMAGE_SIZE; + if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType + && CL_MEM_OBJECT_IMAGE1D != imageType) + { + desc->image_height = TEST_IMAGE_SIZE; + } + if (CL_MEM_OBJECT_IMAGE3D == imageType + || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType) + { + desc->image_depth = TEST_IMAGE_SIZE; + } + if (CL_MEM_OBJECT_IMAGE1D_ARRAY == imageType + || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType) + { + desc->image_array_size = TEST_IMAGE_SIZE; + } +} + +#endif /* _TEST_CL_EXT_IMAGE_BUFFER */
\ No newline at end of file diff --git a/test_conformance/images/kernel_read_write/test_cl_ext_image_from_buffer.cpp b/test_conformance/images/kernel_read_write/test_cl_ext_image_from_buffer.cpp new file mode 100644 index 00000000..1b3b04b7 --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_cl_ext_image_from_buffer.cpp @@ -0,0 +1,1007 @@ +// +// Copyright (c) 2022 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "../testBase.h" +#include "../common.h" +#include "test_cl_ext_image_buffer.hpp" + +static int 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) +{ + cl_platform_id platform = getPlatformFromDevice(device); + GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT); + + cl_int err = CL_SUCCESS; + if (nullptr != row_pitch_alignment) + { + err = clGetImageRequirementsInfoEXT( + context, nullptr, flags, image_format, image_desc, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(*row_pitch_alignment), row_pitch_alignment, nullptr); + test_error(err, "Error getting alignment"); + } + + if (nullptr != slice_pitch_alignment && CL_SUCCESS == err) + { + err = clGetImageRequirementsInfoEXT( + context, nullptr, flags, image_format, image_desc, + CL_IMAGE_REQUIREMENTS_SLICE_PITCH_ALIGNMENT_EXT, + sizeof(*slice_pitch_alignment), slice_pitch_alignment, nullptr); + test_error(err, "Error getting alignment"); + } + + if (nullptr != base_address_alignment && CL_SUCCESS == err) + { + err = clGetImageRequirementsInfoEXT( + context, nullptr, flags, image_format, image_desc, + CL_IMAGE_REQUIREMENTS_BASE_ADDRESS_ALIGNMENT_EXT, + sizeof(*base_address_alignment), base_address_alignment, nullptr); + test_error(err, "Error getting alignment"); + } + + return TEST_PASS; +} + +/** + * Consistency with alignment requirements as returned by + * cl_khr_image2d_from_buffer Check that the returned values for + * CL_DEVICE_IMAGE_PITCH_ALIGNMENT and CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT + * are correct. + */ +int image2d_from_buffer_positive(cl_device_id device, cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_khr_image2d_from_buffer")) + { + printf("Extension cl_khr_image2d_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + cl_uint row_pitch_alignment_2d = 0; + cl_int err = + clGetDeviceInfo(device, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, + sizeof(row_pitch_alignment_2d), + &row_pitch_alignment_2d, nullptr); + test_error(err, "Error clGetDeviceInfo"); + + cl_uint base_address_alignment_2d = 0; + err = + clGetDeviceInfo(device, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, + sizeof(base_address_alignment_2d), + &base_address_alignment_2d, nullptr); + test_error(err, "Error clGetDeviceInfo"); + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + size_t row_pitch_alignment = 0; + size_t base_address_alignment = 0; + + int get_error = get_image_requirement_alignment( + device, context, 0, &format, &image_desc, + &row_pitch_alignment, nullptr, &base_address_alignment); + if (TEST_PASS != get_error) + { + return get_error; + } + + const size_t element_size = + get_format_size(context, &format, imageType, flag); + + /* Alignements in pixels vs bytes */ + if (base_address_alignment + > base_address_alignment_2d * element_size) + { + test_fail("Unexpected base_address_alignment"); + } + + if (row_pitch_alignment > row_pitch_alignment_2d * element_size) + { + test_fail("Unexpected row_pitch_alignment"); + } + } + } + } + + return TEST_PASS; +} + +/** + * Test clGetMemObjectInfo + * Check that CL_MEM_ASSOCIATED_MEMOBJECT correctly returns the buffer that was + * used. + */ +int memInfo_image_from_buffer_positive(cl_device_id device, cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + size_t row_pitch_alignment = 0; + size_t slice_pitch_alignment = 0; + + int get_error = get_image_requirement_alignment( + device, context, 0, &format, &image_desc, + &row_pitch_alignment, &slice_pitch_alignment, nullptr); + if (TEST_PASS != get_error) + { + return get_error; + } + + const size_t element_size = + get_format_size(context, &format, imageType, flag); + + const size_t row_pitch = aligned_size( + TEST_IMAGE_SIZE * element_size, row_pitch_alignment); + const size_t slice_pitch = aligned_size( + row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment); + + const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE; + + cl_int err = CL_SUCCESS; + cl_mem buffer = + clCreateBuffer(context, flag, buffer_size, nullptr, &err); + test_error(err, "Unable to create buffer"); + + image_desc.buffer = buffer; + + cl_mem image_buffer = clCreateImage(context, flag, &format, + &image_desc, nullptr, &err); + test_error(err, "Unable to create image"); + + cl_mem returned_buffer; + err = clGetMemObjectInfo( + image_buffer, CL_MEM_ASSOCIATED_MEMOBJECT, + sizeof(returned_buffer), &returned_buffer, nullptr); + test_error(err, "Error clGetMemObjectInfo"); + + if (returned_buffer != buffer) + { + test_fail("Unexpected CL_MEM_ASSOCIATED_MEMOBJECT buffer"); + } + + err = clReleaseMemObject(buffer); + test_error(err, "Unable to release buffer"); + + err = clReleaseMemObject(image_buffer); + test_error(err, "Unable to release image"); + } + } + } + + return TEST_PASS; +} + +/** + * Test clGetImageInfo + * Check that the returned values for CL_IMAGE_ROW_PITCH and + * CL_IMAGE_SLICE_PITCH are correct. + */ +int imageInfo_image_from_buffer_positive(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + size_t row_pitch_alignment = 0; + size_t slice_pitch_alignment = 0; + + int get_error = get_image_requirement_alignment( + device, context, 0, &format, &image_desc, + &row_pitch_alignment, &slice_pitch_alignment, nullptr); + if (TEST_PASS != get_error) + { + return get_error; + } + + const size_t element_size = + get_format_size(context, &format, imageType, flag); + + const size_t row_pitch = aligned_size( + TEST_IMAGE_SIZE * element_size, row_pitch_alignment); + const size_t slice_pitch = aligned_size( + row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment); + + const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE; + + cl_int err = CL_SUCCESS; + cl_mem buffer = + clCreateBuffer(context, flag, buffer_size, nullptr, &err); + test_error(err, "Unable to create buffer"); + + image_desc.buffer = buffer; + + if (imageType == CL_MEM_OBJECT_IMAGE2D + || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + image_desc.image_row_pitch = row_pitch; + } + else if (imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + image_desc.image_row_pitch = row_pitch; + image_desc.image_slice_pitch = slice_pitch; + } + + cl_mem image_buffer = clCreateImage(context, flag, &format, + &image_desc, nullptr, &err); + test_error(err, "Unable to create image"); + + if (imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY + || imageType == CL_MEM_OBJECT_IMAGE2D + || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + size_t returned_row_pitch = 0; + err = clGetImageInfo(image_buffer, CL_IMAGE_ROW_PITCH, + sizeof(returned_row_pitch), + &returned_row_pitch, nullptr); + test_error(err, "Error clGetImageInfo"); + + if (returned_row_pitch != row_pitch) + { + test_fail( + "Unexpected row pitch " + "CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT"); + } + } + + if (imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + size_t returned_slice_pitch = 0; + err = clGetImageInfo(image_buffer, CL_IMAGE_SLICE_PITCH, + sizeof(returned_slice_pitch), + &returned_slice_pitch, nullptr); + test_error(err, "Error clGetImageInfo"); + + if (returned_slice_pitch != slice_pitch) + { + test_fail( + "Unexpected row pitch " + "CL_IMAGE_REQUIREMENTS_SLICE_PITCH_ALIGNMENT_EXT"); + } + } + + err = clReleaseMemObject(buffer); + test_error(err, "Unable to release buffer"); + + err = clReleaseMemObject(image_buffer); + test_error(err, "Unable to release image"); + } + } + } + + return TEST_PASS; +} + +/** + * Negative testing for clCreateImage and wrong alignment + * - Create an image from a buffer with invalid row pitch (not a multiple of + * required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is returned. + * - Create an image from a buffer with invalid slice pitch (not a multiple of + * required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is returned. + * - Create an image from a buffer with invalid base address alignment (not a + * multiple of required alignment) and check that CL_INVALID_IMAGE_DESCRIPTOR is + * returned + */ +int image_from_buffer_alignment_negative(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + size_t row_pitch_alignment = 0; + size_t slice_pitch_alignment = 0; + size_t base_address_alignment = 0; + + int get_error = get_image_requirement_alignment( + device, context, 0, &format, &image_desc, + &row_pitch_alignment, &slice_pitch_alignment, + &base_address_alignment); + if (TEST_PASS != get_error) + { + return get_error; + } + + const size_t element_size = + get_format_size(context, &format, imageType, flag); + + const size_t row_pitch = aligned_size( + TEST_IMAGE_SIZE * element_size, row_pitch_alignment); + const size_t slice_pitch = aligned_size( + row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment); + + const size_t buffer_size = (slice_pitch + 1) + * TEST_IMAGE_SIZE; /* For bigger row/slice pitch */ + + cl_int err = CL_SUCCESS; + cl_mem buffer = + clCreateBuffer(context, flag, buffer_size, nullptr, &err); + test_error(err, "Unable to create buffer"); + + /* Test Row pitch images */ + if (imageType == CL_MEM_OBJECT_IMAGE2D + || imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + image_desc.buffer = buffer; + image_desc.image_row_pitch = + row_pitch + 1; /* wrong row pitch */ + + clCreateImage(context, flag, &format, &image_desc, nullptr, + &err); + test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, + "Unexpected clCreateImage return"); + } + + /* Test Slice pitch images */ + if (imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + image_desc.buffer = buffer; + image_desc.image_row_pitch = row_pitch; + image_desc.image_slice_pitch = + slice_pitch + 1; /* wrong slice pitch */ + + clCreateImage(context, flag, &format, &image_desc, nullptr, + &err); + test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, + "Unexpected clCreateImage return"); + } + + /* Test buffer from host ptr to test base address alignment */ + const size_t aligned_buffer_size = + aligned_size(buffer_size, base_address_alignment); + /* Create buffer with host ptr and additional size for the wrong + * alignment */ + void* const host_ptr = + malloc(aligned_buffer_size + base_address_alignment); + void* non_aligned_host_ptr = + (void*)((char*)(aligned_ptr(host_ptr, + base_address_alignment)) + + 1); /* wrong alignment */ + + cl_mem buffer_host = clCreateBuffer( + context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, + buffer_size, non_aligned_host_ptr, &err); + test_error(err, "Unable to create buffer"); + + image_desc.buffer = buffer_host; + + clCreateImage(context, flag, &format, &image_desc, nullptr, + &err); + test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, + "Unexpected clCreateImage return"); + + free(host_ptr); + + err = clReleaseMemObject(buffer); + test_error(err, "Unable to release buffer"); + + err = clReleaseMemObject(buffer_host); + test_error(err, "Unable to release buffer"); + } + } + } + + return TEST_PASS; +} + +/** + * Negative testing for clCreateImage (buffer size). + * Create a buffer too small and check that image creation from that buffer is + * rejected + */ +int image_from_small_buffer_negative(cl_device_id device, cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE3D, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + /* Invalid buffer size */ + cl_int err; + cl_mem buffer = clCreateBuffer( + context, flag, TEST_IMAGE_SIZE / 2, nullptr, &err); + test_error(err, "Unable to create buffer"); + + image_desc.buffer = buffer; + + clCreateImage(context, flag, &format, &image_desc, nullptr, + &err); + test_failure_error(err, CL_INVALID_MEM_OBJECT, + "Unexpected clCreateImage return"); + + err = clReleaseMemObject(buffer); + test_error(err, "Unable to release buffer"); + } + } + } + + return TEST_PASS; +} + +static int image_from_buffer_fill_check(cl_command_queue queue, cl_mem image, + size_t* region, size_t element_size, + char pattern) +{ + /* read the image from buffer and check the pattern */ + const size_t image_size = region[0] * region[1] * region[2] * element_size; + size_t origin[3] = { 0, 0, 0 }; + std::vector<char> read_buffer(image_size); + + cl_int error = + clEnqueueReadImage(queue, image, CL_BLOCKING, origin, region, 0, 0, + read_buffer.data(), 0, nullptr, nullptr); + test_error(error, "Error clEnqueueReadImage"); + + for (size_t line = 0; line < region[0]; line++) + { + for (size_t row = 0; row < region[1]; row++) + { + for (size_t depth = 0; depth < region[2]; depth++) + { + for (size_t elmt = 0; elmt < element_size; elmt++) + { + size_t index = line * row * depth * elmt; + + if (read_buffer[index] != pattern) + { + test_fail("Image pattern check failed"); + } + } + } + } + } + + return TEST_PASS; +} + +/** + * Use fill buffer to fill the image from buffer + */ +int image_from_buffer_fill_positive(cl_device_id device, cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + size_t row_pitch_alignment = 0; + size_t slice_pitch_alignment = 0; + + int get_error = get_image_requirement_alignment( + device, context, 0, &format, &image_desc, + &row_pitch_alignment, &slice_pitch_alignment, nullptr); + if (TEST_PASS != get_error) + { + return get_error; + } + + const size_t element_size = + get_format_size(context, &format, imageType, flag); + + const size_t row_pitch = aligned_size( + TEST_IMAGE_SIZE * element_size, row_pitch_alignment); + const size_t slice_pitch = aligned_size( + row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment); + + const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE; + + cl_int err = CL_SUCCESS; + cl_mem buffer = + clCreateBuffer(context, flag, buffer_size, nullptr, &err); + test_error(err, "Unable to create buffer"); + + /* fill the buffer with a pattern */ + const char pattern = 0x55; + err = clEnqueueFillBuffer(queue, buffer, &pattern, + sizeof(pattern), 0, buffer_size, 0, + nullptr, nullptr); + test_error(err, "Error clEnqueueFillBuffer"); + + err = clFinish(queue); + test_error(err, "Error clFinish"); + + cl_mem image1d_buffer; + if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER) + { + image1d_buffer = clCreateBuffer(context, flag, buffer_size, + nullptr, &err); + test_error(err, "Unable to create buffer"); + + image_desc.buffer = image1d_buffer; + } + + cl_mem image = clCreateImage(context, flag, &format, + &image_desc, nullptr, &err); + test_error(err, "Unable to create image"); + + /* Check the image from buffer */ + image_desc.buffer = buffer; + + if (imageType == CL_MEM_OBJECT_IMAGE2D + || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + image_desc.image_row_pitch = row_pitch; + } + else if (imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + image_desc.image_row_pitch = row_pitch; + image_desc.image_slice_pitch = slice_pitch; + } + + cl_mem image_from_buffer = clCreateImage( + context, flag, &format, &image_desc, nullptr, &err); + test_error(err, "Unable to create image"); + + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { 1, 1, 1 }; + + region[0] = TEST_IMAGE_SIZE; + if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType + && CL_MEM_OBJECT_IMAGE1D != imageType) + { + region[1] = TEST_IMAGE_SIZE; + } + if (CL_MEM_OBJECT_IMAGE3D == imageType + || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType) + { + region[2] = TEST_IMAGE_SIZE; + } + + /* Check the copy of the image from buffer */ + err = + clEnqueueCopyImage(queue, image_from_buffer, image, origin, + origin, region, 0, nullptr, nullptr); + test_error(err, "Error clEnqueueCopyImage"); + + err = clFinish(queue); + test_error(err, "Error clFinish"); + + int fill_error = image_from_buffer_fill_check( + queue, image_from_buffer, region, element_size, pattern); + if (TEST_PASS != fill_error) + { + return fill_error; + } + + fill_error = image_from_buffer_fill_check( + queue, image, region, element_size, pattern); + if (TEST_PASS != fill_error) + { + return fill_error; + } + + err = clReleaseMemObject(buffer); + test_error(err, "Unable to release buffer"); + + err = clReleaseMemObject(image); + test_error(err, "Unable to release image"); + + err = clReleaseMemObject(image_from_buffer); + test_error(err, "Unable to release image"); + + if (imageType == CL_MEM_OBJECT_IMAGE1D_BUFFER) + { + err = clReleaseMemObject(image1d_buffer); + test_error(err, "Unable to release image"); + } + } + } + } + + return TEST_PASS; +} + +static int 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) +{ + /* read the buffer and check the pattern */ + std::vector<char> host_buffer(buffer_size); + char* host_ptr = host_buffer.data(); + char* host_ptr_slice = host_ptr; + + cl_int error = + clEnqueueReadBuffer(queue, buffer, CL_BLOCKING, 0, buffer_size, + host_buffer.data(), 0, nullptr, nullptr); + test_error(error, "Error clEnqueueReadBuffer"); + + for (size_t k = 0; k < region[2]; k++) + { + for (size_t i = 0; i < region[1]; i++) + { + for (size_t j = 0; j < region[0] * element_size; j++) + { + if (host_ptr[j] != pattern) + { + test_fail("Image pattern check failed"); + } + } + host_ptr = host_ptr + row_pitch; + } + host_ptr_slice = host_ptr_slice + slice_pitch; + host_ptr = host_ptr_slice; + } + + return TEST_PASS; +} + +/** + * Use fill image to fill the buffer that was used to create the image + */ +int image_from_buffer_read_positive(cl_device_id device, cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + for (auto imageType : imageTypes) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + /* Non normalized format so we can read it back directly from + * clEnqueueFillImage */ + cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT8 }; + const char pattern = 0x55; + + const size_t element_size = + get_format_size(context, &format, imageType, CL_MEM_READ_WRITE); + + size_t row_pitch_alignment = 0; + size_t slice_pitch_alignment = 0; + + int get_error = get_image_requirement_alignment( + device, context, CL_MEM_READ_WRITE, &format, &image_desc, + &row_pitch_alignment, &slice_pitch_alignment, nullptr); + if (TEST_PASS != get_error) + { + return get_error; + } + + const size_t row_pitch = + aligned_size(TEST_IMAGE_SIZE * element_size, row_pitch_alignment); + const size_t slice_pitch = + aligned_size(row_pitch * TEST_IMAGE_SIZE, slice_pitch_alignment); + + const size_t buffer_size = slice_pitch * TEST_IMAGE_SIZE; + + cl_int err = CL_SUCCESS; + cl_mem buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, buffer_size, + nullptr, &err); + test_error(err, "Unable to create buffer"); + + /* Check the image from buffer */ + image_desc.buffer = buffer; + + if (imageType == CL_MEM_OBJECT_IMAGE2D + || imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) + { + image_desc.image_row_pitch = row_pitch; + } + else if (imageType == CL_MEM_OBJECT_IMAGE3D + || imageType == CL_MEM_OBJECT_IMAGE2D_ARRAY) + { + image_desc.image_row_pitch = row_pitch; + image_desc.image_slice_pitch = slice_pitch; + } + + cl_mem image = clCreateImage(context, CL_MEM_READ_WRITE, &format, + &image_desc, nullptr, &err); + test_error(err, "Unable to create image"); + + size_t origin[3] = { 0, 0, 0 }; + size_t region[3] = { 1, 1, 1 }; + + region[0] = TEST_IMAGE_SIZE; + if (CL_MEM_OBJECT_IMAGE1D_BUFFER != imageType + && CL_MEM_OBJECT_IMAGE1D != imageType) + { + region[1] = TEST_IMAGE_SIZE; + } + if (CL_MEM_OBJECT_IMAGE3D == imageType + || CL_MEM_OBJECT_IMAGE2D_ARRAY == imageType) + { + region[2] = TEST_IMAGE_SIZE; + } + + /* fill the image with a pattern */ + cl_uint fill_color[4] = { pattern, pattern, pattern, pattern }; + err = clEnqueueFillImage(queue, image, fill_color, origin, region, 0, + nullptr, nullptr); + test_error(err, "Error clEnqueueFillImage"); + + err = clFinish(queue); + test_error(err, "Error clFinish"); + + int read_error = image_from_buffer_read_check( + queue, buffer, buffer_size, region, element_size, pattern, + (imageType == CL_MEM_OBJECT_IMAGE1D_ARRAY) ? slice_pitch + : row_pitch, + slice_pitch); + if (TEST_PASS != read_error) + { + return read_error; + } + + err = clReleaseMemObject(buffer); + test_error(err, "Unable to release buffer"); + + err = clReleaseMemObject(image); + test_error(err, "Unable to release image"); + } + + return TEST_PASS; +}
\ No newline at end of file diff --git a/test_conformance/images/kernel_read_write/test_cl_ext_image_requirements_info.cpp b/test_conformance/images/kernel_read_write/test_cl_ext_image_requirements_info.cpp new file mode 100644 index 00000000..9212fcbc --- /dev/null +++ b/test_conformance/images/kernel_read_write/test_cl_ext_image_requirements_info.cpp @@ -0,0 +1,482 @@ +// +// Copyright (c) 2022 The Khronos Group Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#include "../testBase.h" +#include "../common.h" +#include "test_cl_ext_image_buffer.hpp" + +/** + * Negative tests for {CL_IMAGE_REQUIREMENTS_SIZE_EXT} + * Check that attempting to perform the {CL_IMAGE_REQUIREMENTS_SIZE_EXT} query + * without specifying the _image_format_ results in {CL_INVALID_VALUE} being + * returned. Check that attempting to perform the + * {CL_IMAGE_REQUIREMENTS_SIZE_EXT} query without specifying the _image_desc_ + * results in {CL_INVALID_VALUE} being returned. + */ +int cl_image_requirements_size_ext_negative(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + cl_platform_id platform = getPlatformFromDevice(device); + GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT); + + size_t max_size = 0; + size_t param_val_size = 0; + + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, CL_MEM_OBJECT_IMAGE2D); + + cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT16 }; + + /* Check image_format null results in CL_INVALID_VALUE */ + cl_int err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, nullptr, &image_desc, + CL_IMAGE_REQUIREMENTS_SIZE_EXT, sizeof(max_size), &max_size, + ¶m_val_size); + test_failure_error(err, CL_INVALID_VALUE, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check image_desc null results in CL_INVALID_VALUE */ + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, nullptr, + CL_IMAGE_REQUIREMENTS_SIZE_EXT, sizeof(max_size), &max_size, + ¶m_val_size); + test_failure_error(err, CL_INVALID_VALUE, + "Unexpected clGetImageRequirementsInfoEXT return"); + + return TEST_PASS; +} + +/** + * Consistency checks for CL_IMAGE_REQUIREMENTS_SIZE_EXT + * When creating 2D images from a buffer is supported + * Check that the CL_IMAGE_REQUIREMENTS_SIZE_EXT query can be performed + * successfully. Create a buffer with the size returned and check that an image + * can successfully be created from the buffer. Check that the value returned + * for CL_MEM_SIZE for the image is the same as the value returned for + * CL_IMAGE_REQUIREMENTS_SIZE_EXT. + */ +int cl_image_requirements_size_ext_consistency(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + if (!is_extension_available(device, "cl_ext_image_from_buffer")) + { + printf("Extension cl_ext_image_from_buffer not available"); + return TEST_SKIPPED_ITSELF; + } + + cl_platform_id platform = getPlatformFromDevice(device); + GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT); + + size_t max_size = 0; + size_t param_val_size = 0; + + std::vector<cl_mem_object_type> imageTypes{ + CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY + }; + + std::vector<cl_mem_flags> flagTypes{ CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY, + CL_MEM_READ_WRITE, + CL_MEM_KERNEL_READ_AND_WRITE }; + + for (auto flag : flagTypes) + { + for (auto imageType : imageTypes) + { + /* Get the list of supported image formats */ + std::vector<cl_image_format> formatList; + if (TEST_PASS + != get_format_list(context, imageType, formatList, flag) + || formatList.size() == 0) + { + test_fail("Failure to get supported formats list"); + } + + for (auto format : formatList) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + flag = (flag == CL_MEM_KERNEL_READ_AND_WRITE) + ? CL_MEM_READ_WRITE + : flag; + + cl_int err = clGetImageRequirementsInfoEXT( + context, nullptr, flag, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_SIZE_EXT, sizeof(max_size), &max_size, + ¶m_val_size); + test_error(err, "Error clGetImageRequirementsInfoEXT"); + + /* Create buffer */ + cl_mem buffer = + clCreateBuffer(context, flag, max_size, nullptr, &err); + test_error(err, "Unable to create buffer"); + + image_desc.buffer = buffer; + + /* 2D Image from buffer */ + cl_mem image_buffer = clCreateImage(context, flag, &format, + &image_desc, nullptr, &err); + test_error(err, "Unable to create image"); + + size_t size = 0; + err = clGetMemObjectInfo(image_buffer, CL_MEM_SIZE, + sizeof(size_t), &size, NULL); + test_error(err, "Error clGetMemObjectInfo"); + + if (max_size != size) + { + test_fail("CL_IMAGE_REQUIREMENTS_SIZE_EXT different from " + "CL_MEM_SIZE"); + } + + err = clReleaseMemObject(image_buffer); + test_error(err, "Error clReleaseMemObject"); + + err = clReleaseMemObject(buffer); + test_error(err, "Error clReleaseMemObject"); + } + } + } + + return TEST_PASS; +} + +/** + * Negative testing for all testable error codes returned by + * clGetImageFormatInfoKHR + */ +int clGetImageRequirementsInfoEXT_negative(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + cl_platform_id platform = getPlatformFromDevice(device); + GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT); + + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, CL_MEM_OBJECT_IMAGE3D); + + cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT16 }; + + /* Check that CL_INVALID_CONTEXT is returned when passing nullptr as context + */ + size_t row_pitch_alignment = 0; + cl_int err = clGetImageRequirementsInfoEXT( + nullptr, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(row_pitch_alignment), &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_CONTEXT, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_VALUE is returned when passing an invalid + * image_type */ + cl_image_desc invalid_desc = { CL_MEM_OBJECT_BUFFER, TEST_IMAGE_SIZE }; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &invalid_desc, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(row_pitch_alignment), &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_IMAGE_DESCRIPTOR, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_VALUE is returned when passing invalid flags */ + err = clGetImageRequirementsInfoEXT( + context, nullptr, -1, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(row_pitch_alignment), &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_VALUE, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_IMAGE_FORMAT_DESCRIPTOR is returned when passing a + * nullptr image_format */ + cl_image_format invalid_format = { CL_INTENSITY, CL_UNORM_SHORT_555 }; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &invalid_format, &image_desc, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(row_pitch_alignment), &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_IMAGE_FORMAT_DESCRIPTOR, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_IMAGE_DESCRIPTOR is returned when passing an + * image_desc with invalid values */ + cl_image_desc invalid_desc_size = { CL_MEM_OBJECT_IMAGE1D, 0 }; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &invalid_desc_size, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(row_pitch_alignment), &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_IMAGE_DESCRIPTOR, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_VALUE is returned when passing an invalid + * param_name */ + cl_image_requirements_info_ext invalid_info = CL_IMAGE_FORMAT; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, invalid_info, + sizeof(row_pitch_alignment), &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_VALUE, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_VALUE is returned when passing a param_value_size + * value smaller than the size of the return type */ + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_ROW_PITCH_ALIGNMENT_EXT, + sizeof(row_pitch_alignment) - 1, &row_pitch_alignment, nullptr); + test_failure_error(err, CL_INVALID_VALUE, + "Unexpected clGetImageRequirementsInfoEXT return"); + + /* Check that CL_INVALID_VALUE is returned when passing a param_value_size + * value smaller than the size of the return type */ + uint32_t max_height = 0; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT, sizeof(max_height) - 1, + &max_height, nullptr); + test_failure_error(err, CL_INVALID_VALUE, + "Unexpected clGetImageRequirementsInfoEXT return"); + + return TEST_PASS; +} + +/** + * Negative tests for {CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT} + * Attempt to perform the {CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT} query on all + * image types for which it is not valid Check that + * {CL_INVALID_IMAGE_DESCRIPTOR} is returned in all cases. + * + * Negative testing for {CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT} + * Attempt to perform the {CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT} query on all + * image types for which it is not valid Check that + * {CL_INVALID_IMAGE_DESCRIPTOR} is returned in all cases. + * + * Negative testing for {CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT} + * Attempt to perform the {CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT} query on + * all image types for which it is not valid Check that + * {CL_INVALID_IMAGE_DESCRIPTOR} is returned in all cases. + */ +int cl_image_requirements_max_val_ext_negative(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + cl_platform_id platform = getPlatformFromDevice(device); + GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT); + + size_t value = 0; + + std::vector<cl_mem_object_type> imageTypes_height{ + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D + }; + + cl_image_format format = { CL_RGBA, CL_UNSIGNED_INT16 }; + + for (auto imageType : imageTypes_height) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + /* Check image_format null results in CL_INVALID_VALUE */ + cl_int err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT, sizeof(value), &value, + nullptr); + test_failure_error(err, CL_INVALID_IMAGE_DESCRIPTOR, + "Unexpected clGetImageRequirementsInfoEXT return"); + } + + std::vector<cl_mem_object_type> imageTypes_depth{ + CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE2D_ARRAY, + CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE1D_BUFFER, + CL_MEM_OBJECT_IMAGE1D + }; + + for (auto imageType : imageTypes_depth) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + /* Check image_format null results in CL_INVALID_VALUE */ + cl_int err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT, sizeof(value), &value, + nullptr); + test_failure_error(err, CL_INVALID_IMAGE_DESCRIPTOR, + "Unexpected clGetImageRequirementsInfoEXT return"); + } + + std::vector<cl_mem_object_type> imageTypes_array_size{ + CL_MEM_OBJECT_IMAGE3D, CL_MEM_OBJECT_IMAGE2D, + CL_MEM_OBJECT_IMAGE1D_BUFFER, CL_MEM_OBJECT_IMAGE1D + }; + + for (auto imageType : imageTypes_array_size) + { + cl_image_desc image_desc = { 0 }; + image_desc_init(&image_desc, imageType); + + /* Check image_format null results in CL_INVALID_VALUE */ + cl_int err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, &format, &image_desc, + CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT, sizeof(value), &value, + nullptr); + test_failure_error(err, CL_INVALID_IMAGE_DESCRIPTOR, + "Unexpected clGetImageRequirementsInfoEXT return"); + } + + return TEST_PASS; +} + +/** + * Consistency checks for {CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT} + ** Check that the {CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT} query can be performed + *successfully + * + * Consistency checks for {CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT} + ** Check that the {CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT} query can be performed + *successfully + * + * Consistency checks for {CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT} + ** Check that the {CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT} query can be performed + *successfully + * + * Consistency checks for {CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT} + ** Check that the {CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT} query can be + *performed successfully + */ +int cl_image_requirements_max_val_ext_positive(cl_device_id device, + cl_context context, + cl_command_queue queue) +{ + if (!is_extension_available(device, "cl_ext_image_requirements_info")) + { + printf("Extension cl_ext_image_requirements_info not available"); + return TEST_SKIPPED_ITSELF; + } + + cl_platform_id platform = getPlatformFromDevice(device); + GET_EXTENSION_FUNC(platform, clGetImageRequirementsInfoEXT); + + /* CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT */ + cl_image_desc image_desc_1d = { 0 }; + image_desc_init(&image_desc_1d, CL_MEM_OBJECT_IMAGE1D); + + uint32_t max_width = 0; + cl_int err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, nullptr, &image_desc_1d, + CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT, sizeof(max_width), &max_width, + nullptr); + test_error(err, "Error clGetImageRequirementsInfoEXT"); + + size_t width_1d = 0; + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, + sizeof(width_1d), &width_1d, NULL); + test_error(err, "Error clGetDeviceInfo"); + + if (!(max_width <= width_1d && max_width > 0)) + { + test_fail("Unexpected CL_IMAGE_REQUIREMENTS_MAX_WIDTH_EXT value"); + } + + /* CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT */ + cl_image_desc image_desc_2d = { 0 }; + image_desc_init(&image_desc_2d, CL_MEM_OBJECT_IMAGE2D); + + uint32_t max_height = 0; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, nullptr, &image_desc_2d, + CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT, sizeof(max_height), &max_height, + nullptr); + test_error(err, "Error clGetImageRequirementsInfoEXT"); + + size_t height_2d = 0; + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, + sizeof(height_2d), &height_2d, NULL); + test_error(err, "Error clGetDeviceInfo"); + + if (!(max_height <= height_2d && max_height > 0)) + { + test_fail("Unexpected CL_IMAGE_REQUIREMENTS_MAX_HEIGHT_EXT value"); + } + + /* CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT */ + cl_image_desc image_desc_3d = { 0 }; + image_desc_init(&image_desc_3d, CL_MEM_OBJECT_IMAGE3D); + + uint32_t max_depth = 0; + err = clGetImageRequirementsInfoEXT(context, nullptr, CL_MEM_READ_WRITE, + nullptr, &image_desc_3d, + CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT, + sizeof(max_depth), &max_depth, nullptr); + test_error(err, "Error clGetImageRequirementsInfoEXT"); + + size_t depth_3d = 0; + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(depth_3d), + &depth_3d, NULL); + test_error(err, "Error clGetDeviceInfo"); + + if (!(max_depth <= depth_3d && max_depth > 0)) + { + test_fail("Unexpected CL_IMAGE_REQUIREMENTS_MAX_DEPTH_EXT value"); + } + + /* CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT */ + cl_image_desc image_desc_array = { 0 }; + image_desc_init(&image_desc_array, CL_MEM_OBJECT_IMAGE2D_ARRAY); + + uint32_t max_array_size = 0; + err = clGetImageRequirementsInfoEXT( + context, nullptr, CL_MEM_READ_WRITE, nullptr, &image_desc_array, + CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT, sizeof(max_array_size), + &max_array_size, nullptr); + test_error(err, "Error clGetImageRequirementsInfoEXT"); + + size_t array_size = 0; + err = clGetDeviceInfo(device, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, + sizeof(array_size), &array_size, NULL); + test_error(err, "Error clGetDeviceInfo"); + + if (!(max_array_size <= array_size && max_array_size > 0)) + { + test_fail("Unexpected CL_IMAGE_REQUIREMENTS_MAX_ARRAY_SIZE_EXT value"); + } + + return TEST_PASS; +}
\ No newline at end of file |