1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/helpers/aligned_memory.h"
9 #include "shared/test/common/test_macros/test.h"
10 
11 #include "opencl/source/helpers/cl_memory_properties_helpers.h"
12 #include "opencl/source/mem_obj/buffer.h"
13 #include "opencl/source/mem_obj/image.h"
14 #include "opencl/test/unit_test/fixtures/cl_device_fixture.h"
15 #include "opencl/test/unit_test/mocks/mock_context.h"
16 
17 #include <memory>
18 using namespace NEO;
19 
20 // Tests for cl_khr_image2d_from_buffer
21 class ImageFromSubBufferTest : public ClDeviceFixture, public ::testing::Test {
22   public:
ImageFromSubBufferTest()23     ImageFromSubBufferTest() {}
24 
25   protected:
SetUp()26     void SetUp() override {
27         imageFormat.image_channel_data_type = CL_UNORM_INT8;
28         imageFormat.image_channel_order = CL_RGBA;
29 
30         imageDesc.image_array_size = 0;
31         imageDesc.image_depth = 0;
32         imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D;
33         imageDesc.image_height = 128 / 2;
34         imageDesc.image_width = 256 / 2;
35         imageDesc.num_mip_levels = 0;
36         imageDesc.image_row_pitch = 0;
37         imageDesc.image_slice_pitch = 0;
38         imageDesc.num_samples = 0;
39 
40         size = 128 * 256 * 4;
41         hostPtr = alignedMalloc(size, 16);
42         ASSERT_NE(nullptr, hostPtr);
43 
44         parentBuffer = clCreateBuffer(&context, CL_MEM_USE_HOST_PTR | CL_MEM_READ_WRITE, size, hostPtr, &retVal);
45         ASSERT_EQ(CL_SUCCESS, retVal);
46 
47         const cl_buffer_region region = {size / 2, size / 2};
48 
49         subBuffer = clCreateSubBuffer(parentBuffer, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION,
50                                       reinterpret_cast<const void *>(&region), &retVal);
51         ASSERT_EQ(CL_SUCCESS, retVal);
52 
53         imageDesc.mem_object = subBuffer;
54         ASSERT_NE(nullptr, imageDesc.mem_object);
55     }
TearDown()56     void TearDown() override {
57         clReleaseMemObject(subBuffer);
58         clReleaseMemObject(parentBuffer);
59         alignedFree(hostPtr);
60     }
61 
createImage()62     Image *createImage() {
63         cl_mem_flags flags = CL_MEM_READ_ONLY;
64         auto surfaceFormat = Image::getSurfaceFormatFromTable(
65             flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features);
66         return Image::create(&context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()),
67                              flags, 0, surfaceFormat, &imageDesc, NULL, retVal);
68     }
69     cl_image_format imageFormat;
70     cl_image_desc imageDesc;
71     cl_int retVal = CL_SUCCESS;
72     MockContext context;
73     void *hostPtr;
74     size_t size;
75     cl_mem parentBuffer;
76     cl_mem subBuffer;
77 };
78 
TEST_F(ImageFromSubBufferTest,GivenSubBufferWithOffsetWhenCreatingImageThenOffsetsAreCorrect)79 TEST_F(ImageFromSubBufferTest, GivenSubBufferWithOffsetWhenCreatingImageThenOffsetsAreCorrect) {
80     std::unique_ptr<Image> imageFromSubBuffer(createImage());
81     EXPECT_NE(nullptr, imageFromSubBuffer);
82 
83     SurfaceOffsets surfaceOffsets = {0};
84     imageFromSubBuffer->getSurfaceOffsets(surfaceOffsets);
85 
86     uint32_t offsetExpected = static_cast<uint32_t>(size) / 2;
87 
88     EXPECT_EQ(offsetExpected, surfaceOffsets.offset);
89     EXPECT_EQ(0u, surfaceOffsets.xOffset);
90     EXPECT_EQ(0u, surfaceOffsets.yOffset);
91     EXPECT_EQ(0u, surfaceOffsets.yOffsetForUVplane);
92 }
93 
TEST_F(ImageFromSubBufferTest,GivenSubBufferWithOffsetGreaterThan4gbWhenCreatingImageThenSurfaceOffsetsAreCorrect)94 TEST_F(ImageFromSubBufferTest, GivenSubBufferWithOffsetGreaterThan4gbWhenCreatingImageThenSurfaceOffsetsAreCorrect) {
95     Buffer *buffer = castToObject<Buffer>(parentBuffer);
96     uint64_t offsetExpected = 0;
97     cl_buffer_region region = {0, size / 2};
98 
99     if constexpr (is64bit) {
100         offsetExpected = 8 * GB;
101         region = {static_cast<size_t>(offsetExpected), size / 2};
102     }
103 
104     Buffer *subBufferWithBigOffset = buffer->createSubBuffer(CL_MEM_READ_WRITE, 0, &region, retVal);
105     imageDesc.mem_object = subBufferWithBigOffset;
106 
107     std::unique_ptr<Image> imageFromSubBuffer(createImage());
108     EXPECT_NE(nullptr, imageFromSubBuffer);
109 
110     SurfaceOffsets surfaceOffsets = {0};
111     imageFromSubBuffer->getSurfaceOffsets(surfaceOffsets);
112 
113     EXPECT_EQ(offsetExpected, surfaceOffsets.offset);
114     EXPECT_EQ(0u, surfaceOffsets.xOffset);
115     EXPECT_EQ(0u, surfaceOffsets.yOffset);
116     EXPECT_EQ(0u, surfaceOffsets.yOffsetForUVplane);
117     subBufferWithBigOffset->release();
118 }
119