diff --git a/runtime/kernel/CMakeLists.txt b/runtime/kernel/CMakeLists.txt index b3da184644..d42d09253e 100644 --- a/runtime/kernel/CMakeLists.txt +++ b/runtime/kernel/CMakeLists.txt @@ -21,6 +21,8 @@ set(RUNTIME_SRCS_KERNEL ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_kernel_info.h + ${CMAKE_CURRENT_SOURCE_DIR}/image_transformer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/image_transformer.h ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel.h ${CMAKE_CURRENT_SOURCE_DIR}/kernel.inl diff --git a/runtime/kernel/image_transformer.cpp b/runtime/kernel/image_transformer.cpp new file mode 100644 index 0000000000..eec1cdfdf2 --- /dev/null +++ b/runtime/kernel/image_transformer.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "runtime/helpers/ptr_math.h" +#include "runtime/kernel/image_transformer.h" +#include "runtime/mem_obj/image.h" +#include "runtime/program/kernel_info.h" + +namespace OCLRT { +void ImageTransformer::registerImage3d(uint32_t argIndex) { + if (std::find(argIndexes.begin(), argIndexes.end(), argIndex) == argIndexes.end()) { + argIndexes.push_back(argIndex); + } +} +void ImageTransformer::transformImagesTo2dArray(const KernelInfo &kernelInfo, const std::vector &kernelArguments, void *ssh) { + for (auto const &argIndex : argIndexes) { + if (kernelInfo.kernelArgInfo.at(argIndex).isTransformable) { + auto clMemObj = *(static_cast(kernelArguments.at(argIndex).value)); + auto image = castToObjectOrAbort(clMemObj); + auto surfaceState = ptrOffset(ssh, kernelInfo.kernelArgInfo.at(argIndex).offsetHeap); + image->transformImage3dTo2dArray(surfaceState); + } + } + transformed = true; +} +void ImageTransformer::transformImagesTo3d(const KernelInfo &kernelInfo, const std::vector &kernelArguments, void *ssh) { + for (auto const &argIndex : argIndexes) { + auto clMemObj = *(static_cast(kernelArguments.at(argIndex).value)); + auto image = castToObjectOrAbort(clMemObj); + auto surfaceState = ptrOffset(ssh, kernelInfo.kernelArgInfo.at(argIndex).offsetHeap); + image->transformImage2dArrayTo3d(surfaceState); + } + transformed = false; +} +bool ImageTransformer::didTransform() const { + return transformed; +} +bool ImageTransformer::hasRegisteredImages3d() const { + return !argIndexes.empty(); +} +} diff --git a/runtime/kernel/image_transformer.h b/runtime/kernel/image_transformer.h new file mode 100644 index 0000000000..d0d0f4c148 --- /dev/null +++ b/runtime/kernel/image_transformer.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once +#include "runtime/kernel/kernel.h" + +namespace OCLRT { + +class ImageTransformer { + public: + void registerImage3d(uint32_t argIndex); + void transformImagesTo2dArray(const KernelInfo &kernelInfo, const std::vector &kernelArguments, void *ssh); + void transformImagesTo3d(const KernelInfo &kernelInfo, const std::vector &kernelArguments, void *ssh); + bool didTransform() const; + bool hasRegisteredImages3d() const; + + protected: + bool transformed = false; + std::vector argIndexes; +}; +} diff --git a/runtime/kernel/kernel.cpp b/runtime/kernel/kernel.cpp index 91063d234c..bf5155fdfc 100644 --- a/runtime/kernel/kernel.cpp +++ b/runtime/kernel/kernel.cpp @@ -41,6 +41,7 @@ #include "runtime/mem_obj/buffer.h" #include "runtime/mem_obj/image.h" #include "runtime/mem_obj/pipe.h" +#include "runtime/kernel/image_transformer.h" #include "runtime/memory_manager/memory_manager.h" #include "runtime/memory_manager/surface.h" #include "runtime/os_interface/debug_settings_manager.h" @@ -105,6 +106,7 @@ Kernel::Kernel(Program *programArg, const KernelInfo &kernelInfoArg, const Devic kernelReflectionSurface(nullptr), usingSharedObjArgs(false) { program->retain(); + imageTransformer.reset(new ImageTransformer); } Kernel::~Kernel() { @@ -773,6 +775,7 @@ cl_int Kernel::setArg(uint32_t argIndex, size_t argSize, const void *argVal) { patchedArgumentsNum++; kernelArguments[argIndex].isPatched = true; } + resolveArgs(); } return retVal; } @@ -1210,6 +1213,10 @@ cl_int Kernel::setArgImageWithMipLevel(uint32_t argIndex, auto &imageDesc = pImage->getImageDesc(); auto &imageFormat = pImage->getImageFormat(); + if (imageDesc.image_type == CL_MEM_OBJECT_IMAGE3D) { + imageTransformer->registerImage3d(argIndex); + } + patch(imageDesc.image_width, crossThreadData, kernelArgInfo.offsetImgWidth); patch(imageDesc.image_height, crossThreadData, kernelArgInfo.offsetImgHeight); patch(imageDesc.image_depth, crossThreadData, kernelArgInfo.offsetImgDepth); @@ -2045,4 +2052,31 @@ cl_int Kernel::checkCorrectImageAccessQualifier(cl_uint argIndex, } return CL_SUCCESS; } + +void Kernel::resolveArgs() { + if (!Kernel::isPatched() || !imageTransformer->hasRegisteredImages3d() || !canTransformImages()) + return; + bool canTransformImageTo2dArray = true; + for (uint32_t i = 0; i < patchedArgumentsNum; i++) { + if (kernelInfo.kernelArgInfo.at(i).isSampler) { + auto clSamplerObj = *(static_cast(kernelArguments.at(i).value)); + auto sampler = castToObjectOrAbort(clSamplerObj); + if (sampler->isTransformable()) { + canTransformImageTo2dArray = true; + } else { + canTransformImageTo2dArray = false; + break; + } + } + } + if (canTransformImageTo2dArray) { + imageTransformer->transformImagesTo2dArray(kernelInfo, kernelArguments, getSurfaceStateHeap()); + } else if (imageTransformer->didTransform()) { + imageTransformer->transformImagesTo3d(kernelInfo, kernelArguments, getSurfaceStateHeap()); + } +} + +bool Kernel::canTransformImages() const { + return device.getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE; +} } // namespace OCLRT diff --git a/runtime/kernel/kernel.h b/runtime/kernel/kernel.h index d50c9704a9..cb51cf848b 100644 --- a/runtime/kernel/kernel.h +++ b/runtime/kernel/kernel.h @@ -35,6 +35,7 @@ namespace OCLRT { struct CompletionStamp; class GraphicsAllocation; +class ImageTransformer; class Surface; class PrintfHandler; @@ -126,6 +127,7 @@ class Kernel : public BaseObject<_cl_kernel> { cl_int cloneKernel(Kernel *pSourceKernel); + MOCKABLE_VIRTUAL bool canTransformImages() const; MOCKABLE_VIRTUAL bool isPatched() const; // API entry points @@ -455,6 +457,8 @@ class Kernel : public BaseObject<_cl_kernel> { void patchBlocksCurbeWithConstantValues(); + void resolveArgs(); + Program *program; Context *context; const Device &device; @@ -481,5 +485,6 @@ class Kernel : public BaseObject<_cl_kernel> { uint32_t patchedArgumentsNum = 0; std::vector patchInfoDataList; + std::unique_ptr imageTransformer; }; } // namespace OCLRT diff --git a/runtime/mem_obj/image.h b/runtime/mem_obj/image.h index 4ae2f83ded..2d54c7ad52 100644 --- a/runtime/mem_obj/image.h +++ b/runtime/mem_obj/image.h @@ -182,6 +182,9 @@ class Image : public MemObj { const McsSurfaceInfo &getMcsSurfaceInfo() { return mcsSurfaceInfo; } size_t calculateOffsetForMapping(const MemObjOffsetArray &origin) const override; + virtual void transformImage2dArrayTo3d(void *memory) = 0; + virtual void transformImage3dTo2dArray(void *memory) = 0; + const bool isTiledImage; protected: @@ -272,7 +275,8 @@ class ImageHw : public Image { void setMediaSurfaceRotation(void *memory) override; void setSurfaceMemoryObjectControlStateIndexToMocsTable(void *memory, uint32_t value) override; void appendSurfaceStateParams(RENDER_SURFACE_STATE *surfaceState); - + void transformImage2dArrayTo3d(void *memory) override; + void transformImage3dTo2dArray(void *memory) override; static Image *create(Context *context, cl_mem_flags flags, size_t size, diff --git a/runtime/mem_obj/image.inl b/runtime/mem_obj/image.inl index 6c94aaaf26..989980934d 100644 --- a/runtime/mem_obj/image.inl +++ b/runtime/mem_obj/image.inl @@ -250,4 +250,21 @@ void ImageHw::setMediaImageArg(void *memory) { surfaceState->setSurfaceBaseAddress(getGraphicsAllocation()->getGpuAddress() + this->surfaceOffsets.offset); } + +template +void ImageHw::transformImage2dArrayTo3d(void *memory) { + DEBUG_BREAK_IF(imageDesc.image_type != CL_MEM_OBJECT_IMAGE3D); + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + auto surfaceState = reinterpret_cast(memory); + surfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D); + surfaceState->setSurfaceArray(false); +} +template +void ImageHw::transformImage3dTo2dArray(void *memory) { + DEBUG_BREAK_IF(imageDesc.image_type != CL_MEM_OBJECT_IMAGE3D); + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + auto surfaceState = reinterpret_cast(memory); + surfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D); + surfaceState->setSurfaceArray(true); +} } // namespace OCLRT diff --git a/runtime/program/kernel_arg_info.h b/runtime/program/kernel_arg_info.h index 1e49264ee5..29d9fc4cb2 100644 --- a/runtime/program/kernel_arg_info.h +++ b/runtime/program/kernel_arg_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -69,6 +69,7 @@ struct KernelArgInfo { uint32_t offsetBufferOffset = undefinedOffset; bool needPatch = false; + bool isTransformable = false; cl_kernel_arg_access_qualifier accessQualifier = CL_KERNEL_ARG_ACCESS_NONE; cl_kernel_arg_address_qualifier addressQualifier = CL_KERNEL_ARG_ADDRESS_GLOBAL; diff --git a/runtime/program/kernel_info.cpp b/runtime/program/kernel_info.cpp index bc88278519..e619509c21 100644 --- a/runtime/program/kernel_info.cpp +++ b/runtime/program/kernel_info.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -303,6 +303,8 @@ void KernelInfo::storeKernelArgument( kernelArgInfo[argNum].accessQualifier = pImageMemObjKernelArg->Writeable ? CL_KERNEL_ARG_ACCESS_READ_WRITE : CL_KERNEL_ARG_ACCESS_READ_ONLY; + + kernelArgInfo[argNum].isTransformable = pImageMemObjKernelArg->Transformable != 0; patchInfo.imageMemObjKernelArgs.push_back(pImageMemObjKernelArg); } diff --git a/runtime/sampler/sampler.cpp b/runtime/sampler/sampler.cpp index 3792dde277..343c2ef5ad 100644 --- a/runtime/sampler/sampler.cpp +++ b/runtime/sampler/sampler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -187,4 +187,11 @@ cl_int Sampler::getInfo(cl_sampler_info paramName, size_t paramValueSize, return retVal; } + +bool Sampler::isTransformable() const { + return addressingMode == CL_ADDRESS_CLAMP_TO_EDGE && + filterMode == CL_FILTER_NEAREST && + normalizedCoordinates == CL_FALSE; +} + } // namespace OCLRT diff --git a/runtime/sampler/sampler.h b/runtime/sampler/sampler.h index 9916f48758..17f58e28b4 100644 --- a/runtime/sampler/sampler.h +++ b/runtime/sampler/sampler.h @@ -52,6 +52,7 @@ class Sampler : public BaseObject<_cl_sampler> { virtual void setArg(void *memory) = 0; static size_t getSamplerStateSize(const HardwareInfo &hwInfo); + bool isTransformable() const; Sampler(Context *context, cl_bool normalizedCoordinates, diff --git a/unit_tests/gen8/CMakeLists.txt b/unit_tests/gen8/CMakeLists.txt index d5af295d69..6d0d4fca22 100644 --- a/unit_tests/gen8/CMakeLists.txt +++ b/unit_tests/gen8/CMakeLists.txt @@ -26,6 +26,7 @@ if(TESTS_GEN8) ${CMAKE_CURRENT_SOURCE_DIR}/enqueue_media_kernel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw_helper_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/image_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/kernel_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sampler_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/scheduler_dispatch_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_device_caps.cpp diff --git a/unit_tests/gen8/kernel_tests.cpp b/unit_tests/gen8/kernel_tests.cpp new file mode 100644 index 0000000000..0830b0c91b --- /dev/null +++ b/unit_tests/gen8/kernel_tests.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "unit_tests/fixtures/device_fixture.h" +#include "unit_tests/mocks/mock_kernel.h" +#include "test.h" + +using namespace OCLRT; + +using Gen8KernelTest = Test; +GEN8TEST_F(Gen8KernelTest, givenKernelWhenCanTransformImagesIsCalledThenReturnsFalse) { + MockKernelWithInternals mockKernel(*pDevice); + auto retVal = mockKernel.mockKernel->Kernel::canTransformImages(); + EXPECT_FALSE(retVal); +} diff --git a/unit_tests/gen9/CMakeLists.txt b/unit_tests/gen9/CMakeLists.txt index 4e86e81a05..880ee05924 100644 --- a/unit_tests/gen9/CMakeLists.txt +++ b/unit_tests/gen9/CMakeLists.txt @@ -26,6 +26,7 @@ if(TESTS_GEN9) ${CMAKE_CURRENT_SOURCE_DIR}/enqueue_media_kernel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw_helper_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/image_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/kernel_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sampler_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sip_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_device_caps.cpp diff --git a/unit_tests/gen9/kernel_tests.cpp b/unit_tests/gen9/kernel_tests.cpp new file mode 100644 index 0000000000..61ba210130 --- /dev/null +++ b/unit_tests/gen9/kernel_tests.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "unit_tests/fixtures/device_fixture.h" +#include "unit_tests/mocks/mock_kernel.h" +#include "test.h" + +using namespace OCLRT; + +using Gen9KernelTest = Test; +GEN9TEST_F(Gen9KernelTest, givenKernelWhenCanTransformImagesIsCalledThenReturnsTrue) { + MockKernelWithInternals mockKernel(*pDevice); + auto retVal = mockKernel.mockKernel->Kernel::canTransformImages(); + EXPECT_TRUE(retVal); +} diff --git a/unit_tests/helpers/mipmap_tests.cpp b/unit_tests/helpers/mipmap_tests.cpp index cbff368e68..d8442b7760 100644 --- a/unit_tests/helpers/mipmap_tests.cpp +++ b/unit_tests/helpers/mipmap_tests.cpp @@ -139,6 +139,8 @@ struct MockImage : public OCLRT::Image { } void setSurfaceMemoryObjectControlStateIndexToMocsTable(void *memory, uint32_t value) override { } + void transformImage2dArrayTo3d(void *memory) override {} + void transformImage3dTo2dArray(void *memory) override {} }; TEST(MipmapHelper, givenImageWithoutMipLevelsWhenIsMipMappedIsCalledThenFalseIsReturned) { diff --git a/unit_tests/kernel/CMakeLists.txt b/unit_tests/kernel/CMakeLists.txt index 04760dd1d3..d100e15e13 100644 --- a/unit_tests/kernel/CMakeLists.txt +++ b/unit_tests/kernel/CMakeLists.txt @@ -21,6 +21,7 @@ set(IGDRCL_SRCS_tests_kernel ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/clone_kernel_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/image_transformer_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel_accelerator_arg_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel_arg_buffer_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel_arg_buffer_fixture.h @@ -36,6 +37,7 @@ set(IGDRCL_SRCS_tests_kernel ${CMAKE_CURRENT_SOURCE_DIR}/kernel_slm_arg_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel_slm_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/kernel_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/kernel_transformable_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/debug_kernel_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/parent_kernel_tests.cpp ) diff --git a/unit_tests/kernel/image_transformer_tests.cpp b/unit_tests/kernel/image_transformer_tests.cpp new file mode 100644 index 0000000000..7bae07d96f --- /dev/null +++ b/unit_tests/kernel/image_transformer_tests.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "runtime/kernel/image_transformer.h" +#include "runtime/program/kernel_info.h" +#include "unit_tests/fixtures/image_fixture.h" +#include "test.h" + +using namespace OCLRT; + +class ImageTransformerTest : public ::testing::Test { + public: + void SetUp() override { + using SimpleKernelArgInfo = Kernel::SimpleKernelArgInfo; + pKernelInfo.reset(KernelInfo::create()); + pKernelInfo->kernelArgInfo.resize(2); + pKernelInfo->kernelArgInfo[0].isTransformable = true; + pKernelInfo->kernelArgInfo[0].offsetHeap = firstImageOffset; + pKernelInfo->kernelArgInfo[1].isTransformable = true; + pKernelInfo->kernelArgInfo[1].offsetHeap = secondImageOffset; + image1.reset(Image3dHelper<>::create(&context)); + image2.reset(Image3dHelper<>::create(&context)); + SimpleKernelArgInfo imageArg1; + SimpleKernelArgInfo imageArg2; + clImage1 = static_cast(image2.get()); + clImage2 = static_cast(image2.get()); + imageArg1.value = &clImage1; + imageArg2.value = &clImage2; + kernelArguments.push_back(imageArg1); + kernelArguments.push_back(imageArg2); + } + const int firstImageOffset = 0x20; + const int secondImageOffset = 0x40; + std::unique_ptr pKernelInfo; + ImageTransformer imageTransformer; + MockContext context; + std::unique_ptr image1; + std::unique_ptr image2; + cl_mem clImage1; + cl_mem clImage2; + char ssh[0x80]; + std::vector kernelArguments; +}; + +TEST_F(ImageTransformerTest, givenImageTransformerWhenRegisterImage3dThenTransformerHasRegisteredImages3d) { + bool retVal; + retVal = imageTransformer.hasRegisteredImages3d(); + EXPECT_FALSE(retVal); + imageTransformer.registerImage3d(0); + retVal = imageTransformer.hasRegisteredImages3d(); + EXPECT_TRUE(retVal); +} + +TEST_F(ImageTransformerTest, givenImageTransformerWhenTransformToImage2dArrayThenTransformerDidTransform) { + bool retVal; + retVal = imageTransformer.didTransform(); + EXPECT_FALSE(retVal); + imageTransformer.transformImagesTo2dArray(*pKernelInfo, kernelArguments, nullptr); + retVal = imageTransformer.didTransform(); + EXPECT_TRUE(retVal); +} + +TEST_F(ImageTransformerTest, givenImageTransformerWhenTransformToImage3dThenTransformerDidNotTransform) { + bool retVal; + retVal = imageTransformer.didTransform(); + EXPECT_FALSE(retVal); + imageTransformer.transformImagesTo2dArray(*pKernelInfo, kernelArguments, nullptr); + imageTransformer.transformImagesTo3d(*pKernelInfo, kernelArguments, nullptr); + retVal = imageTransformer.didTransform(); + EXPECT_FALSE(retVal); +} +HWTEST_F(ImageTransformerTest, givenImageTransformerWhenTransformToImage2dArrayThenTransformOnlyRegisteredImages) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + firstSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + secondSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + firstSurfaceState->setSurfaceArray(false); + secondSurfaceState->setSurfaceArray(false); + + imageTransformer.registerImage3d(1); + imageTransformer.transformImagesTo2dArray(*pKernelInfo, kernelArguments, ssh); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL, firstSurfaceState->getSurfaceType()); + EXPECT_FALSE(firstSurfaceState->getSurfaceArray()); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, secondSurfaceState->getSurfaceType()); + EXPECT_TRUE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(ImageTransformerTest, givenImageTransformerWhenTransformToImage2dArrayThenTransformOnlyTransformableImages) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + pKernelInfo->kernelArgInfo[1].isTransformable = false; + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + firstSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + secondSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + firstSurfaceState->setSurfaceArray(false); + secondSurfaceState->setSurfaceArray(false); + + imageTransformer.registerImage3d(0); + imageTransformer.registerImage3d(1); + imageTransformer.transformImagesTo2dArray(*pKernelInfo, kernelArguments, ssh); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, firstSurfaceState->getSurfaceType()); + EXPECT_TRUE(firstSurfaceState->getSurfaceArray()); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(ImageTransformerTest, givenImageTransformerWhenTransformToImage3dhenTransformAllRegisteredImages) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + pKernelInfo->kernelArgInfo[1].isTransformable = false; + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + firstSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + secondSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + firstSurfaceState->setSurfaceArray(true); + secondSurfaceState->setSurfaceArray(true); + + imageTransformer.registerImage3d(0); + imageTransformer.registerImage3d(1); + imageTransformer.transformImagesTo3d(*pKernelInfo, kernelArguments, ssh); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, firstSurfaceState->getSurfaceType()); + EXPECT_FALSE(firstSurfaceState->getSurfaceArray()); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(ImageTransformerTest, givenImageTransformerWhenTransformToImage3dhenTransformOnlyRegisteredImages) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + pKernelInfo->kernelArgInfo[1].isTransformable = false; + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + firstSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + secondSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + firstSurfaceState->setSurfaceArray(true); + secondSurfaceState->setSurfaceArray(true); + + imageTransformer.registerImage3d(1); + imageTransformer.transformImagesTo3d(*pKernelInfo, kernelArguments, ssh); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL, firstSurfaceState->getSurfaceType()); + EXPECT_TRUE(firstSurfaceState->getSurfaceArray()); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +class MockImageTransformer : public ImageTransformer { + public: + using ImageTransformer::argIndexes; +}; +TEST(ImageTransformerRegisterImageTest, givenImageTransformerWhenRegisterTheSameImageTwiceThenAppendOnlyOne) { + MockImageTransformer transformer; + EXPECT_EQ(0u, transformer.argIndexes.size()); + transformer.registerImage3d(0); + EXPECT_EQ(1u, transformer.argIndexes.size()); + transformer.registerImage3d(0); + EXPECT_EQ(1u, transformer.argIndexes.size()); + transformer.registerImage3d(1); + EXPECT_EQ(2u, transformer.argIndexes.size()); +} diff --git a/unit_tests/kernel/kernel_transformable_tests.cpp b/unit_tests/kernel/kernel_transformable_tests.cpp new file mode 100644 index 0000000000..674d71a184 --- /dev/null +++ b/unit_tests/kernel/kernel_transformable_tests.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2018, Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "runtime/program/kernel_info.h" +#include "runtime/sampler/sampler.h" +#include "unit_tests/fixtures/device_fixture.h" +#include "unit_tests/fixtures/image_fixture.h" +#include "unit_tests/mocks/mock_context.h" +#include "unit_tests/mocks/mock_kernel.h" +#include "unit_tests/mocks/mock_sampler.h" + +#include "test.h" +#include + +using namespace OCLRT; + +class KernelTransformableTest : public ::testing::Test { + public: + void SetUp() override { + pKernelInfo.reset(KernelInfo::create()); + KernelArgPatchInfo kernelArgPatchInfo; + + kernelHeader.SurfaceStateHeapSize = sizeof(surfaceStateHeap); + pKernelInfo->heapInfo.pSsh = surfaceStateHeap; + pKernelInfo->heapInfo.pKernelHeader = &kernelHeader; + pKernelInfo->usesSsh = true; + + pKernelInfo->kernelArgInfo.resize(4); + pKernelInfo->kernelArgInfo[3].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo); + pKernelInfo->kernelArgInfo[2].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo); + pKernelInfo->kernelArgInfo[1].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo); + pKernelInfo->kernelArgInfo[0].kernelArgPatchInfoVector.push_back(kernelArgPatchInfo); + + pKernelInfo->kernelArgInfo[0].offsetHeap = 0x0; + pKernelInfo->kernelArgInfo[0].isSampler = true; + pKernelInfo->kernelArgInfo[1].offsetHeap = 0x0; + pKernelInfo->kernelArgInfo[1].isSampler = true; + pKernelInfo->kernelArgInfo[2].offsetHeap = firstImageOffset; + pKernelInfo->kernelArgInfo[2].isImage = true; + pKernelInfo->kernelArgInfo[3].offsetHeap = secondImageOffset; + pKernelInfo->kernelArgInfo[3].isImage = true; + pKernelInfo->argumentsToPatchNum = 4; + + pKernel.reset(new MockKernel(&program, *pKernelInfo, *context.getDevice(0))); + ASSERT_EQ(CL_SUCCESS, pKernel->initialize()); + + pKernel->setKernelArgHandler(0, &Kernel::setArgSampler); + pKernel->setKernelArgHandler(1, &Kernel::setArgSampler); + pKernel->setKernelArgHandler(2, &Kernel::setArgImage); + pKernel->setKernelArgHandler(3, &Kernel::setArgImage); + } + + Sampler *createTransformableSampler() { + return new MockSampler(nullptr, CL_FALSE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST); + } + Sampler *createNonTransformableSampler() { + return new MockSampler(nullptr, CL_TRUE, CL_ADDRESS_CLAMP_TO_EDGE, CL_FILTER_NEAREST); + } + + const int firstImageOffset = 0x20; + const int secondImageOffset = 0x40; + + cl_int retVal = CL_SUCCESS; + MockContext context; + MockProgram program; + std::unique_ptr pKernel; + std::unique_ptr pKernelInfo; + + std::unique_ptr image; + std::unique_ptr sampler; + SKernelBinaryHeaderCommon kernelHeader; + char surfaceStateHeap[0x80]; +}; + +HWTEST_F(KernelTransformableTest, givenKernelThatCannotTranformImagesWithTwoTransformableImagesAndTwoTransformableSamplersWhenAllArgsAreSetThenImagesAreNotTransformed) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + sampler.reset(createTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + pKernel->canKernelTransformImages = false; + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, firstSurfaceState->getSurfaceType()); + EXPECT_FALSE(firstSurfaceState->getSurfaceArray()); + + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithTwoTransformableImagesAndTwoTransformableSamplersWhenAllArgsAreSetThenImagesAreTransformed) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + sampler.reset(createTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, firstSurfaceState->getSurfaceType()); + EXPECT_TRUE(firstSurfaceState->getSurfaceArray()); + + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, secondSurfaceState->getSurfaceType()); + EXPECT_TRUE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithTwoTransformableImagesAndTwoTransformableSamplersWhenAnyArgIsResetThenImagesAreTransformedAgain) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + sampler.reset(createTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + firstSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + secondSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + + pKernelInfo->kernelArgInfo[3].isTransformable = false; + pKernel->setArg(3, sizeof(clImage), &clImage); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, firstSurfaceState->getSurfaceType()); + EXPECT_TRUE(firstSurfaceState->getSurfaceArray()); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithOneTransformableImageAndTwoTransformableSamplersWhenAnyArgIsResetThenOnlyOneImageIsTransformed) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + sampler.reset(createTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = false; + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, firstSurfaceState->getSurfaceType()); + EXPECT_TRUE(firstSurfaceState->getSurfaceArray()); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithImages2dAndTwoTransformableSamplersWhenAnyArgIsResetThenImagesAreNotTransformed) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image2dHelper<>::create(&context)); + sampler.reset(createTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, firstSurfaceState->getSurfaceType()); + EXPECT_FALSE(firstSurfaceState->getSurfaceArray()); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithTwoTransformableImagesAndTwoTransformableSamplersWhenChangeSamplerToNontransformableThenImagesAreTransformedTo3d) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + sampler.reset(createTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + std::unique_ptr sampler2(createNonTransformableSampler()); + cl_sampler clSampler2 = sampler2.get(); + pKernel->setArg(1, sizeof(clSampler2), &clSampler2); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, firstSurfaceState->getSurfaceType()); + EXPECT_FALSE(firstSurfaceState->getSurfaceArray()); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_3D, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithNonTransformableSamplersWhenResetSamplerWithNontransformableThenImagesNotChangedAgain) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + sampler.reset(createNonTransformableSampler()); + cl_mem clImage = image.get(); + cl_sampler clSampler = sampler.get(); + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + pKernel->setArg(1, sizeof(clSampler), &clSampler); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + firstSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + secondSurfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL); + + pKernel->setArg(0, sizeof(clSampler), &clSampler); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL, firstSurfaceState->getSurfaceType()); + EXPECT_FALSE(firstSurfaceState->getSurfaceArray()); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_NULL, secondSurfaceState->getSurfaceType()); + EXPECT_FALSE(secondSurfaceState->getSurfaceArray()); +} + +HWTEST_F(KernelTransformableTest, givenKernelWithoutSamplersAndTransformableImagesWhenResolveKernelThenImagesAreTransformed) { + using RENDER_SURFACE_STATE = typename FamilyType::RENDER_SURFACE_STATE; + using SURFACE_TYPE = typename RENDER_SURFACE_STATE::SURFACE_TYPE; + + image.reset(Image3dHelper<>::create(&context)); + cl_mem clImage = image.get(); + + pKernelInfo->kernelArgInfo[0].isSampler = false; + pKernelInfo->kernelArgInfo[0].isImage = true; + pKernelInfo->kernelArgInfo[1].isSampler = false; + pKernelInfo->kernelArgInfo[1].isImage = true; + pKernelInfo->kernelArgInfo[2].isTransformable = true; + pKernelInfo->kernelArgInfo[3].isTransformable = true; + + pKernel->setKernelArgHandler(0, &Kernel::setArgImage); + pKernel->setKernelArgHandler(1, &Kernel::setArgImage); + + pKernel->setArg(0, sizeof(clImage), &clImage); + pKernel->setArg(1, sizeof(clImage), &clImage); + pKernel->setArg(2, sizeof(clImage), &clImage); + pKernel->setArg(3, sizeof(clImage), &clImage); + + auto ssh = pKernel->getSurfaceStateHeap(); + + auto firstSurfaceState = reinterpret_cast(ptrOffset(ssh, firstImageOffset)); + auto secondSurfaceState = reinterpret_cast(ptrOffset(ssh, secondImageOffset)); + + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, firstSurfaceState->getSurfaceType()); + EXPECT_TRUE(firstSurfaceState->getSurfaceArray()); + EXPECT_EQ(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D, secondSurfaceState->getSurfaceType()); + EXPECT_TRUE(secondSurfaceState->getSurfaceArray()); +} diff --git a/unit_tests/mem_obj/image_tests.cpp b/unit_tests/mem_obj/image_tests.cpp index a07f42a0d2..abbb590405 100644 --- a/unit_tests/mem_obj/image_tests.cpp +++ b/unit_tests/mem_obj/image_tests.cpp @@ -34,7 +34,7 @@ #include "unit_tests/helpers/memory_management.h" #include "unit_tests/mocks/mock_context.h" #include "unit_tests/mocks/mock_memory_manager.h" -#include "gtest/gtest.h" +#include "unit_tests/gen_common/test.h" using namespace OCLRT; @@ -1107,3 +1107,32 @@ INSTANTIATE_TEST_CASE_P(HasSlices, 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 = RENDER_SURFACE_STATE::sInit(); + 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 = RENDER_SURFACE_STATE::sInit(); + 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()); +} diff --git a/unit_tests/mocks/mock_kernel.cpp b/unit_tests/mocks/mock_kernel.cpp index 527dfdb1f6..b841951fe6 100644 --- a/unit_tests/mocks/mock_kernel.cpp +++ b/unit_tests/mocks/mock_kernel.cpp @@ -55,6 +55,10 @@ bool MockKernel::isPatched() const { return true; } +bool MockKernel::canTransformImages() const { + return canKernelTransformImages; +} + void MockKernel::makeResident(CommandStreamReceiver &commandStreamReceiver) { makeResidentCalls++; Kernel::makeResident(commandStreamReceiver); diff --git a/unit_tests/mocks/mock_kernel.h b/unit_tests/mocks/mock_kernel.h index ce7453c27a..fa98cfb5f2 100644 --- a/unit_tests/mocks/mock_kernel.h +++ b/unit_tests/mocks/mock_kernel.h @@ -153,6 +153,8 @@ class MockKernel : public Kernel { } bool isPatched() const override; + bool canTransformImages() const override; + //////////////////////////////////////////////////////////////////////////////// void setCrossThreadData(const void *crossThreadDataPattern, uint32_t newCrossThreadDataSize) { if ((Kernel::crossThreadData != nullptr) && (Kernel::crossThreadData != mockCrossThreadData.data())) { @@ -240,6 +242,8 @@ class MockKernel : public Kernel { uint32_t makeResidentCalls = 0; uint32_t getResidencyCalls = 0; + bool canKernelTransformImages = true; + protected: KernelInfo *kernelInfoAllocated = nullptr; }; diff --git a/unit_tests/program/kernel_info_tests.cpp b/unit_tests/program/kernel_info_tests.cpp index 20282cff8a..fdbd4666ba 100644 --- a/unit_tests/program/kernel_info_tests.cpp +++ b/unit_tests/program/kernel_info_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ #include "runtime/program/kernel_info.h" #include "gtest/gtest.h" #include +#include using OCLRT::KernelInfo; using OCLRT::SPatchStatelessConstantMemoryObjectKernelArgument; @@ -212,3 +213,27 @@ TEST(KernelInfo_resolveKernelInfo, complexArgumentType) { delete pKernelInfo; } + +TEST(KernelInfo, givenKernelInfoWhenStoreTransformableArgThenArgInfoIsTransformable) { + uint32_t argumentNumber = 1; + std::unique_ptr kernelInfo(KernelInfo::create()); + SPatchImageMemoryObjectKernelArgument arg; + arg.ArgumentNumber = argumentNumber; + arg.Transformable = true; + + kernelInfo->storeKernelArgument(&arg); + const auto &argInfo = kernelInfo->kernelArgInfo[argumentNumber]; + EXPECT_TRUE(argInfo.isTransformable); +} + +TEST(KernelInfo, givenKernelInfoWhenStoreNonTransformableArgThenArgInfoIsNotTransformable) { + uint32_t argumentNumber = 1; + std::unique_ptr kernelInfo(KernelInfo::create()); + SPatchImageMemoryObjectKernelArgument arg; + arg.ArgumentNumber = argumentNumber; + arg.Transformable = false; + + kernelInfo->storeKernelArgument(&arg); + const auto &argInfo = kernelInfo->kernelArgInfo[argumentNumber]; + EXPECT_FALSE(argInfo.isTransformable); +} diff --git a/unit_tests/sampler/sampler_tests.cpp b/unit_tests/sampler/sampler_tests.cpp index b7b1a2acd9..21d475d160 100644 --- a/unit_tests/sampler/sampler_tests.cpp +++ b/unit_tests/sampler/sampler_tests.cpp @@ -104,3 +104,29 @@ INSTANTIATE_TEST_CASE_P(Sampler, ::testing::ValuesIn(normalizedCoordModes), ::testing::ValuesIn(addressingModes), ::testing::ValuesIn(filterModes))); + +typedef ::testing::TestWithParam> TransformableSamplerTest; + +TEST_P(TransformableSamplerTest, givenSamplerWhenHasProperParametersThenIsTransformable) { + bool expectedRetVal; + bool retVal; + cl_bool normalizedCoords; + cl_addressing_mode addressingMode; + cl_filter_mode filterMode; + std::tie(normalizedCoords, addressingMode, filterMode) = GetParam(); + + expectedRetVal = addressingMode == CL_ADDRESS_CLAMP_TO_EDGE && + filterMode == CL_FILTER_NEAREST && + normalizedCoords == CL_FALSE; + + MockSampler sampler(nullptr, normalizedCoords, addressingMode, filterMode); + + retVal = sampler.isTransformable(); + EXPECT_EQ(expectedRetVal, retVal); +} +INSTANTIATE_TEST_CASE_P(Sampler, + TransformableSamplerTest, + ::testing::Combine( + ::testing::ValuesIn(normalizedCoordModes), + ::testing::ValuesIn(addressingModes), + ::testing::ValuesIn(filterModes)));