From e9ebe2ebf874902f9e510cac695e2d8bd23f686c Mon Sep 17 00:00:00 2001 From: "Diedrich, Kamil" Date: Sun, 19 Mar 2023 23:36:46 +0000 Subject: [PATCH] Add redescribing for YUYV format Related-To: NEO-7245 Signed-off-by: Diedrich, Kamil --- opencl/source/mem_obj/image.cpp | 43 +++++---- opencl/source/sharings/va/va_surface.cpp | 13 ++- .../mem_obj/image_validate_tests.cpp | 87 ++++++++++++++++++- .../mem_obj/packed_yuv_image_tests.cpp | 60 +++++++++++++ .../sharings/va/va_sharing_tests.cpp | 19 ++-- 5 files changed, 197 insertions(+), 25 deletions(-) diff --git a/opencl/source/mem_obj/image.cpp b/opencl/source/mem_obj/image.cpp index 030d254d92..faa665520f 100644 --- a/opencl/source/mem_obj/image.cpp +++ b/opencl/source/mem_obj/image.cpp @@ -411,12 +411,17 @@ cl_int Image::validate(Context *context, return CL_INVALID_VALUE; } } - if (parentImage && !isNV12Image(&parentImage->getImageFormat())) { // Image 2d from image 2d + if (parentImage && (!isNV12Image(&parentImage->getImageFormat()) && !isPackedYuvImage(&parentImage->getImageFormat()))) { // Image 2d from image 2d if (!parentImage->hasSameDescriptor(*imageDesc) || !parentImage->hasValidParentImageFormat(surfaceFormat->OCLImageFormat)) { return CL_INVALID_IMAGE_FORMAT_DESCRIPTOR; } } - if (!(parentImage && isNV12Image(&parentImage->getImageFormat())) && + if (parentImage && isPackedYuvImage(&parentImage->getImageFormat())) { + if (!parentImage->hasValidParentImageFormat(surfaceFormat->OCLImageFormat) || imageDesc->image_width != parentImage->getImageDesc().image_width / 2) { + return CL_INVALID_IMAGE_DESCRIPTOR; + } + } + if (!((parentImage && isNV12Image(&parentImage->getImageFormat())) || (parentImage && isPackedYuvImage(&parentImage->getImageFormat()))) && (imageDesc->image_width == 0 || imageDesc->image_height == 0)) { return CL_INVALID_IMAGE_DESCRIPTOR; } @@ -1116,22 +1121,26 @@ void Image::setImageProperties(Image *image, const cl_image_desc &imageDesc, con } void Image::adjustImagePropertiesFromParentImage(size_t &width, size_t &height, size_t &depth, ImageInfo &imageInfo, cl_image_desc &descriptor, Image *parentImage) { - - width = parentImage->getImageDesc().image_width; - height = parentImage->getImageDesc().image_height; - depth = 1; - if (isNV12Image(&parentImage->getImageFormat())) { - if (descriptor.image_depth == 1) { // UV Plane - width /= 2; - height /= 2; - imageInfo.plane = GMM_PLANE_U; - } else { - imageInfo.plane = GMM_PLANE_Y; + if (isPackedYuvImage(&parentImage->getImageFormat())) { + width = parentImage->getImageDesc().image_width / 2; + height = parentImage->getImageDesc().image_height; + } else { + width = parentImage->getImageDesc().image_width; + height = parentImage->getImageDesc().image_height; + depth = 1; + if (isNV12Image(&parentImage->getImageFormat())) { + if (descriptor.image_depth == 1) { // UV Plane + width /= 2; + height /= 2; + imageInfo.plane = GMM_PLANE_U; + } else { + imageInfo.plane = GMM_PLANE_Y; + } } - } - imageInfo.surfaceFormat = &parentImage->surfaceFormatInfo.surfaceFormat; - descriptor = parentImage->getImageDesc(); + imageInfo.surfaceFormat = &parentImage->surfaceFormatInfo.surfaceFormat; + descriptor = parentImage->getImageDesc(); + } } void Image::setAllocationInfoFromParentBuffer(CreateMemObj::AllocationInfo &allocationInfo, const void *&hostPtr, void *&hostPtrToSet, @@ -1607,6 +1616,8 @@ bool Image::hasValidParentImageFormat(const cl_image_format &imageFormat) const return imageFormat.image_channel_order == CL_RGBx; case CL_R: return imageFormat.image_channel_order == CL_DEPTH; + case CL_YUYV_INTEL: + return imageFormat.image_channel_order == CL_RGBA; default: return false; } diff --git a/opencl/source/sharings/va/va_surface.cpp b/opencl/source/sharings/va/va_surface.cpp index fd4ab4d367..c47a9ddd45 100644 --- a/opencl/source/sharings/va/va_surface.cpp +++ b/opencl/source/sharings/va/va_surface.cpp @@ -63,6 +63,9 @@ VAStatus VASurface::getSurfaceDescription(SharedSurfaceInfo &surfaceInfo, VAShar return VA_STATUS_ERROR_INVALID_PARAMETER; } + surfaceInfo.imagePitch = vaDrmPrimeSurfaceDesc.layers[0].pitch[0]; + surfaceInfo.imageOffset = vaDrmPrimeSurfaceDesc.layers[0].offset[0]; + if (surfaceInfo.plane == 1) { surfaceInfo.imageOffset = vaDrmPrimeSurfaceDesc.layers[1].offset[0]; surfaceInfo.imagePitch = vaDrmPrimeSurfaceDesc.layers[1].pitch[0]; @@ -151,7 +154,13 @@ void VASurface::applyPlaneSettings(SharedSurfaceInfo &sharedSurfaceInfo, cl_uint } void VASurface::applyPackedOptions(SharedSurfaceInfo &sharedSurfaceInfo) { - sharedSurfaceInfo.channelOrder = CL_YUYV_INTEL; + if (sharedSurfaceInfo.imageFourcc == VA_FOURCC_Y210) { + sharedSurfaceInfo.channelType = CL_UNORM_INT16; + sharedSurfaceInfo.channelOrder = CL_RGBA; + } else { + sharedSurfaceInfo.channelType = CL_UNORM_INT8; + sharedSurfaceInfo.channelOrder = CL_YUYV_INTEL; + } sharedSurfaceInfo.imgInfo.surfaceFormat = &VASurface::getExtendedSurfaceFormatInfo(sharedSurfaceInfo.imageFourcc)->surfaceFormat; } @@ -240,6 +249,8 @@ bool VASurface::validate(cl_mem_flags flags, cl_uint plane) { case CL_MEM_READ_ONLY: case CL_MEM_WRITE_ONLY: case CL_MEM_READ_WRITE: + case CL_MEM_READ_ONLY | CL_MEM_ACCESS_FLAGS_UNRESTRICTED_INTEL: + case CL_MEM_ACCESS_FLAGS_UNRESTRICTED_INTEL: break; default: return false; diff --git a/opencl/test/unit_test/mem_obj/image_validate_tests.cpp b/opencl/test/unit_test/mem_obj/image_validate_tests.cpp index 7ebc0d075a..420596ffbe 100644 --- a/opencl/test/unit_test/mem_obj/image_validate_tests.cpp +++ b/opencl/test/unit_test/mem_obj/image_validate_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -759,7 +759,7 @@ INSTANTIATE_TEST_CASE_P( using ValidParentImageFormatTest = ::testing::TestWithParam>; cl_channel_order allChannelOrders[] = {CL_R, CL_A, CL_RG, CL_RA, CL_RGB, CL_RGBA, CL_BGRA, CL_ARGB, CL_INTENSITY, CL_LUMINANCE, CL_Rx, CL_RGx, CL_RGBx, CL_DEPTH, CL_DEPTH_STENCIL, CL_sRGB, - CL_sRGBx, CL_sRGBA, CL_sBGRA, CL_ABGR, CL_NV12_INTEL}; + CL_sRGBx, CL_sRGBA, CL_sBGRA, CL_ABGR, CL_NV12_INTEL, CL_YUYV_INTEL}; struct NullImage : public Image { using Image::imageDesc; @@ -817,7 +817,8 @@ std::tuple imageFromImageValidChannelOrderPairs[] = { std::make_tuple(CL_DEPTH, 0), std::make_tuple(CL_DEPTH_STENCIL, 0), std::make_tuple(CL_ABGR, 0), - std::make_tuple(CL_NV12_INTEL, 0)}; + std::make_tuple(CL_NV12_INTEL, 0), + std::make_tuple(CL_YUYV_INTEL, CL_RGBA)}; INSTANTIATE_TEST_CASE_P( ValidParentImageFormatTests, @@ -892,6 +893,86 @@ TEST(ImageValidatorTest, givenInvalidImage2dSizesWithoutParentObjectWhenValidate descriptor.image_width = 1; EXPECT_EQ(CL_INVALID_IMAGE_DESCRIPTOR, Image::validate(&context, {}, &surfaceFormat, &descriptor, dummyPtr)); }; +TEST(ImageValidatorTest, givenPackedYUVImage2dAsParentImageWhenValidateImageZeroSizedThenReturnsSuccess) { + NullImage image; + cl_image_desc descriptor; + MockContext context; + REQUIRE_IMAGES_OR_SKIP(&context); + + void *dummyPtr = reinterpret_cast(0x17); + ClSurfaceFormatInfo surfaceFormat = {}; + surfaceFormat.OCLImageFormat.image_channel_order = CL_RGBA; + image.imageFormat.image_channel_order = CL_YUYV_INTEL; + + descriptor.image_type = CL_MEM_OBJECT_IMAGE2D; + descriptor.image_height = 0; + descriptor.image_width = 0; + descriptor.image_row_pitch = 0; + descriptor.mem_object = ℑ + + EXPECT_EQ(CL_SUCCESS, Image::validate(&context, {}, &surfaceFormat, &descriptor, dummyPtr)); +}; +TEST(ImageValidatorTest, givenPackedYUVImage2dAsParentImageWhenValidateImageTwoChannelsThenReturnsFailure) { + NullImage image; + cl_image_desc descriptor; + MockContext context; + REQUIRE_IMAGES_OR_SKIP(&context); + + void *dummyPtr = reinterpret_cast(0x17); + ClSurfaceFormatInfo surfaceFormat = {}; + surfaceFormat.OCLImageFormat.image_channel_order = CL_RG; + image.imageFormat.image_channel_order = CL_YUYV_INTEL; + + descriptor.image_type = CL_MEM_OBJECT_IMAGE2D; + descriptor.image_height = 0; + descriptor.image_width = 0; + descriptor.image_row_pitch = 0; + descriptor.mem_object = ℑ + + EXPECT_EQ(CL_INVALID_IMAGE_DESCRIPTOR, Image::validate(&context, {}, &surfaceFormat, &descriptor, dummyPtr)); +}; +TEST(ImageValidatorTest, givenPackedYUVImage2dAsParentImageWhenValidateImageInvalidSizeThenReturnsFailure) { + NullImage image; + cl_image_desc descriptor; + MockContext context; + REQUIRE_IMAGES_OR_SKIP(&context); + + void *dummyPtr = reinterpret_cast(0x17); + ClSurfaceFormatInfo surfaceFormat = {}; + image.imageDesc.image_width = 4u; + image.imageDesc.image_height = 4u; + surfaceFormat.OCLImageFormat.image_channel_order = CL_RGBA; + image.imageFormat.image_channel_order = CL_YUYV_INTEL; + + descriptor.image_type = CL_MEM_OBJECT_IMAGE2D; + descriptor.image_height = 4; + descriptor.image_width = 1; + descriptor.image_row_pitch = 0; + descriptor.mem_object = ℑ + + EXPECT_EQ(CL_INVALID_IMAGE_DESCRIPTOR, Image::validate(&context, {}, &surfaceFormat, &descriptor, dummyPtr)); +}; +TEST(ImageValidatorTest, givenPackedYUVImage2dAsParentImageWhenValidateImageInvalidSizeAndChannelsThenReturnsFailure) { + NullImage image; + cl_image_desc descriptor; + MockContext context; + REQUIRE_IMAGES_OR_SKIP(&context); + + void *dummyPtr = reinterpret_cast(0x17); + ClSurfaceFormatInfo surfaceFormat = {}; + image.imageDesc.image_width = 4u; + image.imageDesc.image_height = 4u; + surfaceFormat.OCLImageFormat.image_channel_order = CL_RG; + image.imageFormat.image_channel_order = CL_YUYV_INTEL; + + descriptor.image_type = CL_MEM_OBJECT_IMAGE2D; + descriptor.image_height = 4; + descriptor.image_width = 1; + descriptor.image_row_pitch = 0; + descriptor.mem_object = ℑ + + EXPECT_EQ(CL_INVALID_IMAGE_DESCRIPTOR, Image::validate(&context, {}, &surfaceFormat, &descriptor, dummyPtr)); +}; TEST(ImageValidatorTest, givenNV12Image2dAsParentImageWhenValidateImageZeroSizedThenReturnsSuccess) { NullImage image; cl_image_desc descriptor; diff --git a/opencl/test/unit_test/mem_obj/packed_yuv_image_tests.cpp b/opencl/test/unit_test/mem_obj/packed_yuv_image_tests.cpp index 536c3c19d1..810e8234d7 100644 --- a/opencl/test/unit_test/mem_obj/packed_yuv_image_tests.cpp +++ b/opencl/test/unit_test/mem_obj/packed_yuv_image_tests.cpp @@ -7,6 +7,7 @@ #include "shared/source/helpers/aligned_memory.h" #include "shared/test/common/mocks/mock_device.h" +#include "shared/test/common/mocks/mock_gmm_resource_info.h" #include "shared/test/common/test_macros/test.h" #include "opencl/source/helpers/cl_memory_properties_helpers.h" @@ -114,3 +115,62 @@ INSTANTIATE_TEST_CASE_P( PackedYuvImageTests, PackedYuvImageTest, testing::ValuesIn(packedYuvChannels)); + +class PackedYUVImageTest : public testing::Test { + protected: + void SetUp() override { + imageFormat.image_channel_data_type = CL_UNORM_INT8; + imageFormat.image_channel_order = CL_YUYV_INTEL; + + imageDesc.mem_object = NULL; + imageDesc.image_array_size = 0; + imageDesc.image_depth = 1; + imageDesc.image_height = 4 * 4; // Valid values multiple of 4 + imageDesc.image_width = imageWidth; // Valid values multiple of 4 + + imageDesc.image_row_pitch = 0; + imageDesc.image_slice_pitch = 0; + imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; + imageDesc.num_mip_levels = 0; + imageDesc.num_samples = 0; + + flags = CL_MEM_HOST_NO_ACCESS; + } + + void validateImageWithFlags(cl_mem_flags flags) { + auto surfaceFormat = Image::getSurfaceFormatFromTable( + flags, &imageFormat, context.getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); + retVal = Image::validate(&context, ClMemoryPropertiesHelper::createMemoryProperties(flags, 0, 0, &context.getDevice(0)->getDevice()), + surfaceFormat, &imageDesc, nullptr); + } + + Image *createImageWithFlags(cl_mem_flags flags) { + 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); + } + + const uint32_t imageWidth = 4 * 4; + cl_int retVal = CL_SUCCESS; + MockContext context; + cl_image_format imageFormat; + cl_image_desc imageDesc; + cl_mem_flags flags; +}; + +TEST_F(PackedYUVImageTest, GivenImageViewWhenYUYVIsPassedThenSuccessIsReturned) { + std::unique_ptr image{createImageWithFlags(CL_MEM_READ_ONLY | CL_MEM_ACCESS_FLAGS_UNRESTRICTED_INTEL)}; + + ASSERT_NE(nullptr, image); + + imageFormat.image_channel_order = CL_RGBA; + imageDesc.image_width = imageWidth / 2; // YUYV image view to RGBA reads two pixel in one read Y0 U0 Y1 V0 + imageDesc.mem_object = image.get(); + + std::unique_ptr imageRGBAFromYUYV{createImageWithFlags(CL_MEM_READ_WRITE)}; + + ASSERT_NE(nullptr, imageRGBAFromYUYV); + + EXPECT_EQ(imageRGBAFromYUYV->getImageDesc().image_width, imageDesc.image_width); +} diff --git a/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp b/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp index fa6ceaf46b..5a9fa9611c 100644 --- a/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp +++ b/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp @@ -598,12 +598,19 @@ TEST_F(VaSharingTests, givenValidSurfaceWithPlaneSetWhenApplyPlaneSettingsThenPr } TEST_F(VaSharingTests, givenValidPackedFormatWhenApplyPackedOptionsThenSurfaceFormatIsSet) { - SharedSurfaceInfo surfaceInfo{}; - surfaceInfo.imageFourcc = VA_FOURCC_YUY2; + SharedSurfaceInfo surfaceInfoYUY2{}; + surfaceInfoYUY2.imageFourcc = VA_FOURCC_YUY2; - VASurface::applyPackedOptions(surfaceInfo); + VASurface::applyPackedOptions(surfaceInfoYUY2); - EXPECT_EQ(surfaceInfo.imgInfo.surfaceFormat->GMMSurfaceFormat, GMM_FORMAT_YCRCB_NORMAL); + EXPECT_EQ(surfaceInfoYUY2.imgInfo.surfaceFormat->GMMSurfaceFormat, GMM_FORMAT_YCRCB_NORMAL); + + SharedSurfaceInfo surfaceInfoY210{}; + surfaceInfoY210.imageFourcc = VA_FOURCC_Y210; + + VASurface::applyPackedOptions(surfaceInfoY210); + + EXPECT_EQ(surfaceInfoY210.imgInfo.surfaceFormat->GMMSurfaceFormat, GMM_FORMAT_Y210); } TEST_F(VaSharingTests, givenInvalidPlaneWhenVaSurfaceIsCreatedAndNotRGBPThenUnrecoverableIsCalled) { @@ -1294,10 +1301,12 @@ TEST(VaSurface, givenValidPlaneAndFlagsWhenValidatingInputsThenTrueIsReturned) { EXPECT_TRUE(VASurface::validate(CL_MEM_READ_ONLY, plane)); EXPECT_TRUE(VASurface::validate(CL_MEM_WRITE_ONLY, plane)); EXPECT_TRUE(VASurface::validate(CL_MEM_READ_WRITE, plane)); + EXPECT_TRUE(VASurface::validate(CL_MEM_READ_ONLY | CL_MEM_ACCESS_FLAGS_UNRESTRICTED_INTEL, plane)); + EXPECT_TRUE(VASurface::validate(CL_MEM_ACCESS_FLAGS_UNRESTRICTED_INTEL, plane)); } } -TEST(VaSurface, givenInValidPlaneOrFlagsWhenValidatingInputsThenTrueIsReturned) { +TEST(VaSurface, givenInvalidPlaneOrFlagsWhenValidatingInputsThenTrueIsReturned) { cl_uint plane = 2; EXPECT_FALSE(VASurface::validate(CL_MEM_READ_ONLY, plane)); EXPECT_FALSE(VASurface::validate(CL_MEM_USE_HOST_PTR, 0));