Add tests for cl_ext_immutable_memory_objects (#2286)

This change provides partial test coverage for
KhronosGroup/OpenCL-Docs#1280

Adding CTS tests for:
1. clEnqueueMapBuffer, clEnqueueMapImage.
2. Command buffer negative tests.
3. clSetKernelArgs negative tests.

The bulk of the tests is to make sure that the CL driver does not allow
writing to a memory object that is created with `CL_MEM_IMMUTABLE_EXT`
flag when used with the above APIs.

---------

Signed-off-by: Michael Rizkalla <michael.rizkalla@arm.com>
This commit is contained in:
Michael Rizkalla
2025-06-17 18:19:11 +01:00
committed by GitHub
parent e622512301
commit 8701acfa90
7 changed files with 745 additions and 10 deletions

View File

@@ -0,0 +1,36 @@
//
// Copyright (c) 2024 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.
#pragma once
#include "basic_command_buffer.h"
#include <type_traits>
template <class TBase>
struct CommandBufferWithImmutableMemoryObjectsTest : public TBase
{
using TBase::TBase;
static_assert(std::is_base_of<BasicCommandBufferTest, TBase>::value,
"TBase must be BasicCommandBufferTest or a derived class");
bool Skip() override
{
bool is_immutable_memory_objects_supported = is_extension_available(
BasicCommandBufferTest::device, "cl_ext_immutable_memory_objects");
return !is_immutable_memory_objects_supported || TBase::Skip();
}
};

View File

@@ -14,6 +14,9 @@
// limitations under the License.
//
#include "basic_command_buffer.h"
#include "command_buffer_with_immutable_memory.h"
#include "imageHelpers.h"
#include <vector>
//--------------------------------------------------------------------------
template <bool check_image_support>
@@ -577,6 +580,252 @@ struct CommandBufferCopyImageMutableHandleNotNull
return CL_SUCCESS;
}
};
struct CommandBufferCopyToImmutableImage
: public CommandBufferWithImmutableMemoryObjectsTest<
CommandBufferCopyBaseTest<true>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandFillImageKHR(
command_buffer, nullptr, nullptr, src_image, fill_color_1, origin,
region, 0, nullptr, nullptr, nullptr);
test_error(error, "clCommandFillImageKHR failed");
error = clCommandCopyImageKHR(command_buffer, nullptr, nullptr,
src_image, dst_image, origin, origin,
region, 0, 0, nullptr, nullptr);
test_failure_error_ret(error, CL_INVALID_OPERATION,
"clCommandCopyImageKHR is supposed to fail "
"with CL_INVALID_OPERATION when dst_image is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
src_image = create_image_2d(context, CL_MEM_READ_ONLY, &format,
img_width, img_height, 0, nullptr, &error);
test_error(error, "create_image_2d failed");
size_t pixel_size = get_pixel_size(&format);
size_t image_size =
pixel_size * sizeof(cl_uchar) * img_width * img_height;
std::vector<cl_uchar> imgptr(image_size);
dst_image = create_image_2d(
context, CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR, &format,
img_width, img_height, 0, imgptr.data(), &error);
test_error(error, "create_image_2d failed");
return CL_SUCCESS;
}
clMemWrapper dst_image;
clMemWrapper src_image;
static constexpr cl_uint pattern_1 = 0x05;
const cl_uint fill_color_1[4] = { pattern_1, pattern_1, pattern_1,
pattern_1 };
};
struct CommandBufferCopyToImmutableBuffer
: public CommandBufferWithImmutableMemoryObjectsTest<
CommandBufferCopyBaseTest<false>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandCopyBufferKHR(command_buffer, nullptr, nullptr,
in_mem, buffer, 0, 0, data_size,
0, nullptr, nullptr, nullptr);
test_failure_error_ret(error, CL_INVALID_OPERATION,
"clCommandCopyBufferKHR is supposed to fail "
"with CL_INVALID_OPERATION when dst_buffer is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
in_mem = clCreateBuffer(context, CL_MEM_READ_ONLY, data_size, nullptr,
&error);
test_error(error, "clCreateBuffer failed");
std::vector<cl_uchar> data(data_size);
buffer =
clCreateBuffer(context, CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR,
data_size, data.data(), &error);
test_error(error, "clCreateBuffer failed");
return CL_SUCCESS;
}
};
struct CommandBufferCopyBufferToImmutableImage
: public CommandBufferWithImmutableMemoryObjectsTest<
CommandBufferCopyBaseTest<true>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandFillBufferKHR(
command_buffer, nullptr, nullptr, buffer, &pattern_1,
sizeof(pattern_1), 0, data_size, 0, nullptr, nullptr, nullptr);
test_error(error, "clCommandFillBufferKHR failed");
error = clCommandCopyBufferToImageKHR(command_buffer, nullptr, nullptr,
buffer, image, 0, origin, region,
0, 0, nullptr, nullptr);
test_failure_error_ret(
error, CL_INVALID_OPERATION,
"clCommandCopyBufferToImageKHR is supposed to fail "
"with CL_INVALID_OPERATION when dst_image is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, data_size, nullptr,
&error);
test_error(error, "Unable to create buffer");
size_t pixel_size = get_pixel_size(&format);
size_t image_size =
pixel_size * sizeof(cl_uchar) * img_width * img_height;
std::vector<cl_uchar> imgptr(image_size);
image = create_image_2d(
context, CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR, &format,
img_width, img_height, 0, imgptr.data(), &error);
test_error(error, "create_image_2d failed");
return CL_SUCCESS;
}
const uint8_t pattern_1 = 0x05;
};
struct CommandBufferCopyImageToImmutableBuffer
: public CommandBufferWithImmutableMemoryObjectsTest<
CommandBufferCopyBaseTest<true>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandFillImageKHR(
command_buffer, nullptr, nullptr, image, fill_color_1, origin,
region, 0, nullptr, nullptr, nullptr);
test_error(error, "clCommandFillImageKHR failed");
error = clCommandCopyImageToBufferKHR(command_buffer, nullptr, nullptr,
image, buffer, origin, region, 0,
0, nullptr, nullptr, nullptr);
test_failure_error_ret(
error, CL_INVALID_OPERATION,
"clCommandCopyImageToBufferKHR is supposed to fail "
"with CL_INVALID_OPERATION when dst_buffer is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
image = create_image_2d(context, CL_MEM_READ_WRITE, &format, img_width,
img_height, 0, NULL, &error);
test_error(error, "create_image_2d failed");
std::vector<cl_uchar> data(data_size);
buffer =
clCreateBuffer(context, CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR,
data_size, data.data(), &error);
test_error(error, "Unable to create buffer");
return CL_SUCCESS;
}
static constexpr cl_uint pattern_1 = 0x12;
const cl_uint fill_color_1[4] = { pattern_1, pattern_1, pattern_1,
pattern_1 };
};
struct CommandBufferCopyToImmutableBufferRect
: public CommandBufferWithImmutableMemoryObjectsTest<
CommandBufferCopyBaseTest<false>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandCopyBufferRectKHR(
command_buffer, nullptr, nullptr, in_mem, buffer, origin, origin,
region, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr);
test_failure_error_ret(error, CL_INVALID_OPERATION,
"clCommandCopyBufferRectKHR is supposed to fail "
"with CL_INVALID_OPERATION when dst_buffer is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
in_mem = clCreateBuffer(context, CL_MEM_READ_ONLY, data_size, nullptr,
&error);
test_error(error, "clCreateBuffer failed");
std::vector<cl_uchar> data(data_size);
buffer =
clCreateBuffer(context, CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR,
data_size, data.data(), &error);
test_error(error, "clCreateBuffer failed");
return CL_SUCCESS;
}
};
}
REGISTER_TEST(negative_command_buffer_command_copy_buffer_queue_not_null)
@@ -657,3 +906,33 @@ REGISTER_TEST(
return MakeAndRunTest<CommandBufferCopyImageMutableHandleNotNull>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_copy_to_immutable_buffer)
{
return MakeAndRunTest<CommandBufferCopyToImmutableBuffer>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_copy_to_immutable_buffer_rect)
{
return MakeAndRunTest<CommandBufferCopyToImmutableBufferRect>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_copy_image_to_immutable_buffer)
{
return MakeAndRunTest<CommandBufferCopyImageToImmutableBuffer>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_copy_to_immutable_image)
{
return MakeAndRunTest<CommandBufferCopyToImmutableImage>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_copy_buffer_to_immutable_image)
{
return MakeAndRunTest<CommandBufferCopyBufferToImmutableImage>(
device, context, queue, num_elements);
}

View File

@@ -14,6 +14,8 @@
// limitations under the License.
//
#include "basic_command_buffer.h"
#include "command_buffer_with_immutable_memory.h"
#include "imageHelpers.h"
#include <vector>
//--------------------------------------------------------------------------
@@ -456,6 +458,89 @@ struct CommandBufferCommandFillImageMutableHandleNotNull
}
};
// CL_INVALID_OPERATION if destination buffer is immutable memory
struct CommandBufferCommandFillImmutableBuffer
: CommandBufferWithImmutableMemoryObjectsTest<CommandFillBaseTest<false>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandFillBufferKHR(
command_buffer, nullptr, nullptr, buffer, &pattern_1,
sizeof(pattern_1), 0, buffer_size, 0, nullptr, nullptr, nullptr);
test_failure_error_ret(error, CL_INVALID_OPERATION,
"clCommandFillBufferKHR is supposed to fail "
"with CL_INVALID_OPERATION when buffer is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
std::vector<cl_uchar> data(buffer_size);
buffer =
clCreateBuffer(context, CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR,
buffer_size, data.data(), &error);
test_error(error, "clCreateBuffer failed");
return CL_SUCCESS;
}
clMemWrapper buffer;
const size_t buffer_size = 512;
const uint8_t pattern_1 = 0x0f;
};
struct CommandBufferCommandFillImmutableImage
: CommandBufferWithImmutableMemoryObjectsTest<CommandFillBaseTest<true>>
{
using CommandBufferWithImmutableMemoryObjectsTest::
CommandBufferWithImmutableMemoryObjectsTest;
cl_int Run() override
{
cl_int error = clCommandFillImageKHR(
command_buffer, nullptr, nullptr, image, fill_color_1, origin,
region, 0, nullptr, nullptr, nullptr);
test_failure_error_ret(error, CL_INVALID_OPERATION,
"clCommandFillImageKHR is supposed to fail "
"with CL_INVALID_OPERATION when image is "
"created with CL_MEM_IMMUTABLE_EXT",
TEST_FAIL);
return CL_SUCCESS;
}
cl_int SetUp(int elements) override
{
cl_int error = BasicCommandBufferTest::SetUp(elements);
test_error(error, "BasicCommandBufferTest::SetUp failed");
size_t pixel_size = get_pixel_size(&formats);
size_t image_size = pixel_size * sizeof(cl_uchar) * 512 * 512;
std::vector<cl_uchar> imgptr(image_size);
image = create_image_2d(context,
CL_MEM_IMMUTABLE_EXT | CL_MEM_COPY_HOST_PTR,
&formats, 512, 512, 0, imgptr.data(), &error);
test_error(error, "create_image_2d failed");
return CL_SUCCESS;
}
clMemWrapper image;
};
}
REGISTER_TEST(negative_command_buffer_command_fill_buffer_queue_not_null)
@@ -537,3 +622,15 @@ REGISTER_TEST(
return MakeAndRunTest<CommandBufferCommandFillImageMutableHandleNotNull>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_fill_immutable_image)
{
return MakeAndRunTest<CommandBufferCommandFillImmutableImage>(
device, context, queue, num_elements);
}
REGISTER_TEST(negative_fill_immutable_buffer)
{
return MakeAndRunTest<CommandBufferCommandFillImmutableBuffer>(
device, context, queue, num_elements);
}