aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Petit <kevin.petit@arm.com>2022-09-13 17:58:24 +0100
committerGitHub <noreply@github.com>2022-09-13 09:58:24 -0700
commitc0a10f4e12c1a4866a37449c5697a2f4c5e82e25 (patch)
treea4aa67363b62f5df7fd829c1262b58eda0dd9a69
parent426097cf7c2e0e4b6c659bd0b744e6f51e61805d (diff)
downloadOpenCL-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>
-rw-r--r--test_conformance/images/kernel_read_write/CMakeLists.txt2
-rw-r--r--test_conformance/images/kernel_read_write/main.cpp143
-rw-r--r--test_conformance/images/kernel_read_write/test_cl_ext_image_buffer.hpp124
-rw-r--r--test_conformance/images/kernel_read_write/test_cl_ext_image_from_buffer.cpp1007
-rw-r--r--test_conformance/images/kernel_read_write/test_cl_ext_image_requirements_info.cpp482
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,
+ &param_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,
+ &param_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,
+ &param_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