/* * Copyright (C) 2018-2023 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/built_ins/built_ins.h" #include "shared/source/compiler_interface/compiler_cache.h" #include "shared/source/compiler_interface/compiler_interface.h" #include "shared/source/helpers/aligned_memory.h" #include "shared/source/image/image_surface_state.h" #include "shared/source/os_interface/os_context.h" #include "shared/test/common/fixtures/memory_management_fixture.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/kernel_binary_helper.h" #include "shared/test/common/helpers/unit_test_helper.h" #include "shared/test/common/mocks/mock_allocation_properties.h" #include "shared/test/common/mocks/mock_gmm.h" #include "shared/test/common/mocks/mock_memory_manager.h" #include "shared/test/common/test_macros/test.h" #include "shared/test/common/test_macros/test_checks_shared.h" #include "opencl/source/helpers/mipmap.h" #include "opencl/source/mem_obj/buffer.h" #include "opencl/source/mem_obj/image.h" #include "opencl/source/mem_obj/mem_obj_helper.h" #include "opencl/test/unit_test/command_queue/command_queue_fixture.h" #include "opencl/test/unit_test/fixtures/cl_device_fixture.h" #include "opencl/test/unit_test/fixtures/image_fixture.h" #include "opencl/test/unit_test/fixtures/multi_root_device_fixture.h" #include "opencl/test/unit_test/mem_obj/image_compression_fixture.h" #include "opencl/test/unit_test/mocks/mock_context.h" #include "opencl/test/unit_test/mocks/mock_platform.h" using namespace NEO; static const unsigned int testImageDimensions = 45; auto channelType = CL_UNORM_INT8; auto channelOrder = CL_RGBA; auto const elementSize = 4; // sizeof CL_RGBA * CL_UNORM_INT8 class CreateImageTest : public ClDeviceFixture, public testing::TestWithParam, public CommandQueueHwFixture { typedef CommandQueueHwFixture CommandQueueFixture; public: CreateImageTest() { } Image *createImageWithFlags(cl_mem_flags flags) { return createImageWithFlags(flags, context); } Image *createImageWithFlags(cl_mem_flags flags, Context *context) { auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); return Image::create(context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context->getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, nullptr, retVal); } protected: void SetUp() override { ClDeviceFixture::setUp(); CommandQueueFixture::setUp(pClDevice, 0); flags = GetParam(); // clang-format off imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; imageDesc.image_width = testImageDimensions; imageDesc.image_height = testImageDimensions; imageDesc.image_depth = 0; imageDesc.image_array_size = 1; imageDesc.image_row_pitch = 0; imageDesc.image_slice_pitch = 0; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // clang-format on } void TearDown() override { CommandQueueFixture::tearDown(); ClDeviceFixture::tearDown(); } cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal = CL_SUCCESS; cl_mem_flags flags = 0; unsigned char pHostPtr[testImageDimensions * testImageDimensions * elementSize * 4]; }; typedef CreateImageTest CreateImageNoHostPtr; TEST(TestSliceAndRowPitch, Given1dImageWithZeroRowPitchAndZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 1D image with 0 row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; imageDesc.image_width = width; imageDesc.image_height = 0; imageDesc.image_depth = 0; imageDesc.image_array_size = 0; imageDesc.image_row_pitch = 0; imageDesc.image_slice_pitch = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ(width * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ(0u, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given1dImageWithNonZeroRowPitchAndZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 1D image with non-zero row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; imageDesc.image_width = width; imageDesc.image_height = 0; imageDesc.image_depth = 0; imageDesc.image_array_size = 0; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ(0u, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given2dImageWithNonZeroRowPitchAndZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D image with non-zero row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 0; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ(0u, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given1dArrayWithNonZeroRowPitchAndZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 1D ARRAY image with non-zero row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; imageDesc.image_width = width; imageDesc.image_height = 0; imageDesc.image_depth = 0; imageDesc.image_array_size = 2; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given2dArrayWithNonZeroRowPitchAndZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D ARRAY image with non-zero row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 2; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ((width + 1) * elementSize * height, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given2dArrayWithZeroRowPitchAndNonZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D ARRAY image with zero row_pitch and non-zero slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 2; imageDesc.image_row_pitch = 0; imageDesc.image_slice_pitch = (width + 1) * elementSize * height; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ(width * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ((width + 1) * elementSize * height, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given2dArrayWithNonZeroRowPitchAndNonZeroSlicePitchWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D ARRAY image with non-zero row_pitch and non-zero slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 2; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = (width + 1) * elementSize * height; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ((width + 1) * elementSize * height, image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestSliceAndRowPitch, Given2dArrayWithNonZeroRowPitchAndNonZeroSlicePitchGreaterThanRowPitchTimesHeightWhenGettingHostPtrSlicePitchAndRowPitchThenCorrectValuesAreReturned) { DebugManagerStateRestore dbgRestorer; DebugManager.flags.ForceLinearImages.set(true); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D ARRAY image with non-zero row_pitch and non-zero slice_pitch > row_pitch * height imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 2; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = (width + 1) * elementSize * (height + 1); cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ((width + 1) * elementSize * (height + 1), image->getHostPtrSlicePitch()); delete image; alignedFree(hostPtr); } TEST(TestCreateImage, GivenSharedContextWhenImageIsCreatedThenRowAndSliceAreCorrect) { cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; context.isSharedContext = true; const size_t width = 5; const size_t height = 3; const size_t depth = 2; char *hostPtr = (char *)alignedMalloc(width * height * depth * elementSize * 2, 64); imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D image with non-zero row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 0; imageDesc.image_row_pitch = (width + 1) * elementSize; imageDesc.image_slice_pitch = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal); ASSERT_NE(nullptr, image); EXPECT_EQ((width + 1) * elementSize, image->getHostPtrRowPitch()); EXPECT_EQ(0u, image->getHostPtrSlicePitch()); EXPECT_TRUE(image->isMemObjZeroCopy()); delete image; alignedFree(hostPtr); } TEST(TestCreateImageUseHostPtr, GivenDifferenHostPtrAlignmentsWhenCheckingMemoryALignmentThenCorrectValueIsReturned) { KernelBinaryHelper kbHelper(KernelBinaryHelper::BUILT_INS_WITH_IMAGES); cl_image_format imageFormat; cl_image_desc imageDesc; cl_int retVal; MockContext context; const size_t width = 4; const size_t height = 32; imageFormat.image_channel_data_type = channelType; imageFormat.image_channel_order = channelOrder; imageDesc.num_mip_levels = 0; imageDesc.num_samples = 0; imageDesc.mem_object = NULL; // 2D image with 0 row_pitch and 0 slice_pitch imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; imageDesc.image_width = width; imageDesc.image_height = height; imageDesc.image_depth = 0; imageDesc.image_array_size = 0; imageDesc.image_row_pitch = alignUp(alignUp(width, 4) * 4, 0x80); // row pitch for tiled img imageDesc.image_slice_pitch = 0; void *pageAlignedPointer = alignedMalloc(imageDesc.image_row_pitch * height * 1 * 4 + 256, 4096); void *hostPtr[] = {ptrOffset(pageAlignedPointer, 16), // 16 - byte alignment ptrOffset(pageAlignedPointer, 32), // 32 - byte alignment ptrOffset(pageAlignedPointer, 64), // 64 - byte alignment ptrOffset(pageAlignedPointer, 128)}; // 128 - byte alignment bool result[] = {false, false, true, true}; cl_mem_flags flags = CL_MEM_HOST_NO_ACCESS | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); for (int i = 0; i < 4; i++) { auto image = Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr[i], retVal); ASSERT_NE(nullptr, image); auto address = image->getCpuAddress(); if (result[i] && image->isMemObjZeroCopy()) { EXPECT_EQ(hostPtr[i], address); } else { EXPECT_NE(hostPtr[i], address); } delete image; } alignedFree(pageAlignedPointer); } TEST(TestCreateImageUseHostPtr, givenZeroCopyImageValuesWhenUsingHostPtrThenZeroCopyImageIsCreated) { cl_int retVal = CL_SUCCESS; MockContext context; cl_image_desc imageDesc = {}; imageDesc.image_width = 4096; imageDesc.image_height = 1; imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; cl_image_format imageFormat = {}; imageFormat.image_channel_data_type = CL_UNSIGNED_INT8; imageFormat.image_channel_order = CL_R; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto hostPtr = alignedMalloc(imageDesc.image_width * surfaceFormat->surfaceFormat.ImageElementSizeInBytes, MemoryConstants::cacheLineSize); auto image = std::unique_ptr(Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, hostPtr, retVal)); auto allocation = image->getGraphicsAllocation(context.getDevice(0)->getRootDeviceIndex()); EXPECT_NE(nullptr, image); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_TRUE(image->isMemObjZeroCopy()); EXPECT_EQ(hostPtr, allocation->getUnderlyingBuffer()); EXPECT_EQ(nullptr, image->getMapAllocation(context.getDevice(0)->getRootDeviceIndex())); alignedFree(hostPtr); } TEST_P(CreateImageNoHostPtr, GivenMissingPitchWhenImageIsCreatedThenConstructorFillsMissingData) { auto image = createImageWithFlags(flags); ASSERT_EQ(CL_SUCCESS, retVal); ASSERT_NE(nullptr, image); const auto &imageDesc = image->getImageDesc(); // Sometimes the user doesn't pass image_row/slice_pitch during a create. // Ensure the driver fills in the missing data. EXPECT_NE(0u, imageDesc.image_row_pitch); EXPECT_GE(imageDesc.image_slice_pitch, imageDesc.image_row_pitch); delete image; } TEST_P(CreateImageNoHostPtr, whenImageIsCreatedThenItHasProperAccessAndCacheProperties) { DebugManagerStateRestore restorer; DebugManager.flags.CreateMultipleSubDevices.set(2); auto context = std::make_unique(); auto image = createImageWithFlags(flags, context.get()); ASSERT_EQ(CL_SUCCESS, retVal); ASSERT_NE(nullptr, image); auto allocation = image->getGraphicsAllocation(context->getDevice(0)->getRootDeviceIndex()); EXPECT_TRUE(allocation->getAllocationType() == AllocationType::IMAGE); auto isImageWritable = !(flags & (CL_MEM_READ_ONLY | CL_MEM_HOST_READ_ONLY | CL_MEM_HOST_NO_ACCESS)); EXPECT_EQ(isImageWritable, allocation->isMemObjectsAllocationWithWritableFlags()); auto isReadOnly = isValueSet(flags, CL_MEM_READ_ONLY); EXPECT_NE(isReadOnly, allocation->isFlushL3Required()); delete image; } // Parameterized test that tests image creation with all flags that should be // valid with a nullptr host ptr static cl_mem_flags NoHostPtrFlags[] = { CL_MEM_READ_WRITE, CL_MEM_WRITE_ONLY, CL_MEM_READ_ONLY, CL_MEM_HOST_READ_ONLY, CL_MEM_HOST_WRITE_ONLY, CL_MEM_HOST_NO_ACCESS}; INSTANTIATE_TEST_CASE_P( CreateImageTest_Create, CreateImageNoHostPtr, testing::ValuesIn(NoHostPtrFlags)); struct CreateImageHostPtr : public CreateImageTest, public MemoryManagementFixture { typedef CreateImageTest BaseClass; CreateImageHostPtr() { } void SetUp() override { MemoryManagementFixture::setUp(); BaseClass::SetUp(); } void TearDown() override { delete image; BaseClass::TearDown(); platformsImpl->clear(); MemoryManagementFixture::tearDown(); } Image *createImage(cl_int &retVal) { auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); return Image::create( context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context->getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, pHostPtr, retVal); } cl_int retVal = CL_INVALID_VALUE; Image *image = nullptr; }; TEST_P(CreateImageHostPtr, WhenImageIsCreatedThenResidencyIsFalse) { image = createImage(retVal); ASSERT_NE(nullptr, image); auto allocation = image->getGraphicsAllocation(context->getDevice(0)->getRootDeviceIndex()); EXPECT_FALSE(allocation->isResident(pDevice->getDefaultEngine().osContext->getContextId())); } TEST_P(CreateImageHostPtr, WhenCheckingAddressThenAlllocationDependsOnSizeRelativeToPage) { image = createImage(retVal); auto allocation = image->getGraphicsAllocation(context->getDevice(0)->getRootDeviceIndex()); ASSERT_NE(nullptr, image); auto address = image->getBasePtrForMap(0); EXPECT_NE(nullptr, address); if (!(flags & CL_MEM_USE_HOST_PTR)) { EXPECT_EQ(nullptr, image->getHostPtr()); } if (flags & CL_MEM_USE_HOST_PTR) { // if size fits within a page then zero copy can be applied, if not RT needs to do a copy of image auto computedSize = imageDesc.image_width * elementSize * alignUp(imageDesc.image_height, 4) * imageDesc.image_array_size; auto ptrSize = imageDesc.image_width * elementSize * imageDesc.image_height * imageDesc.image_array_size; auto alignedRequiredSize = alignSizeWholePage(static_cast(pHostPtr), computedSize); auto alignedPtrSize = alignSizeWholePage(static_cast(pHostPtr), ptrSize); size_t halignReq = imageDesc.image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY ? 64 : 1; auto rowPitch = imageDesc.image_width * elementSize; auto slicePitch = rowPitch * imageDesc.image_height; auto requiredRowPitch = alignUp(imageDesc.image_width, halignReq) * elementSize; auto requiredSlicePitch = requiredRowPitch * alignUp(imageDesc.image_height, 4); bool copyRequired = (alignedRequiredSize > alignedPtrSize) | (requiredRowPitch != rowPitch) | (slicePitch != requiredSlicePitch); EXPECT_EQ(pHostPtr, address); EXPECT_EQ(pHostPtr, image->getHostPtr()); if (copyRequired) { EXPECT_FALSE(image->isMemObjZeroCopy()); } } else { EXPECT_NE(pHostPtr, address); } if (flags & CL_MEM_COPY_HOST_PTR && image->isMemObjZeroCopy()) { // Buffer should contain a copy of host memory EXPECT_EQ(0, memcmp(pHostPtr, allocation->getUnderlyingBuffer(), sizeof(testImageDimensions))); } } TEST_P(CreateImageHostPtr, WhenGettingImageDescThenCorrectValuesAreReturned) { image = createImage(retVal); ASSERT_NE(nullptr, image); auto allocation = image->getGraphicsAllocation(context->getDevice(0)->getRootDeviceIndex()); const auto &imageDesc = image->getImageDesc(); // clang-format off EXPECT_EQ(this->imageDesc.image_type, imageDesc.image_type); EXPECT_EQ(this->imageDesc.image_width, imageDesc.image_width); EXPECT_EQ(this->imageDesc.image_height, imageDesc.image_height); EXPECT_EQ(this->imageDesc.image_depth, imageDesc.image_depth); EXPECT_EQ(0u, imageDesc.image_array_size); EXPECT_NE(0u, imageDesc.image_row_pitch); EXPECT_GE(imageDesc.image_slice_pitch, imageDesc.image_row_pitch); EXPECT_EQ(this->imageDesc.num_mip_levels, imageDesc.num_mip_levels); EXPECT_EQ(this->imageDesc.num_samples, imageDesc.num_samples); EXPECT_EQ(this->imageDesc.buffer, imageDesc.buffer); EXPECT_EQ(this->imageDesc.mem_object, imageDesc.mem_object); // clang-format on EXPECT_EQ(image->getHostPtrRowPitch(), static_cast(imageDesc.image_width * elementSize)); // Only 3D, and array images can have slice pitch int isArrayOr3DType = 0; if (this->imageDesc.image_type == CL_MEM_OBJECT_IMAGE3D || this->imageDesc.image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY || this->imageDesc.image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY) { isArrayOr3DType = 1; } EXPECT_EQ(image->getHostPtrSlicePitch(), static_cast(imageDesc.image_width * elementSize * imageDesc.image_height) * isArrayOr3DType); EXPECT_EQ(image->getImageCount(), 1u); EXPECT_NE(0u, image->getSize()); EXPECT_NE(nullptr, allocation); } TEST_P(CreateImageHostPtr, GivenFailedAllocationInjectionWhenCheckingAllocationThenOnlyFailedAllocationReturnsNull) { InjectedFunction method = [this](size_t failureIndex) { // System under test image = createImage(retVal); if (MemoryManagement::nonfailingAllocation == failureIndex) { EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_NE(nullptr, image); } else { EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal) << "for allocation " << failureIndex; EXPECT_EQ(nullptr, image); } delete image; image = nullptr; }; injectFailures(method, 4); // check only first 5 allocations - avoid checks on writeImg call allocations for tiled imgs } TEST_P(CreateImageHostPtr, givenLinearImageWhenFailedAtCreationThenReturnError) { DebugManagerStateRestore restore; DebugManager.flags.ForceLinearImages.set(true); InjectedFunction method = [this](size_t failureIndex) { // System under test image = createImage(retVal); if (MemoryManagement::nonfailingAllocation == failureIndex) { EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_NE(nullptr, image); } else { EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal) << "for allocation " << failureIndex; EXPECT_EQ(nullptr, image); } delete image; image = nullptr; }; injectFailures(method, 4); // check only first 5 allocations - avoid checks on writeImg call allocations for tiled imgs } TEST_P(CreateImageHostPtr, WhenWritingOutsideAllocatedMemoryWhileCreatingImageThenWriteIsHandledCorrectly) { auto mockMemoryManager = new MockMemoryManager(*pDevice->executionEnvironment); pDevice->injectMemoryManager(mockMemoryManager); context->memoryManager = mockMemoryManager; mockMemoryManager->redundancyRatio = 2; memset(pHostPtr, 1, testImageDimensions * testImageDimensions * elementSize * 4); imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; imageDesc.image_height = 1; imageDesc.image_row_pitch = elementSize * imageDesc.image_width + 1; image = createImage(retVal); auto allocation = image->getGraphicsAllocation(pDevice->getRootDeviceIndex()); char *memory = reinterpret_cast(allocation->getUnderlyingBuffer()); auto memorySize = allocation->getUnderlyingBufferSize() / 2; for (size_t i = 0; i < image->getHostPtrSlicePitch(); ++i) { if (i < imageDesc.image_width * elementSize) { EXPECT_EQ(1, memory[i]); } else { EXPECT_EQ(0, memory[i]); } } for (size_t i = 0; i < memorySize; ++i) { EXPECT_EQ(0, memory[memorySize + i]); } mockMemoryManager->redundancyRatio = 1; } struct ModifyableImage { enum { flags = 0 }; static cl_image_format imageFormat; static cl_image_desc imageDesc; static void *hostPtr; static NEO::Context *context; }; void *ModifyableImage::hostPtr = nullptr; NEO::Context *ModifyableImage::context = nullptr; cl_image_format ModifyableImage::imageFormat; cl_image_desc ModifyableImage::imageDesc; class ImageTransfer : public ::testing::Test { public: void SetUp() override { context = new MockContext(); ASSERT_NE(context, nullptr); ModifyableImage::context = context; ModifyableImage::hostPtr = nullptr; ModifyableImage::imageFormat = {CL_R, CL_FLOAT}; ModifyableImage::imageDesc = {CL_MEM_OBJECT_IMAGE1D, 512, 0, 0, 0, 0, 0, 0, 0, {nullptr}}; hostPtr = nullptr; unalignedHostPtr = nullptr; } void TearDown() override { if (context) delete context; if (hostPtr) alignedFree(hostPtr); } void createHostPtrs(size_t imageSize) { hostPtr = alignedMalloc(imageSize + 100, 4096); unalignedHostPtr = (char *)hostPtr + 4; memset(hostPtr, 0, imageSize + 100); memset(unalignedHostPtr, 1, imageSize); } MockContext *context; void *hostPtr; void *unalignedHostPtr; }; TEST_F(ImageTransfer, GivenNonZeroCopyImageWhenDataTransferedFromHostPtrToMemStorageThenNoOverflowOfHostPtr) { size_t imageSize = 512 * 4; createHostPtrs(imageSize); ModifyableImage::imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; ModifyableImage::imageDesc.image_width = 512; ModifyableImage::imageDesc.image_height = 0; ModifyableImage::imageDesc.image_row_pitch = 0; ModifyableImage::imageDesc.image_array_size = 0; ModifyableImage::imageFormat.image_channel_order = CL_R; ModifyableImage::imageFormat.image_channel_data_type = CL_FLOAT; ModifyableImage::hostPtr = unalignedHostPtr; Image *imageNonZeroCopy = ImageHelper>::create(); ASSERT_NE(nullptr, imageNonZeroCopy); void *memoryStorage = imageNonZeroCopy->getCpuAddress(); size_t memoryStorageSize = imageNonZeroCopy->getSize(); ASSERT_NE(memoryStorage, unalignedHostPtr); int result = memcmp(memoryStorage, unalignedHostPtr, imageSize); EXPECT_EQ(0, result); memset(memoryStorage, 0, memoryStorageSize); memset((char *)unalignedHostPtr + imageSize, 2, 100 - 4); auto &imgDesc = imageNonZeroCopy->getImageDesc(); MemObjOffsetArray copyOffset = {{0, 0, 0}}; MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; imageNonZeroCopy->transferDataFromHostPtr(copySize, copyOffset); void *foundData = memchr(memoryStorage, 2, memoryStorageSize); EXPECT_EQ(0, foundData); delete imageNonZeroCopy; } TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchImageWhenDataIsTransferedFromHostPtrToMemStorageThenDestinationIsNotOverflowed) { ModifyableImage::imageDesc.image_width = 16; ModifyableImage::imageDesc.image_row_pitch = 65; ModifyableImage::imageFormat.image_channel_data_type = CL_UNORM_INT8; size_t imageSize = ModifyableImage::imageDesc.image_row_pitch; size_t imageWidth = ModifyableImage::imageDesc.image_width; createHostPtrs(imageSize); ModifyableImage::hostPtr = unalignedHostPtr; Image *imageNonZeroCopy = ImageHelper>::create(); ASSERT_NE(nullptr, imageNonZeroCopy); void *memoryStorage = imageNonZeroCopy->getCpuAddress(); size_t memoryStorageSize = imageNonZeroCopy->getSize(); ASSERT_NE(memoryStorage, unalignedHostPtr); int result = memcmp(memoryStorage, unalignedHostPtr, imageWidth); EXPECT_EQ(0, result); memset(memoryStorage, 0, memoryStorageSize); memset((char *)unalignedHostPtr + imageSize, 2, 100 - 4); auto &imgDesc = imageNonZeroCopy->getImageDesc(); MemObjOffsetArray copyOffset = {{0, 0, 0}}; MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; imageNonZeroCopy->transferDataFromHostPtr(copySize, copyOffset); void *foundData = memchr(memoryStorage, 2, memoryStorageSize); EXPECT_EQ(0, foundData); delete imageNonZeroCopy; } TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchWithExtraBytes1DArrayImageWhenDataIsTransferedForthAndBackThenDataValidates) { ModifyableImage::imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; ModifyableImage::imageDesc.image_width = 5; ModifyableImage::imageDesc.image_row_pitch = 28; // == (4 * 5) row bytes + (4 * 2) extra bytes ModifyableImage::imageDesc.image_array_size = 3; ModifyableImage::imageFormat.image_channel_order = CL_RGBA; ModifyableImage::imageFormat.image_channel_data_type = CL_UNORM_INT8; const size_t imageWidth = ModifyableImage::imageDesc.image_width; const size_t imageRowPitchInPixels = ModifyableImage::imageDesc.image_row_pitch / 4; const size_t imageHeight = 1; const size_t imageCount = ModifyableImage::imageDesc.image_array_size; size_t imageSize = ModifyableImage::imageDesc.image_row_pitch * imageHeight * imageCount; createHostPtrs(imageSize); uint32_t *row = static_cast(unalignedHostPtr); for (uint32_t arrayIndex = 0; arrayIndex < imageCount; ++arrayIndex) { for (uint32_t pixelInRow = 0; pixelInRow < imageRowPitchInPixels; ++pixelInRow) { if (pixelInRow < imageWidth) { row[pixelInRow] = pixelInRow; } else { row[pixelInRow] = 66; } } row = row + imageRowPitchInPixels; } ModifyableImage::hostPtr = unalignedHostPtr; Image *imageNonZeroCopy = ImageHelper>::create(); ASSERT_NE(nullptr, imageNonZeroCopy); void *memoryStorage = imageNonZeroCopy->getCpuAddress(); ASSERT_NE(memoryStorage, unalignedHostPtr); size_t internalSlicePitch = imageNonZeroCopy->getImageDesc().image_slice_pitch; // Check twice, once after image create, and second time after transfer from HostPtrToMemoryStorage // when these paths are unified, only one check will be enough for (size_t run = 0; run < 2; ++run) { row = static_cast(unalignedHostPtr); unsigned char *internalRow = static_cast(memoryStorage); if (run == 1) { auto &imgDesc = imageNonZeroCopy->getImageDesc(); MemObjOffsetArray copyOffset = {{0, 0, 0}}; MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; imageNonZeroCopy->transferDataFromHostPtr(copySize, copyOffset); } for (size_t arrayIndex = 0; arrayIndex < imageCount; ++arrayIndex) { for (size_t pixelInRow = 0; pixelInRow < imageRowPitchInPixels; ++pixelInRow) { if (pixelInRow < imageWidth) { if (memcmp(&row[pixelInRow], &internalRow[pixelInRow * 4], 4)) { EXPECT_FALSE(1) << "Data in memory storage did not validate, row: " << pixelInRow << " array: " << arrayIndex << "\n"; } } else { // Change extra bytes pattern row[pixelInRow] = 55; } } row = row + imageRowPitchInPixels; internalRow = internalRow + internalSlicePitch; } } auto &imgDesc = imageNonZeroCopy->getImageDesc(); MemObjOffsetArray copyOffset = {{0, 0, 0}}; MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; imageNonZeroCopy->transferDataToHostPtr(copySize, copyOffset); row = static_cast(unalignedHostPtr); for (size_t arrayIndex = 0; arrayIndex < imageCount; ++arrayIndex) { for (size_t pixelInRow = 0; pixelInRow < imageRowPitchInPixels; ++pixelInRow) { if (pixelInRow < imageWidth) { if (row[pixelInRow] != pixelInRow) { EXPECT_FALSE(1) << "Data under host_ptr did not validate, row: " << pixelInRow << " array: " << arrayIndex << "\n"; } } else { if (row[pixelInRow] != 55) { EXPECT_FALSE(1) << "Data under host_ptr corrupted in extra bytes, row: " << pixelInRow << " array: " << arrayIndex << "\n"; } } } row = row + imageRowPitchInPixels; } delete imageNonZeroCopy; } // Parameterized test that tests image creation with all flags that should be // valid with a valid host ptr static cl_mem_flags ValidHostPtrFlags[] = { 0 | CL_MEM_USE_HOST_PTR, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_HOST_READ_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_HOST_WRITE_ONLY | CL_MEM_USE_HOST_PTR, CL_MEM_HOST_NO_ACCESS | CL_MEM_USE_HOST_PTR, 0 | CL_MEM_COPY_HOST_PTR, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_HOST_READ_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_HOST_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, CL_MEM_HOST_NO_ACCESS | CL_MEM_COPY_HOST_PTR}; INSTANTIATE_TEST_CASE_P( CreateImageTest_Create, CreateImageHostPtr, testing::ValuesIn(ValidHostPtrFlags)); TEST(ImageGetSurfaceFormatInfoTest, givenNullptrFormatWhenGetSurfaceFormatInfoIsCalledThenReturnsNullptr) { MockContext context; auto surfaceFormat = Image::getSurfaceFormatFromTable(0, nullptr, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); EXPECT_EQ(nullptr, surfaceFormat); } HWTEST_F(ImageCompressionTests, givenTiledImageWhenCreatingAllocationThenPreferCompression) { imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; imageDesc.image_width = 5; imageDesc.image_height = 5; MockContext context; auto surfaceFormat = Image::getSurfaceFormatFromTable(flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = std::unique_ptr(Image::create( mockContext.get(), ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); ASSERT_NE(nullptr, image); EXPECT_EQ(UnitTestHelper::tiledImagesSupported, image->isTiledAllocation()); EXPECT_TRUE(myMemoryManager->mockMethodCalled); EXPECT_EQ(UnitTestHelper::tiledImagesSupported, myMemoryManager->capturedPreferCompressed); } TEST_F(ImageCompressionTests, givenNonTiledImageWhenCreatingAllocationThenDontPreferCompression) { imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; imageDesc.image_width = 5; MockContext context; auto surfaceFormat = Image::getSurfaceFormatFromTable(flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = std::unique_ptr(Image::create( mockContext.get(), ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); ASSERT_NE(nullptr, image); EXPECT_FALSE(image->isTiledAllocation()); EXPECT_TRUE(myMemoryManager->mockMethodCalled); EXPECT_FALSE(myMemoryManager->capturedPreferCompressed); } HWTEST_F(ImageCompressionTests, givenTiledImageAndVariousFlagsWhenCreatingAllocationThenCorrectlySetPreferCompression) { imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; imageDesc.image_width = 5; imageDesc.image_height = 5; auto newFlags = flags | CL_MEM_COMPRESSED_HINT_INTEL; MockContext context; auto surfaceFormat = Image::getSurfaceFormatFromTable( newFlags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = std::unique_ptr(Image::create( mockContext.get(), ClMemoryPropertiesHelper::createMemoryProperties(newFlags, 0, 0, &context.getDevice(0)->getDevice()), newFlags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); ASSERT_NE(nullptr, image); EXPECT_EQ(UnitTestHelper::tiledImagesSupported, image->isTiledAllocation()); EXPECT_TRUE(myMemoryManager->mockMethodCalled); EXPECT_EQ(UnitTestHelper::tiledImagesSupported, myMemoryManager->capturedPreferCompressed); newFlags = flags | CL_MEM_UNCOMPRESSED_HINT_INTEL; surfaceFormat = Image::getSurfaceFormatFromTable( newFlags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); image = std::unique_ptr(Image::create( mockContext.get(), ClMemoryPropertiesHelper::createMemoryProperties(newFlags, 0, 0, &context.getDevice(0)->getDevice()), newFlags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); ASSERT_NE(nullptr, image); EXPECT_EQ(UnitTestHelper::tiledImagesSupported, image->isTiledAllocation()); EXPECT_TRUE(myMemoryManager->mockMethodCalled); EXPECT_FALSE(myMemoryManager->capturedPreferCompressed); } TEST_F(ImageCompressionTests, givenNonTiledImageAndVariousFlagsWhenCreatingAllocationThenDontPreferCompression) { imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; imageDesc.image_width = 5; auto newFlags = flags | CL_MEM_COMPRESSED_HINT_INTEL; MockContext context; auto surfaceFormat = Image::getSurfaceFormatFromTable( newFlags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = std::unique_ptr(Image::create( mockContext.get(), ClMemoryPropertiesHelper::createMemoryProperties(newFlags, 0, 0, &context.getDevice(0)->getDevice()), newFlags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); ASSERT_NE(nullptr, image); EXPECT_FALSE(image->isTiledAllocation()); EXPECT_TRUE(myMemoryManager->mockMethodCalled); EXPECT_FALSE(myMemoryManager->capturedPreferCompressed); newFlags = flags | CL_MEM_UNCOMPRESSED_HINT_INTEL; surfaceFormat = Image::getSurfaceFormatFromTable( newFlags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); image = std::unique_ptr(Image::create( mockContext.get(), ClMemoryPropertiesHelper::createMemoryProperties(newFlags, 0, 0, &context.getDevice(0)->getDevice()), newFlags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); ASSERT_NE(nullptr, image); EXPECT_FALSE(image->isTiledAllocation()); EXPECT_TRUE(myMemoryManager->mockMethodCalled); EXPECT_FALSE(myMemoryManager->capturedPreferCompressed); } TEST(ImageTest, givenImageWhenGettingCompressionOfImageThenCorrectValueIsReturned) { MockContext context; std::unique_ptr image(ImageHelper::create(&context)); EXPECT_NE(nullptr, image); auto allocation = image->getGraphicsAllocation(context.getDevice(0)->getRootDeviceIndex()); allocation->getDefaultGmm()->isCompressionEnabled = true; size_t sizeReturned = 0; cl_bool usesCompression; cl_int retVal = CL_SUCCESS; retVal = image->getMemObjectInfo( CL_MEM_USES_COMPRESSION_INTEL, sizeof(cl_bool), &usesCompression, &sizeReturned); EXPECT_EQ(CL_SUCCESS, retVal); ASSERT_EQ(sizeof(cl_bool), sizeReturned); EXPECT_TRUE(usesCompression); allocation->getDefaultGmm()->isCompressionEnabled = false; sizeReturned = 0; usesCompression = cl_bool{CL_FALSE}; retVal = image->getMemObjectInfo( CL_MEM_USES_COMPRESSION_INTEL, sizeof(cl_bool), &usesCompression, &sizeReturned); EXPECT_EQ(CL_SUCCESS, retVal); ASSERT_EQ(sizeof(cl_bool), sizeReturned); EXPECT_FALSE(usesCompression); } using ImageTests = ::testing::Test; HWTEST_F(ImageTests, givenImageWhenAskedForPtrOffsetForGpuMappingThenReturnCorrectValue) { if (!UnitTestHelper::tiledImagesSupported) { GTEST_SKIP(); } MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); EXPECT_FALSE(image->mappingOnCpuAllowed()); MemObjOffsetArray origin = {{4, 5, 6}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getHostPtrRowPitch() * origin[1] + image->getHostPtrSlicePitch() * origin[2]; EXPECT_EQ(expectedOffset, retOffset); } TEST(ImageTest, givenImageWhenAskedForMcsInfoThenDefaultValuesAreReturned) { MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); auto mcsInfo = image->getMcsSurfaceInfo(); EXPECT_EQ(0u, mcsInfo.multisampleCount); EXPECT_EQ(0u, mcsInfo.qPitch); EXPECT_EQ(0u, mcsInfo.pitch); } TEST(ImageTest, givenImageWhenAskedForPtrOffsetForCpuMappingThenReturnCorrectValue) { DebugManagerStateRestore restore; DebugManager.flags.ForceLinearImages.set(true); MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); EXPECT_TRUE(image->mappingOnCpuAllowed()); MemObjOffsetArray origin = {{4, 5, 6}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getImageDesc().image_row_pitch * origin[1] + image->getImageDesc().image_slice_pitch * origin[2]; EXPECT_EQ(expectedOffset, retOffset); } TEST(ImageTest, given1DArrayImageWhenAskedForPtrOffsetForMappingThenReturnCorrectValue) { MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); MemObjOffsetArray origin = {{4, 5, 0}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getImageDesc().image_slice_pitch * origin[1]; EXPECT_EQ(expectedOffset, retOffset); } HWTEST_F(ImageTests, givenImageWhenAskedForPtrLengthForGpuMappingThenReturnCorrectValue) { if (!UnitTestHelper::tiledImagesSupported) { GTEST_SKIP(); } MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); EXPECT_FALSE(image->mappingOnCpuAllowed()); MemObjSizeArray region = {{4, 5, 6}}; auto retLength = image->calculateMappedPtrLength(region); size_t expectedLength = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * region[0] + image->getHostPtrRowPitch() * region[1] + image->getHostPtrSlicePitch() * region[2]; EXPECT_EQ(expectedLength, retLength); } TEST(ImageTest, givenImageWhenAskedForPtrLengthForCpuMappingThenReturnCorrectValue) { DebugManagerStateRestore restore; DebugManager.flags.ForceLinearImages.set(true); MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); EXPECT_TRUE(image->mappingOnCpuAllowed()); MemObjSizeArray region = {{4, 5, 6}}; auto retLength = image->calculateMappedPtrLength(region); size_t expectedLength = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * region[0] + image->getImageDesc().image_row_pitch * region[1] + image->getImageDesc().image_slice_pitch * region[2]; EXPECT_EQ(expectedLength, retLength); } TEST(ImageTest, givenMipMapImage3DWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithSlicePitch) { MockContext ctx; cl_image_desc imageDesc{}; imageDesc.image_type = CL_MEM_OBJECT_IMAGE3D; imageDesc.image_width = 5; imageDesc.image_height = 5; imageDesc.image_depth = 5; imageDesc.num_mip_levels = 2; std::unique_ptr image(ImageHelper::create(&ctx, &imageDesc)); EXPECT_FALSE(image->mappingOnCpuAllowed()); MemObjOffsetArray origin{{1, 1, 1}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getHostPtrRowPitch() * origin[1] + image->getHostPtrSlicePitch() * origin[2]; EXPECT_EQ(expectedOffset, retOffset); } TEST(ImageTest, givenMipMapImage2DArrayWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithSlicePitch) { MockContext ctx; cl_image_desc imageDesc{}; imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; imageDesc.image_width = 5; imageDesc.image_height = 5; imageDesc.image_array_size = 5; imageDesc.num_mip_levels = 2; std::unique_ptr image(ImageHelper::create(&ctx, &imageDesc)); EXPECT_FALSE(image->mappingOnCpuAllowed()); MemObjOffsetArray origin{{1, 1, 1}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getHostPtrRowPitch() * origin[1] + image->getHostPtrSlicePitch() * origin[2]; EXPECT_EQ(expectedOffset, retOffset); } TEST(ImageTest, givenNonMipMapImage2DArrayWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithSlicePitch) { MockContext ctx; cl_image_desc imageDesc{}; imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; imageDesc.image_width = 5; imageDesc.image_height = 5; imageDesc.image_array_size = 5; imageDesc.num_mip_levels = 1; std::unique_ptr image(ImageHelper::create(&ctx, &imageDesc)); EXPECT_FALSE(image->mappingOnCpuAllowed()); MemObjOffsetArray origin{{1, 1, 1}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getHostPtrRowPitch() * origin[1] + image->getHostPtrSlicePitch() * origin[2]; EXPECT_EQ(expectedOffset, retOffset); } TEST(ImageTest, givenMipMapImage1DArrayWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithSlicePitch) { MockContext ctx; cl_image_desc imageDesc{}; imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; imageDesc.image_width = 5; imageDesc.image_array_size = 5; imageDesc.num_mip_levels = 2; std::unique_ptr image(ImageHelper::create(&ctx, &imageDesc)); EXPECT_FALSE(image->mappingOnCpuAllowed()); MemObjOffsetArray origin{{1, 1, 0}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().surfaceFormat.ImageElementSizeInBytes * origin[0] + image->getHostPtrSlicePitch() * origin[1]; EXPECT_EQ(expectedOffset, retOffset); } TEST(ImageTest, givenClMemForceLinearStorageSetWhenCreateImageThenDisallowTiling) { cl_int retVal = CL_SUCCESS; MockContext context; cl_image_desc imageDesc = {}; imageDesc.image_width = 4096; imageDesc.image_height = 1; imageDesc.image_depth = 1; imageDesc.image_type = CL_MEM_OBJECT_IMAGE3D; cl_image_format imageFormat = {}; imageFormat.image_channel_data_type = CL_UNSIGNED_INT8; imageFormat.image_channel_order = CL_R; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_FORCE_LINEAR_STORAGE_INTEL; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); auto image = std::unique_ptr(Image::create( &context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, nullptr, retVal)); EXPECT_FALSE(image->isTiledAllocation()); EXPECT_NE(nullptr, image); EXPECT_EQ(CL_SUCCESS, retVal); } TEST(ImageTest, givenClMemCopyHostPointerPassedToImageCreateWhenAllocationIsNotInSystemMemoryPoolThenAllocationIsWrittenByEnqueueWriteImage) { REQUIRE_IMAGES_OR_SKIP(defaultHwInfo); ExecutionEnvironment *executionEnvironment = platform()->peekExecutionEnvironment(); auto *memoryManager = new MockMemoryManagerFailFirstAllocation(*executionEnvironment); executionEnvironment->memoryManager.reset(memoryManager); memoryManager->returnBaseAllocateGraphicsMemoryInDevicePool = true; auto device = std::make_unique(MockDevice::create(executionEnvironment, 0)); MockContext ctx(device.get()); char memory[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; auto taskCount = device->getGpgpuCommandStreamReceiver().peekLatestFlushedTaskCount(); cl_int retVal = 0; cl_mem_flags flags = CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR; cl_image_desc imageDesc{}; imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; imageDesc.image_width = 1; imageDesc.image_height = 1; imageDesc.image_row_pitch = sizeof(memory); cl_image_format imageFormat = {}; imageFormat.image_channel_data_type = CL_UNSIGNED_INT8; imageFormat.image_channel_order = CL_R; MockContext context; auto surfaceFormat = Image::getSurfaceFormatFromTable( flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); memoryManager->returnAllocateNonSystemGraphicsMemoryInDevicePool = true; std::unique_ptr image( Image::create(&ctx, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), flags, 0, surfaceFormat, &imageDesc, memory, retVal)); EXPECT_NE(nullptr, image); auto taskCountSent = device->getGpgpuCommandStreamReceiver().peekLatestFlushedTaskCount(); EXPECT_LT(taskCount, taskCountSent); } struct ImageConvertTypeTest : public ::testing::Test { void SetUp() override { } void TearDown() override { } std::array, 7> types = {{std::make_pair<>(CL_MEM_OBJECT_IMAGE1D, ImageType::Image1D), std::make_pair<>(CL_MEM_OBJECT_IMAGE2D, ImageType::Image2D), std::make_pair<>(CL_MEM_OBJECT_IMAGE3D, ImageType::Image3D), std::make_pair<>(CL_MEM_OBJECT_IMAGE1D_ARRAY, ImageType::Image1DArray), std::make_pair<>(CL_MEM_OBJECT_IMAGE2D_ARRAY, ImageType::Image2DArray), std::make_pair<>(CL_MEM_OBJECT_IMAGE1D_BUFFER, ImageType::Image1DBuffer), std::make_pair<>(0, ImageType::Invalid)}}; }; TEST_F(ImageConvertTypeTest, givenClMemObjectTypeWhenConvertedThenCorrectImageTypeIsReturned) { for (size_t i = 0; i < types.size(); i++) { EXPECT_EQ(types[i].second, Image::convertType(static_cast(types[i].first))); } } TEST_F(ImageConvertTypeTest, givenImageTypeWhenConvertedThenCorrectClMemObjectTypeIsReturned) { for (size_t i = 0; i < types.size(); i++) { EXPECT_EQ(static_cast(types[i].first), Image::convertType(types[i].second)); } } TEST(ImageConvertDescriptorTest, givenClImageDescWhenConvertedThenCorrectImageDescriptorIsReturned) { cl_image_desc clDesc = {CL_MEM_OBJECT_IMAGE1D, 16, 24, 1, 1, 1024, 2048, 1, 3, {nullptr}}; auto desc = Image::convertDescriptor(clDesc); EXPECT_EQ(ImageType::Image1D, desc.imageType); EXPECT_EQ(clDesc.image_array_size, desc.imageArraySize); EXPECT_EQ(clDesc.image_depth, desc.imageDepth); EXPECT_EQ(clDesc.image_height, desc.imageHeight); EXPECT_EQ(clDesc.image_row_pitch, desc.imageRowPitch); EXPECT_EQ(clDesc.image_slice_pitch, desc.imageSlicePitch); EXPECT_EQ(clDesc.image_width, desc.imageWidth); EXPECT_EQ(clDesc.num_mip_levels, desc.numMipLevels); EXPECT_EQ(clDesc.num_samples, desc.numSamples); EXPECT_FALSE(desc.fromParent); cl_mem temporary = reinterpret_cast(0x1234); clDesc.mem_object = temporary; desc = Image::convertDescriptor(clDesc); EXPECT_TRUE(desc.fromParent); } TEST(ImageConvertDescriptorTest, givenImageDescriptorWhenConvertedThenCorrectClImageDescIsReturned) { ImageDescriptor desc = {ImageType::Image2D, 16, 24, 1, 1, 1024, 2048, 1, 3, false}; auto clDesc = Image::convertDescriptor(desc); EXPECT_EQ(clDesc.image_type, static_cast(CL_MEM_OBJECT_IMAGE2D)); EXPECT_EQ(clDesc.image_array_size, desc.imageArraySize); EXPECT_EQ(clDesc.image_depth, desc.imageDepth); EXPECT_EQ(clDesc.image_height, desc.imageHeight); EXPECT_EQ(clDesc.image_row_pitch, desc.imageRowPitch); EXPECT_EQ(clDesc.image_slice_pitch, desc.imageSlicePitch); EXPECT_EQ(clDesc.image_width, desc.imageWidth); EXPECT_EQ(clDesc.num_mip_levels, desc.numMipLevels); EXPECT_EQ(clDesc.num_samples, desc.numSamples); EXPECT_EQ(nullptr, clDesc.mem_object); } TEST(ImageTest, givenImageWhenValidateRegionAndOriginIsCalledThenAdditionalOriginAndRegionCoordinatesAreAnalyzed) { size_t origin[3]{}; size_t region[3]{1, 1, 1}; for (uint32_t imageType : {CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE2D_ARRAY, CL_MEM_OBJECT_IMAGE3D}) { cl_image_desc desc = {}; desc.image_type = imageType; EXPECT_EQ(CL_INVALID_VALUE, Image::validateRegionAndOrigin(origin, region, desc)); desc.image_width = 1; EXPECT_EQ(CL_INVALID_VALUE, Image::validateRegionAndOrigin(origin, region, desc)); desc.image_height = 1; desc.image_depth = 1; desc.image_array_size = 1; EXPECT_EQ(CL_SUCCESS, Image::validateRegionAndOrigin(origin, region, desc)); if (imageType == CL_MEM_OBJECT_IMAGE3D) { desc.image_depth = 0; EXPECT_EQ(CL_INVALID_VALUE, Image::validateRegionAndOrigin(origin, region, desc)); } } } TEST(ImageTest, givenImageArrayWhenValidateRegionAndOriginIsCalledThenAdditionalOriginAndRegionCoordinatesAreAnalyzed) { size_t region[3]{1, 1, 1}; size_t origin[3]{}; cl_image_desc desc = {}; desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY; desc.image_width = 1; EXPECT_EQ(CL_INVALID_VALUE, Image::validateRegionAndOrigin(origin, region, desc)); desc.image_array_size = 1; EXPECT_EQ(CL_SUCCESS, Image::validateRegionAndOrigin(origin, region, desc)); desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY; desc.image_array_size = 0; desc.image_width = 1; desc.image_height = 1; EXPECT_EQ(CL_INVALID_VALUE, Image::validateRegionAndOrigin(origin, region, desc)); desc.image_array_size = 1; EXPECT_EQ(CL_SUCCESS, Image::validateRegionAndOrigin(origin, region, desc)); } typedef ::testing::TestWithParam MipLevelCoordinateTest; TEST_P(MipLevelCoordinateTest, givenMipmappedImageWhenValidateRegionAndOriginIsCalledThenAdditionalOriginCoordinateIsAnalyzed) { size_t origin[4]{}; size_t region[3]{1, 1, 1}; cl_image_desc desc = {}; desc.image_type = GetParam(); desc.num_mip_levels = 2; desc.image_width = 1; desc.image_height = 1; desc.image_depth = 1; desc.image_array_size = 1; origin[getMipLevelOriginIdx(desc.image_type)] = 1; EXPECT_EQ(CL_SUCCESS, Image::validateRegionAndOrigin(origin, region, desc)); origin[getMipLevelOriginIdx(desc.image_type)] = 2; EXPECT_EQ(CL_INVALID_MIP_LEVEL, Image::validateRegionAndOrigin(origin, region, desc)); } INSTANTIATE_TEST_CASE_P(MipLevelCoordinate, MipLevelCoordinateTest, ::testing::Values(CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE2D_ARRAY, CL_MEM_OBJECT_IMAGE3D)); typedef ::testing::TestWithParam> HasSlicesTest; TEST_P(HasSlicesTest, givenMemObjectTypeWhenHasSlicesIsCalledThenReturnsTrueIfTypeDefinesObjectWithSlicePitch) { auto pair = GetParam(); EXPECT_EQ(pair.second, Image::hasSlices(pair.first)); } INSTANTIATE_TEST_CASE_P(HasSlices, HasSlicesTest, ::testing::Values(std::make_pair(CL_MEM_OBJECT_IMAGE1D, false), std::make_pair(CL_MEM_OBJECT_IMAGE1D_ARRAY, true), std::make_pair(CL_MEM_OBJECT_IMAGE2D, false), std::make_pair(CL_MEM_OBJECT_IMAGE2D_ARRAY, true), std::make_pair(CL_MEM_OBJECT_IMAGE3D, true), std::make_pair(CL_MEM_OBJECT_BUFFER, false), std::make_pair(CL_MEM_OBJECT_PIPE, false))); typedef ::testing::Test ImageTransformTest; HWTEST_F(ImageTransformTest, givenSurfaceStateWhenTransformImage3dTo2dArrayIsCalledThenSurface2dArrayIsSet) { using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; MockContext context; auto image = std::unique_ptr(ImageHelper::create(&context)); auto surfaceState = FamilyType::cmdInitRenderSurfaceState; auto imageHw = static_cast *>(image.get()); surfaceState.setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D); surfaceState.setSurfaceArray(false); imageHw->transformImage3dTo2dArray(reinterpret_cast(&surfaceState)); EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, surfaceState.getSurfaceType()); EXPECT_TRUE(surfaceState.getSurfaceArray()); } HWTEST_F(ImageTransformTest, givenSurfaceStateWhenTransformImage2dArrayTo3dIsCalledThenSurface3dIsSet) { using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; MockContext context; auto image = std::unique_ptr(ImageHelper::create(&context)); auto surfaceState = FamilyType::cmdInitRenderSurfaceState; auto imageHw = static_cast *>(image.get()); surfaceState.setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D); surfaceState.setSurfaceArray(true); imageHw->transformImage2dArrayTo3d(reinterpret_cast(&surfaceState)); EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, surfaceState.getSurfaceType()); EXPECT_FALSE(surfaceState.getSurfaceArray()); } HWTEST_F(ImageTransformTest, givenSurfaceBaseAddressAndUnifiedSurfaceWhenSetUnifiedAuxAddressCalledThenAddressIsSet) { using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; MockContext context; auto image = std::unique_ptr(ImageHelper::create(&context)); auto surfaceState = FamilyType::cmdInitRenderSurfaceState; auto gmm = std::unique_ptr(new Gmm(context.getDevice(0)->getGmmHelper(), nullptr, 1, 0, GMM_RESOURCE_USAGE_OCL_BUFFER, false, {}, true)); uint64_t surfBsaseAddress = 0xABCDEF1000; surfaceState.setSurfaceBaseAddress(surfBsaseAddress); auto mockResource = reinterpret_cast(gmm->gmmResourceInfo.get()); mockResource->setUnifiedAuxTranslationCapable(); EXPECT_EQ(0u, surfaceState.getAuxiliarySurfaceBaseAddress()); setUnifiedAuxBaseAddress(&surfaceState, gmm.get()); uint64_t offset = gmm->gmmResourceInfo->getUnifiedAuxSurfaceOffset(GMM_UNIFIED_AUX_TYPE::GMM_AUX_SURF); EXPECT_EQ(surfBsaseAddress + offset, surfaceState.getAuxiliarySurfaceBaseAddress()); } TEST(ImageTest, givenImageWhenFillRegionIsCalledThenProperRegionIsSet) { MockContext context; { size_t region[3] = {}; std::unique_ptr image(Image1dHelper<>::create(&context)); image->fillImageRegion(region); EXPECT_EQ(Image1dDefaults::imageDesc.image_width, region[0]); EXPECT_EQ(1u, region[1]); EXPECT_EQ(1u, region[2]); } { size_t region[3] = {}; std::unique_ptr image(Image1dArrayHelper<>::create(&context)); image->fillImageRegion(region); EXPECT_EQ(Image1dArrayDefaults::imageDesc.image_width, region[0]); EXPECT_EQ(Image1dArrayDefaults::imageDesc.image_array_size, region[1]); EXPECT_EQ(1u, region[2]); } { size_t region[3] = {}; std::unique_ptr image(Image1dBufferHelper<>::create(&context)); image->fillImageRegion(region); EXPECT_EQ(Image1dBufferDefaults::imageDesc.image_width, region[0]); EXPECT_EQ(1u, region[1]); EXPECT_EQ(1u, region[2]); } { size_t region[3] = {}; std::unique_ptr image(Image2dHelper<>::create(&context)); image->fillImageRegion(region); EXPECT_EQ(Image2dDefaults::imageDesc.image_width, region[0]); EXPECT_EQ(Image2dDefaults::imageDesc.image_height, region[1]); EXPECT_EQ(1u, region[2]); } { size_t region[3] = {}; std::unique_ptr image(Image2dArrayHelper<>::create(&context)); image->fillImageRegion(region); EXPECT_EQ(Image2dArrayDefaults::imageDesc.image_width, region[0]); EXPECT_EQ(Image2dArrayDefaults::imageDesc.image_height, region[1]); EXPECT_EQ(Image2dArrayDefaults::imageDesc.image_array_size, region[2]); } { size_t region[3] = {}; std::unique_ptr image(Image3dHelper<>::create(&context)); image->fillImageRegion(region); EXPECT_EQ(Image3dDefaults::imageDesc.image_width, region[0]); EXPECT_EQ(Image3dDefaults::imageDesc.image_height, region[1]); EXPECT_EQ(Image3dDefaults::imageDesc.image_depth, region[2]); } } TEST(ImageTest, givenMultiDeviceEnvironmentWhenReleaseImageFromBufferThenMainBufferProperlyDereferenced) { MockDefaultContext context; int32_t retVal; auto *buffer = Buffer::create(&context, CL_MEM_READ_WRITE, MemoryConstants::pageSize, nullptr, retVal); auto imageDesc = Image2dDefaults::imageDesc; cl_mem clBuffer = buffer; imageDesc.mem_object = clBuffer; auto image = Image2dHelper<>::create(&context, &imageDesc); EXPECT_EQ(3u, buffer->getMultiGraphicsAllocation().getGraphicsAllocations().size()); EXPECT_EQ(3u, image->getMultiGraphicsAllocation().getGraphicsAllocations().size()); EXPECT_EQ(2, buffer->getRefInternalCount()); image->release(); EXPECT_EQ(1, buffer->getRefInternalCount()); buffer->release(); }