diff --git a/runtime/command_queue/command_queue.cpp b/runtime/command_queue/command_queue.cpp index e9f777aff2..c1f27c4c32 100644 --- a/runtime/command_queue/command_queue.cpp +++ b/runtime/command_queue/command_queue.cpp @@ -392,7 +392,7 @@ cl_int CommandQueue::enqueueWriteMemObjForUnmap(MemObj *memObj, void *mappedPtr, UNRECOVERABLE_IF(mipIdx >= 4); writeOrigin[mipIdx] = unmapInfo.mipLevel; retVal = enqueueWriteImage(image, CL_FALSE, writeOrigin, &unmapInfo.size[0], - image->getHostPtrRowPitch(), image->getHostPtrSlicePitch(), mappedPtr, + image->getHostPtrRowPitchForMap(unmapInfo.mipLevel), image->getHostPtrSlicePitchForMap(unmapInfo.mipLevel), mappedPtr, eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); bool mustCallFinish = true; if (!(image->getFlags() & CL_MEM_USE_HOST_PTR)) { @@ -439,7 +439,7 @@ void *CommandQueue::enqueueReadMemObjForMap(TransferProperties &transferProperti UNRECOVERABLE_IF(mipIdx >= 4); readOrigin[mipIdx] = transferProperties.mipLevel; errcodeRet = enqueueReadImage(image, transferProperties.blocking, readOrigin, &transferProperties.size[0], - image->getHostPtrRowPitch(), image->getHostPtrSlicePitch(), returnPtr, eventsRequest.numEventsInWaitList, + image->getHostPtrRowPitchForMap(transferProperties.mipLevel), image->getHostPtrSlicePitchForMap(transferProperties.mipLevel), returnPtr, eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); } @@ -495,6 +495,7 @@ void *CommandQueue::enqueueMapImage(Image *image, cl_bool blockingMap, const_cast(origin), const_cast(region), nullptr); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); + auto returnPtr = enqueueMapMemObject(transferProperties, eventsRequest, errcodeRet); if (image->isMemObjZeroCopy() && image->mappingOnCpuAllowed()) { GetInfoHelper::set(imageSlicePitch, image->getImageDesc().image_slice_pitch); if (image->getImageDesc().image_type == CL_MEM_OBJECT_IMAGE1D_ARRAY) { @@ -507,13 +508,14 @@ void *CommandQueue::enqueueMapImage(Image *image, cl_bool blockingMap, GetInfoHelper::set(imageRowPitch, image->getImageDesc().image_row_pitch); } } else { - GetInfoHelper::set(imageSlicePitch, image->getHostPtrSlicePitch()); - GetInfoHelper::set(imageRowPitch, image->getHostPtrRowPitch()); + GetInfoHelper::set(imageSlicePitch, image->getHostPtrSlicePitchForMap(transferProperties.mipLevel)); + GetInfoHelper::set(imageRowPitch, image->getHostPtrRowPitchForMap(transferProperties.mipLevel)); } if (Image::hasSlices(image->peekClMemObjType()) == false) { GetInfoHelper::set(imageSlicePitch, static_cast(0)); } - return enqueueMapMemObject(transferProperties, eventsRequest, errcodeRet); + + return returnPtr; } cl_int CommandQueue::enqueueUnmapMemObject(MemObj *memObj, void *mappedPtr, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { diff --git a/runtime/gen8/image_gen8.cpp b/runtime/gen8/image_gen8.cpp index cf3a573ef1..a438f7cd68 100644 --- a/runtime/gen8/image_gen8.cpp +++ b/runtime/gen8/image_gen8.cpp @@ -36,5 +36,19 @@ void ImageHw::setMediaSurfaceRotation(void *) {} template void ImageHw::setSurfaceMemoryObjectControlStateIndexToMocsTable(void *, uint32_t) {} +template <> +size_t ImageHw::getHostPtrRowPitchForMap(uint32_t mipLevel) { + size_t mipWidth = (getImageDesc().image_width >> mipLevel) > 0 ? (getImageDesc().image_width >> mipLevel) : 1; + return mipWidth * getSurfaceFormatInfo().ImageElementSizeInBytes; +} + +template <> +size_t ImageHw::getHostPtrSlicePitchForMap(uint32_t mipLevel) { + size_t mipHeight = (getImageDesc().image_height >> mipLevel) > 0 ? (getImageDesc().image_height >> mipLevel) : 1; + size_t rowPitch = getHostPtrRowPitchForMap(mipLevel); + + return rowPitch * mipHeight; +} + #include "runtime/mem_obj/image_factory_init.inl" } diff --git a/runtime/mem_obj/image.cpp b/runtime/mem_obj/image.cpp index 12a6a4631f..e2db9451e3 100644 --- a/runtime/mem_obj/image.cpp +++ b/runtime/mem_obj/image.cpp @@ -1210,14 +1210,19 @@ size_t Image::calculateOffsetForMapping(const MemObjOffsetArray &origin) const { switch (imageDesc.image_type) { case CL_MEM_OBJECT_IMAGE1D_ARRAY: - offset += slicePitch * origin[1]; + if (imageDesc.num_mip_levels <= 1) { + offset += slicePitch * origin[1]; + } break; case CL_MEM_OBJECT_IMAGE2D: offset += rowPitch * origin[1]; break; case CL_MEM_OBJECT_IMAGE2D_ARRAY: case CL_MEM_OBJECT_IMAGE3D: - offset += rowPitch * origin[1] + slicePitch * origin[2]; + offset += rowPitch * origin[1]; + if (imageDesc.num_mip_levels <= 1) { + offset += slicePitch * origin[2]; + } break; default: break; diff --git a/runtime/mem_obj/image.h b/runtime/mem_obj/image.h index e40fc7b531..a8d2862656 100644 --- a/runtime/mem_obj/image.h +++ b/runtime/mem_obj/image.h @@ -185,6 +185,9 @@ class Image : public MemObj { virtual void transformImage2dArrayTo3d(void *memory) = 0; virtual void transformImage3dTo2dArray(void *memory) = 0; + virtual size_t getHostPtrRowPitchForMap(uint32_t mipLevel) = 0; + virtual size_t getHostPtrSlicePitchForMap(uint32_t mipLevel) = 0; + const bool isTiledImage; bool hasSameDescriptor(const cl_image_desc &imageDesc) const; @@ -271,6 +274,8 @@ class ImageHw : public Image { } } + size_t getHostPtrRowPitchForMap(uint32_t mipLevel) override; + size_t getHostPtrSlicePitchForMap(uint32_t mipLevel) override; void setImageArg(void *memory, bool setAsMediaBlockImage, uint32_t mipLevel) override; void setAuxParamsForMultisamples(RENDER_SURFACE_STATE *surfaceState); void setAuxParamsForCCS(RENDER_SURFACE_STATE *surfaceState, Gmm *gmm); diff --git a/runtime/mem_obj/image.inl b/runtime/mem_obj/image.inl index ab4eca1612..afe9309d8a 100644 --- a/runtime/mem_obj/image.inl +++ b/runtime/mem_obj/image.inl @@ -269,4 +269,14 @@ void ImageHw::transformImage3dTo2dArray(void *memory) { surfaceState->setSurfaceType(SURFACE_TYPE::SURFACE_TYPE_SURFTYPE_2D); surfaceState->setSurfaceArray(true); } + +template +size_t ImageHw::getHostPtrRowPitchForMap(uint32_t mipLevel) { + return getHostPtrRowPitch(); +} + +template +size_t ImageHw::getHostPtrSlicePitchForMap(uint32_t mipLevel) { + return getHostPtrSlicePitch(); +} } // namespace OCLRT diff --git a/unit_tests/command_queue/enqueue_map_image_tests.cpp b/unit_tests/command_queue/enqueue_map_image_tests.cpp index a4d7c2ca7f..ef4c8cb6da 100644 --- a/unit_tests/command_queue/enqueue_map_image_tests.cpp +++ b/unit_tests/command_queue/enqueue_map_image_tests.cpp @@ -865,32 +865,33 @@ TEST_F(EnqueueMapImageTest, givenNonZeroCopyImageWhenMappedOnGpuThenReturnHostRo EXPECT_EQ(image->getHostPtrSlicePitch(), retImageSlicePitch); } -TEST_F(EnqueueMapImageTest, givenMipMapImageWhenMappedThenReturnHostRowAndSlicePitch) { - const size_t origin[3] = {0, 0, 0}; +TEST_F(EnqueueMapImageTest, givenMipMapImageWhenMappedThenReturnHostRowAndSlicePitchForMap) { + const size_t origin[4] = {0, 0, 0, 1}; const size_t region[3] = {1, 1, 1}; size_t retImageRowPitch = 0; size_t retImageSlicePitch = 0; cl_image_desc imageDesc = {}; - imageDesc.image_type = CL_MEM_OBJECT_IMAGE1D; + imageDesc.image_type = CL_MEM_OBJECT_IMAGE3D; imageDesc.num_mip_levels = 10; imageDesc.image_width = 4; + imageDesc.image_height = 4; + imageDesc.image_depth = 4; - std::unique_ptr image(ImageHelper>::create(context, &imageDesc)); + std::unique_ptr image(ImageHelper::create(context, &imageDesc)); image->setSharingHandler(new SharingHandler()); EXPECT_FALSE(image->mappingOnCpuAllowed()); - EXPECT_FALSE(image->isMemObjZeroCopy()); pCmdQ->enqueueMapImage(image.get(), true, CL_MAP_READ, origin, region, &retImageRowPitch, &retImageSlicePitch, 0, nullptr, nullptr, retVal); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_EQ(image->getHostPtrRowPitch(), retImageRowPitch); - EXPECT_EQ(image->getHostPtrSlicePitch(), retImageSlicePitch); + EXPECT_EQ(image->getHostPtrRowPitchForMap(static_cast(origin[3])), retImageRowPitch); + EXPECT_EQ(image->getHostPtrSlicePitchForMap(static_cast(origin[3])), retImageSlicePitch); } -TEST_F(EnqueueMapImageTest, givenMipMapImageWhen1DArrayThenReturnRowAndSlicePitchAreEqual) { +TEST_F(EnqueueMapImageTest, givenImage1DArrayWhenEnqueueMapImageIsCalledThenReturnRowAndSlicePitchAreEqual) { class MockImage : public Image { public: MockImage(Context *context, cl_mem_flags flags, GraphicsAllocation *allocation, const SurfaceFormatInfo &surfaceFormat, @@ -909,6 +910,8 @@ TEST_F(EnqueueMapImageTest, givenMipMapImageWhen1DArrayThenReturnRowAndSlicePitc void setSurfaceMemoryObjectControlStateIndexToMocsTable(void *memory, uint32_t value) override {} void transformImage2dArrayTo3d(void *memory) override {} void transformImage3dTo2dArray(void *memory) override {} + size_t getHostPtrRowPitchForMap(uint32_t mipLevel) override { return getHostPtrRowPitch(); } + size_t getHostPtrSlicePitchForMap(uint32_t mipLevel) override { return getHostPtrSlicePitch(); } }; const size_t origin[3] = {0, 0, 0}; diff --git a/unit_tests/gen8/image_tests_gen8.cpp b/unit_tests/gen8/image_tests_gen8.cpp index d572352ee6..f6b309b3b5 100644 --- a/unit_tests/gen8/image_tests_gen8.cpp +++ b/unit_tests/gen8/image_tests_gen8.cpp @@ -42,3 +42,51 @@ GEN8TEST_F(gen8ImageTests, appendSurfaceStateParamsDoesNothing) { EXPECT_EQ(0, memcmp(&surfaceStateBefore, &surfaceStateAfter, sizeof(RENDER_SURFACE_STATE))); } + +GEN8TEST_F(gen8ImageTests, WhenGetHostPtrRowOrSlicePitchForMapIsCalledWithMipLevelZeroThenReturnWidthTimesBytesPerPixelAndRowPitchTimesHeight) { + MockContext context; + 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(&context, &imageDesc)); + auto rowPitch = image->getHostPtrRowPitchForMap(0u); + auto slicePitch = image->getHostPtrSlicePitchForMap(0u); + EXPECT_EQ(4 * imageDesc.image_width, rowPitch); + EXPECT_EQ(imageDesc.image_height * rowPitch, slicePitch); +} + +GEN8TEST_F(gen8ImageTests, WhenGetHostPtrRowOrSlicePitchForMapIsCalledWithMipLevelNonZeroThenReturnScaledWidthTimesBytesPerPixelAndRowPitchTimesScaledHeight) { + MockContext context; + 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(&context, &imageDesc)); + auto rowPitch = image->getHostPtrRowPitchForMap(1u); + auto slicePitch = image->getHostPtrSlicePitchForMap(1u); + EXPECT_EQ(4 * (imageDesc.image_width >> 1), rowPitch); + EXPECT_EQ((imageDesc.image_height >> 1) * rowPitch, slicePitch); +} + +GEN8TEST_F(gen8ImageTests, WhenGetHostPtrRowOrSlicePitchForMapIsCalledWithMipLevelNonZeroThenReturnedScaledWidthTimesBytesPerPixelAndRowPitchTimesScaledHeightCannotBeZero) { + MockContext context; + 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 = 5; + + std::unique_ptr image(ImageHelper::create(&context, &imageDesc)); + auto rowPitch = image->getHostPtrRowPitchForMap(4u); + auto slicePitch = image->getHostPtrSlicePitchForMap(4u); + EXPECT_EQ(4u, rowPitch); + EXPECT_EQ(rowPitch, slicePitch); +} diff --git a/unit_tests/gen9/image_tests_gen9.cpp b/unit_tests/gen9/image_tests_gen9.cpp index 9bbdd581aa..7dea93e322 100644 --- a/unit_tests/gen9/image_tests_gen9.cpp +++ b/unit_tests/gen9/image_tests_gen9.cpp @@ -42,3 +42,35 @@ GEN9TEST_F(gen9ImageTests, appendSurfaceStateParamsDoesNothing) { EXPECT_EQ(0, memcmp(&surfaceStateBefore, &surfaceStateAfter, sizeof(RENDER_SURFACE_STATE))); } + +GEN9TEST_F(gen9ImageTests, WhenGetHostPtrRowOrSlicePitchForMapIsCalledWithMipLevelZeroThenReturnHostPtrRowPitchAndSlicePitch) { + MockContext context; + cl_image_desc imageDesc{}; + imageDesc.image_type = CL_MEM_OBJECT_IMAGE3D; + imageDesc.image_width = 5; + imageDesc.image_height = 5; + imageDesc.image_array_size = 5; + imageDesc.num_mip_levels = 2; + + std::unique_ptr image(ImageHelper::create(&context, &imageDesc)); + auto rowPitch = image->getHostPtrRowPitchForMap(0u); + auto slicePitch = image->getHostPtrSlicePitchForMap(0u); + EXPECT_EQ(image->getHostPtrRowPitch(), rowPitch); + EXPECT_EQ(image->getHostPtrSlicePitch(), slicePitch); +} + +GEN9TEST_F(gen9ImageTests, WhenGetHostPtrRowOrSlicePitchForMapIsCalledWithMipLevelNonZeroThenReturnHostPtrRowPitchAndSlicePitch) { + MockContext context; + cl_image_desc imageDesc{}; + imageDesc.image_type = CL_MEM_OBJECT_IMAGE3D; + imageDesc.image_width = 5; + imageDesc.image_height = 5; + imageDesc.image_array_size = 5; + imageDesc.num_mip_levels = 2; + + std::unique_ptr image(ImageHelper::create(&context, &imageDesc)); + auto rowPitch = image->getHostPtrRowPitchForMap(1u); + auto slicePitch = image->getHostPtrSlicePitchForMap(1u); + EXPECT_EQ(image->getHostPtrRowPitch(), rowPitch); + EXPECT_EQ(image->getHostPtrSlicePitch(), slicePitch); +} diff --git a/unit_tests/mem_obj/image_tests.cpp b/unit_tests/mem_obj/image_tests.cpp index dd4e5099b7..ac8efd6c73 100644 --- a/unit_tests/mem_obj/image_tests.cpp +++ b/unit_tests/mem_obj/image_tests.cpp @@ -1082,6 +1082,67 @@ TEST(ImageTest, givenImageWhenAskedForPtrLengthForCpuMappingThenReturnCorrectVal EXPECT_EQ(expectedLength, retLength); } +TEST(ImageTest, givenMipMapImage3DWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithoutSlicePitch) { + 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 = {{}}; + + auto retOffset = image->calculateOffsetForMapping(origin); + size_t expectedOffset = image->getSurfaceFormatInfo().ImageElementSizeInBytes * origin[0] + + image->getHostPtrRowPitch() * origin[1]; + + EXPECT_EQ(expectedOffset, retOffset); +} + +TEST(ImageTest, givenMipMapImage2DArrayWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithoutSlicePitch) { + 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 = {{}}; + + auto retOffset = image->calculateOffsetForMapping(origin); + size_t expectedOffset = image->getSurfaceFormatInfo().ImageElementSizeInBytes * origin[0] + + image->getHostPtrRowPitch() * origin[1]; + + EXPECT_EQ(expectedOffset, retOffset); +} + +TEST(ImageTest, givenMipMapImage1DArrayWhenAskedForPtrOffsetForGpuMappingThenReturnOffsetWithoutSlicePitch) { + 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 = {{}}; + + auto retOffset = image->calculateOffsetForMapping(origin); + size_t expectedOffset = image->getSurfaceFormatInfo().ImageElementSizeInBytes * origin[0]; + + EXPECT_EQ(expectedOffset, retOffset); +} + typedef ::testing::TestWithParam MipLevelCoordinateTest; TEST_P(MipLevelCoordinateTest, givenMipmappedImageWhenValidateRegionAndOriginIsCalledThenAdditionalOriginCoordinateIsAnalyzed) { diff --git a/unit_tests/mem_obj/image_validate_tests.cpp b/unit_tests/mem_obj/image_validate_tests.cpp index 232d2dbfee..b3dc15e0b8 100644 --- a/unit_tests/mem_obj/image_validate_tests.cpp +++ b/unit_tests/mem_obj/image_validate_tests.cpp @@ -794,6 +794,8 @@ struct NullImage : public Image { void setSurfaceMemoryObjectControlStateIndexToMocsTable(void *memory, uint32_t value) override {} void transformImage2dArrayTo3d(void *memory) override {} void transformImage3dTo2dArray(void *memory) override {} + size_t getHostPtrRowPitchForMap(uint32_t mipLevel) override { return getHostPtrRowPitch(); } + size_t getHostPtrSlicePitchForMap(uint32_t mipLevel) override { return getHostPtrSlicePitch(); } }; TEST_P(ValidParentImageFormatTest, givenParentChannelOrderWhenTestWithAllChannelOrdersThenReturnTrueForValidChannelOrder) { diff --git a/unit_tests/mocks/mock_image.h b/unit_tests/mocks/mock_image.h index 362b051b7d..c5c6f39cf1 100644 --- a/unit_tests/mocks/mock_image.h +++ b/unit_tests/mocks/mock_image.h @@ -47,4 +47,6 @@ struct MockImageBase : public OCLRT::Image { void setSurfaceMemoryObjectControlStateIndexToMocsTable(void *memory, uint32_t value) override {} void transformImage2dArrayTo3d(void *memory) override {} void transformImage3dTo2dArray(void *memory) override {} + size_t getHostPtrRowPitchForMap(uint32_t mipLevel) override { return getHostPtrRowPitch(); }; + size_t getHostPtrSlicePitchForMap(uint32_t mipLevel) override { return getHostPtrSlicePitch(); }; };