Skip to content

Commit

Permalink
[UR][CTS] Add tests for urEnqueueMemImageCopy
Browse files Browse the repository at this point in the history
Also remove image map and fill test files as they no longer exist in the API
  • Loading branch information
callumfare committed Jul 4, 2023
1 parent 7e5059c commit 558a2e5
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 10 deletions.
2 changes: 0 additions & 2 deletions test/conformance/enqueue/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ add_conformance_test_with_kernels_environment(enqueue
urEnqueueMemBufferWrite.cpp
urEnqueueMemBufferWriteRect.cpp
urEnqueueMemImageCopy.cpp
urEnqueueMemImageFill.cpp
urEnqueueMemImageMap.cpp
urEnqueueMemImageRead.cpp
urEnqueueMemImageWrite.cpp
urEnqueueMemUnmap.cpp
Expand Down
243 changes: 243 additions & 0 deletions test/conformance/enqueue/urEnqueueMemImageCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,246 @@
// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
// See LICENSE.TXT
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <uur/fixtures.h>

struct urEnqueueMemImageCopyTest
: public uur::urQueueTestWithParam<ur_mem_type_t> {
// Helper type so element offset calculations work the same as pixel offsets
struct rgba_pixel {
uint32_t data[4];
};
void SetUp() override {
UUR_RETURN_ON_FATAL_FAILURE(urQueueTestWithParam::SetUp());
type = getParam();
size = (type == UR_MEM_TYPE_IMAGE1D) ? ur_rect_region_t{width, 1, 1}
: (type == UR_MEM_TYPE_IMAGE2D)
? ur_rect_region_t{width, height, 1}
: ur_rect_region_t{width, height, depth};
buffSize = size.width * size.height * size.depth;
// Create a region that is half the size on each dimension so we can
// test partial copies of images
partialRegion = {
size.width / 2,
size.height > 1 ? size.height / 2 : 1,
size.depth > 1 ? size.depth / 2 : 1,
};
// Create an offset that is the centre of the image on each dimension.
// Used with the above region to test partial copies to non-zero offsets
partialRegionOffset = {
size.width / 2,
size.height > 1 ? size.height / 2 : 0,
size.depth > 1 ? size.depth / 2 : 0,
};

ur_image_desc_t desc = {UR_STRUCTURE_TYPE_IMAGE_DESC, // stype
nullptr, // pNext
type, // mem object type
size.width, // image width
size.height, // image height
size.depth, // image depth
1, // array size
0, // row pitch
0, // slice pitch
0, // mip levels
0}; // num samples
ASSERT_SUCCESS(urMemImageCreate(this->context, UR_MEM_FLAG_READ_WRITE,
&format, &desc, nullptr, &srcImage));
ASSERT_SUCCESS(urMemImageCreate(this->context, UR_MEM_FLAG_READ_WRITE,
&format, &desc, nullptr, &dstImage));
input.assign(buffSize, inputFill);
ASSERT_SUCCESS(urEnqueueMemImageWrite(queue, srcImage, true, origin,
size, 0, 0, input.data(), 0,
nullptr, nullptr));
// Fill the dst image with arbitrary data that is different to the
// input image so we can test partial copies
std::vector<rgba_pixel> dstData(buffSize, outputFill);
ASSERT_SUCCESS(urEnqueueMemImageWrite(queue, dstImage, true, origin,
size, 0, 0, dstData.data(), 0,
nullptr, nullptr));
}

void TearDown() override {
if (srcImage) {
EXPECT_SUCCESS(urMemRelease(dstImage));
}
if (dstImage) {
EXPECT_SUCCESS(urMemRelease(dstImage));
}
UUR_RETURN_ON_FATAL_FAILURE(urQueueTestWithParam::TearDown());
}

const size_t width = 32;
const size_t height = 8;
const size_t depth = 4;
const ur_rect_offset_t origin{0, 0, 0};
const ur_image_format_t format = {UR_IMAGE_CHANNEL_ORDER_RGBA,
UR_IMAGE_CHANNEL_TYPE_FLOAT};
const rgba_pixel inputFill = {42, 42, 42, 42};
const rgba_pixel outputFill = {21, 21, 21, 21};

ur_mem_type_t type;
ur_rect_region_t size;
ur_rect_region_t partialRegion;
ur_rect_offset_t partialRegionOffset;
size_t buffSize;
ur_mem_handle_t srcImage = nullptr;
ur_mem_handle_t dstImage = nullptr;
std::vector<rgba_pixel> input;
};

bool operator==(urEnqueueMemImageCopyTest::rgba_pixel lhs,
urEnqueueMemImageCopyTest::rgba_pixel rhs) {
return lhs.data[0] == rhs.data[0] && lhs.data[1] == rhs.data[1] &&
lhs.data[2] == rhs.data[2] && lhs.data[3] == rhs.data[3];
}

template <typename T>
inline std::string printImageCopyTestString(
const testing::TestParamInfo<typename T::ParamType> &info) {
// ParamType will be std::tuple<ur_device_handle_t, ur_mem_type_t>
const auto device_handle = std::get<0>(info.param);
const auto platform_device_name =
uur::GetPlatformAndDeviceName(device_handle);
const auto image_type = std::get<1>(info.param);
auto test_name = (image_type == UR_MEM_TYPE_IMAGE1D) ? "1D"
: (image_type == UR_MEM_TYPE_IMAGE2D) ? "2D"
: "3D";
return platform_device_name + "__" + test_name;
}

UUR_TEST_SUITE_P(urEnqueueMemImageCopyTest,
testing::ValuesIn({UR_MEM_TYPE_IMAGE1D, UR_MEM_TYPE_IMAGE2D,
UR_MEM_TYPE_IMAGE3D}),
printImageCopyTestString<urEnqueueMemImageCopyTest>);

TEST_P(urEnqueueMemImageCopyTest, Success) {
ASSERT_SUCCESS(urEnqueueMemImageCopy(queue, srcImage, dstImage, {0, 0, 0},
{0, 0, 0}, size, 0, nullptr, nullptr));
std::vector<rgba_pixel> output(buffSize, {1, 1, 1, 1});
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, dstImage, true, origin, size, 0,
0, output.data(), 0, nullptr,
nullptr));
ASSERT_EQ(input, output);
}

TEST_P(urEnqueueMemImageCopyTest, SuccessPartialCopy) {
ASSERT_SUCCESS(urEnqueueMemImageCopy(queue, srcImage, dstImage, {0, 0, 0},
{0, 0, 0}, partialRegion, 0, nullptr,
nullptr));
std::vector<rgba_pixel> output(buffSize, {0, 0, 0, 0});
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, dstImage, true, origin, size, 0,
0, output.data(), 0, nullptr,
nullptr));

// Perform equivalent copy of the region on the host
std::vector<rgba_pixel> expectedOutput(buffSize, outputFill);
for (size_t z = 0; z < partialRegion.depth; z++) {
for (size_t y = 0; y < partialRegion.height; y++) {
for (size_t x = 0; x < partialRegion.width; x++) {
size_t index =
(z * (size.width * size.height)) + (y * size.width) + x;
expectedOutput.data()[index] = input.data()[index];
}
}
}

ASSERT_EQ(expectedOutput, output);
}

TEST_P(urEnqueueMemImageCopyTest, SuccessPartialCopyWithSrcOffset) {
ASSERT_SUCCESS(urEnqueueMemImageCopy(queue, srcImage, dstImage,
partialRegionOffset, {0, 0, 0},
partialRegion, 0, nullptr, nullptr));
std::vector<rgba_pixel> output(buffSize, {0, 0, 0, 0});
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, dstImage, true, origin, size, 0,
0, output.data(), 0, nullptr,
nullptr));

// Perform equivalent copy of the region on the host
std::vector<rgba_pixel> expectedOutput(buffSize, outputFill);
for (size_t z = 0; z < partialRegion.depth; z++) {
for (size_t y = 0; y < partialRegion.height; y++) {
for (size_t x = 0; x < partialRegion.width; x++) {
size_t index =
(z * (size.width * size.height)) + (y * size.width) + x;
expectedOutput.data()[index] = input.data()[index];
}
}
}

ASSERT_EQ(expectedOutput, output);
}

TEST_P(urEnqueueMemImageCopyTest, SuccessPartialCopyWithDstOffset) {
ASSERT_SUCCESS(urEnqueueMemImageCopy(queue, srcImage, dstImage, {0, 0, 0},
partialRegionOffset, partialRegion, 0,
nullptr, nullptr));
std::vector<rgba_pixel> output(buffSize, {0, 0, 0, 0});
ASSERT_SUCCESS(urEnqueueMemImageRead(queue, dstImage, true, origin, size, 0,
0, output.data(), 0, nullptr,
nullptr));

// Perform equivalent copy of the region on the host
std::vector<rgba_pixel> expectedOutput(buffSize, outputFill);
for (size_t z = partialRegionOffset.z;
z < partialRegionOffset.z + partialRegion.depth; z++) {
for (size_t y = partialRegionOffset.y;
y < partialRegionOffset.y + partialRegion.height; y++) {
for (size_t x = partialRegionOffset.x;
x < partialRegionOffset.x + partialRegion.width; x++) {
size_t index =
(z * (size.width * size.height)) + (y * size.width) + x;
expectedOutput.data()[index] = input.data()[index];
}
}
}

ASSERT_EQ(expectedOutput, output);
}

TEST_P(urEnqueueMemImageCopyTest, InvalidNullHandleQueue) {
ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_HANDLE,
urEnqueueMemImageCopy(nullptr, srcImage, dstImage,
{0, 0, 0}, {0, 0, 0}, size, 0,
nullptr, nullptr));
}

TEST_P(urEnqueueMemImageCopyTest, InvalidNullHandleImageSrc) {
ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_HANDLE,
urEnqueueMemImageCopy(queue, nullptr, dstImage, {0, 0, 0},
{0, 0, 0}, size, 0, nullptr,
nullptr));
}

TEST_P(urEnqueueMemImageCopyTest, InvalidNullHandleImageDst) {
ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_HANDLE,
urEnqueueMemImageCopy(queue, srcImage, nullptr, {0, 0, 0},
{0, 0, 0}, size, 0, nullptr,
nullptr));
}

TEST_P(urEnqueueMemImageCopyTest, InvalidNullPtrEventWaitList) {
ASSERT_EQ_RESULT(urEnqueueMemImageCopy(queue, srcImage, dstImage, {0, 0, 0},
{0, 0, 0}, size, 1, nullptr,
nullptr),
UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST);

ur_event_handle_t validEvent;
ASSERT_SUCCESS(urEnqueueEventsWait(queue, 0, nullptr, &validEvent));

ASSERT_EQ_RESULT(urEnqueueMemImageCopy(queue, srcImage, dstImage, {0, 0, 0},
{0, 0, 0}, size, 0, &validEvent,
nullptr),
UR_RESULT_ERROR_INVALID_EVENT_WAIT_LIST);
}

TEST_P(urEnqueueMemImageCopyTest, InvalidSize) {
ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_SIZE,
urEnqueueMemImageCopy(queue, srcImage, dstImage, {1, 0, 0},
{0, 0, 0}, size, 0, nullptr,
nullptr));
ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_SIZE,
urEnqueueMemImageCopy(queue, srcImage, dstImage, {0, 0, 0},
{1, 0, 0}, size, 0, nullptr,
nullptr));
}
4 changes: 0 additions & 4 deletions test/conformance/enqueue/urEnqueueMemImageFill.cpp

This file was deleted.

4 changes: 0 additions & 4 deletions test/conformance/enqueue/urEnqueueMemImageMap.cpp

This file was deleted.

0 comments on commit 558a2e5

Please sign in to comment.