From 4f2a05ac88454a5215a327c9b348ff53cacf95bd Mon Sep 17 00:00:00 2001 From: "Dunajski, Bartosz" Date: Thu, 8 Feb 2018 20:55:31 +0100 Subject: [PATCH] Map/unmap enqueue fixes [2/n]: CPU operations on limited range - Curently each non-zerocopy CPU operation on map/unmap make a full copy using hostPtr - This commit adds functionality to select specific range of copy - Multiple mapping with different size is not supported yet, so copy will be made on full range for now. This is for future usage. Change-Id: I7652e85482ba6fffb2474169447baf9b080dcd1e --- Jenkinsfile | 2 +- runtime/api/api.cpp | 4 + .../cpu_data_transfer_handler.cpp | 68 +++++---- runtime/helpers/task_information.cpp | 18 ++- runtime/mem_obj/buffer.cpp | 17 ++- runtime/mem_obj/buffer.h | 5 +- runtime/mem_obj/image.cpp | 141 ++++++++--------- runtime/mem_obj/image.h | 12 +- runtime/mem_obj/mem_obj.cpp | 5 - runtime/mem_obj/mem_obj.h | 6 +- unit_tests/api/cl_create_image_tests.cpp | 24 +++ unit_tests/mem_obj/CMakeLists.txt | 2 +- unit_tests/mem_obj/buffer_tests.cpp | 47 ++++++ unit_tests/mem_obj/image_copy_tests.cpp | 114 -------------- unit_tests/mem_obj/image_tests.cpp | 32 ++-- unit_tests/mem_obj/image_transfer_tests.cpp | 144 ++++++++++++++++++ unit_tests/mem_obj/mem_obj_tests.cpp | 35 ++++- unit_tests/mocks/mock_gmm_resource_info.cpp | 3 + 18 files changed, 405 insertions(+), 274 deletions(-) delete mode 100644 unit_tests/mem_obj/image_copy_tests.cpp create mode 100644 unit_tests/mem_obj/image_transfer_tests.cpp diff --git a/Jenkinsfile b/Jenkinsfile index af463f9a46..fa91c79be9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,4 +2,4 @@ neoDependenciesRev='735095-769' strategy='EQUAL' allowedF=43 -allowedCD=344 +allowedCD=342 diff --git a/runtime/api/api.cpp b/runtime/api/api.cpp index 69e87b64ba..31a75ee9e2 100644 --- a/runtime/api/api.cpp +++ b/runtime/api/api.cpp @@ -731,6 +731,10 @@ cl_mem CL_API_CALL clCreateImage(cl_context context, break; } } + if ((flags & (CL_MEM_COPY_HOST_PTR | CL_MEM_USE_HOST_PTR)) && !hostPtr) { + retVal = CL_INVALID_HOST_PTR; + break; + } image = Image::validateAndCreateImage(pContext, flags, imageFormat, imageDesc, hostPtr, retVal); } while (false); diff --git a/runtime/command_queue/cpu_data_transfer_handler.cpp b/runtime/command_queue/cpu_data_transfer_handler.cpp index c690f92d52..fc8c8db015 100644 --- a/runtime/command_queue/cpu_data_transfer_handler.cpp +++ b/runtime/command_queue/cpu_data_transfer_handler.cpp @@ -35,11 +35,7 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie bool eventCompleted = false; ErrorCodeHelper err(&retVal, CL_SUCCESS); - auto memObj = transferProperties.memObj; - auto image = castToObject(memObj); - auto cmdType = transferProperties.cmdType; - auto size = transferProperties.size; - auto offset = transferProperties.offset; + auto image = castToObject(transferProperties.memObj); if (eventsRequest.outEvent) { eventBuilder.create(this, transferProperties.cmdType, Event::eventNotReady, Event::eventNotReady); @@ -84,8 +80,8 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie eventBuilder.getEvent()->setSubmitTimeStamp(); } //wait for the completness of previous commands - if (cmdType != CL_COMMAND_UNMAP_MEM_OBJECT) { - if (!memObj->isMemObjZeroCopy() || transferProperties.blocking) { + if (transferProperties.cmdType != CL_COMMAND_UNMAP_MEM_OBJECT) { + if (!transferProperties.memObj->isMemObjZeroCopy() || transferProperties.blocking) { finish(true); eventCompleted = true; } @@ -95,33 +91,37 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie eventBuilder.getEvent()->setStartTimeStamp(); } - switch (cmdType) { + switch (transferProperties.cmdType) { case CL_COMMAND_MAP_BUFFER: - if (!memObj->isMemObjZeroCopy()) { + if (!transferProperties.memObj->isMemObjZeroCopy()) { if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_MAP_BUFFER_REQUIRES_COPY_DATA, static_cast(memObj)); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_MAP_BUFFER_REQUIRES_COPY_DATA, static_cast(transferProperties.memObj)); } - memObj->transferDataToHostPtr(); + transferProperties.memObj->transferDataToHostPtr({{transferProperties.memObj->getSize(), 0, 0}}, {{0, 0, 0}}); eventCompleted = true; } else { if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL, CL_ENQUEUE_MAP_BUFFER_DOESNT_REQUIRE_COPY_DATA, static_cast(memObj)); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL, CL_ENQUEUE_MAP_BUFFER_DOESNT_REQUIRE_COPY_DATA, static_cast(transferProperties.memObj)); } } - memObj->incMapCount(); + transferProperties.memObj->incMapCount(); break; case CL_COMMAND_MAP_IMAGE: if (!image->isMemObjZeroCopy()) { if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_MAP_IMAGE_REQUIRES_COPY_DATA, static_cast(image)); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_MAP_IMAGE_REQUIRES_COPY_DATA, static_cast(transferProperties.memObj)); } - image->transferDataToHostPtr(); + auto &imgDesc = image->getImageDesc(); + std::array copySize = {{getValidParam(imgDesc.image_width), + getValidParam(imgDesc.image_height), + getValidParam((std::max(imgDesc.image_depth, imgDesc.image_array_size)))}}; + image->transferDataToHostPtr(copySize, {{0, 0, 0}}); GetInfoHelper::set(transferProperties.retSlicePitch, image->getHostPtrSlicePitch()); GetInfoHelper::set(transferProperties.retRowPitch, image->getHostPtrRowPitch()); eventCompleted = true; } else { if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL, CL_ENQUEUE_MAP_IMAGE_DOESNT_REQUIRE_COPY_DATA, static_cast(image)); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL, CL_ENQUEUE_MAP_IMAGE_DOESNT_REQUIRE_COPY_DATA, static_cast(transferProperties.memObj)); } GetInfoHelper::set(transferProperties.retSlicePitch, image->getImageDesc().image_slice_pitch); GetInfoHelper::set(transferProperties.retRowPitch, image->getImageDesc().image_row_pitch); @@ -129,31 +129,38 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie image->incMapCount(); break; case CL_COMMAND_UNMAP_MEM_OBJECT: - if (!memObj->isMemObjZeroCopy()) { + if (!transferProperties.memObj->isMemObjZeroCopy()) { if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_UNMAP_MEM_OBJ_REQUIRES_COPY_DATA, transferProperties.ptr, static_cast(memObj)); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_UNMAP_MEM_OBJ_REQUIRES_COPY_DATA, transferProperties.ptr, static_cast(transferProperties.memObj)); } - memObj->transferDataFromHostPtrToMemoryStorage(); + std::array copySize = {{transferProperties.memObj->getSize(), 0, 0}}; + if (image) { + auto imgDesc = image->getImageDesc(); + copySize = {{getValidParam(imgDesc.image_width), + getValidParam(imgDesc.image_height), + getValidParam((std::max(imgDesc.image_depth, imgDesc.image_array_size)))}}; + } + transferProperties.memObj->transferDataFromHostPtr(copySize, {{0, 0, 0}}); eventCompleted = true; } else { if (context->isProvidingPerformanceHints()) { context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_GOOD_INTEL, CL_ENQUEUE_UNMAP_MEM_OBJ_DOESNT_REQUIRE_COPY_DATA, transferProperties.ptr); } } - memObj->decMapCount(); + transferProperties.memObj->decMapCount(); break; case CL_COMMAND_READ_BUFFER: if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_READ_BUFFER_REQUIRES_COPY_DATA, static_cast(memObj), transferProperties.ptr); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_READ_BUFFER_REQUIRES_COPY_DATA, static_cast(transferProperties.memObj), transferProperties.ptr); } - memcpy_s(transferProperties.ptr, *size, ptrOffset(memObj->getCpuAddressForMemoryTransfer(), *offset), *size); + memcpy_s(transferProperties.ptr, *transferProperties.size, ptrOffset(transferProperties.memObj->getCpuAddressForMemoryTransfer(), *transferProperties.offset), *transferProperties.size); eventCompleted = true; break; case CL_COMMAND_WRITE_BUFFER: if (context->isProvidingPerformanceHints()) { - context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_WRITE_BUFFER_REQUIRES_COPY_DATA, static_cast(memObj), transferProperties.ptr); + context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_WRITE_BUFFER_REQUIRES_COPY_DATA, static_cast(transferProperties.memObj), transferProperties.ptr); } - memcpy_s(ptrOffset(memObj->getCpuAddressForMemoryTransfer(), *offset), *size, transferProperties.ptr, *size); + memcpy_s(ptrOffset(transferProperties.memObj->getCpuAddressForMemoryTransfer(), *transferProperties.offset), *transferProperties.size, transferProperties.ptr, *transferProperties.size); eventCompleted = true; break; case CL_COMMAND_MARKER: @@ -173,15 +180,14 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie } } - if (cmdType == CL_COMMAND_MAP_BUFFER) { - return memObj->setAndReturnMappedPtr(*offset); + if (transferProperties.cmdType == CL_COMMAND_MAP_BUFFER) { + return transferProperties.memObj->setAndReturnMappedPtr(*transferProperties.offset); } - if (cmdType == CL_COMMAND_MAP_IMAGE) { - size_t mapOffset = - image->getSurfaceFormatInfo().ImageElementSizeInBytes * offset[0] + - image->getImageDesc().image_row_pitch * offset[1] + - image->getImageDesc().image_slice_pitch * offset[2]; + if (transferProperties.cmdType == CL_COMMAND_MAP_IMAGE) { + size_t mapOffset = image->getSurfaceFormatInfo().ImageElementSizeInBytes * transferProperties.offset[0] + + image->getImageDesc().image_row_pitch * transferProperties.offset[1] + + image->getImageDesc().image_slice_pitch * transferProperties.offset[2]; void *ptrToReturn = nullptr; if (image->isMemObjZeroCopy()) { ptrToReturn = ptrOffset(image->getCpuAddress(), mapOffset); diff --git a/runtime/helpers/task_information.cpp b/runtime/helpers/task_information.cpp index 7d95d23584..561da00e33 100644 --- a/runtime/helpers/task_information.cpp +++ b/runtime/helpers/task_information.cpp @@ -26,7 +26,7 @@ #include "runtime/command_queue/enqueue_common.h" #include "runtime/device/device.h" #include "runtime/device_queue/device_queue.h" -#include "runtime/mem_obj/mem_obj.h" +#include "runtime/mem_obj/image.h" #include "runtime/memory_manager/surface.h" #include "runtime/helpers/aligned_memory.h" #include "runtime/helpers/string.h" @@ -87,12 +87,22 @@ CompletionStamp &CommandMapUnmap::submit(uint32_t taskLevel, bool terminated) { cmdQ.waitUntilComplete(completionStamp.taskCount, completionStamp.flushStamp); - if (memObj.isMemObjZeroCopy() == false) { + if (!memObj.isMemObjZeroCopy()) { + std::array copySize = {{memObj.getSize(), 0, 0}}; + + auto image = castToObject(&memObj); + if (image) { + auto &imgDesc = image->getImageDesc(); + copySize = {{getValidParam(imgDesc.image_width), + getValidParam(imgDesc.image_height), + getValidParam((std::max(imgDesc.image_depth, imgDesc.image_array_size)))}}; + } + if (op == MAP) { - memObj.transferDataToHostPtr(); + memObj.transferDataToHostPtr(copySize, {{0, 0, 0}}); } else { DEBUG_BREAK_IF(op != UNMAP); - memObj.transferDataFromHostPtrToMemoryStorage(); + memObj.transferDataFromHostPtr(copySize, {{0, 0, 0}}); } } diff --git a/runtime/mem_obj/buffer.cpp b/runtime/mem_obj/buffer.cpp index c3a44d2df6..60f3aae898 100644 --- a/runtime/mem_obj/buffer.cpp +++ b/runtime/mem_obj/buffer.cpp @@ -291,10 +291,19 @@ bool Buffer::bufferRectPitchSet(const size_t *bufferOrigin, return true; } -void *Buffer::transferDataToHostPtr() { - DBG_LOG(LogMemoryObject, __FUNCTION__, "hostPtr:", hostPtr, "size:", size, "memoryStorage:", memoryStorage); - memcpy_s(hostPtr, size, memoryStorage, size); - return hostPtr; +void Buffer::transferData(void *dst, void *src, size_t copySize, size_t copyOffset) { + DBG_LOG(LogMemoryObject, __FUNCTION__, " hostPtr: ", hostPtr, ", size: ", copySize, ", offset: ", copyOffset, ", memoryStorage: ", memoryStorage); + auto dstPtr = ptrOffset(dst, copyOffset); + auto srcPtr = ptrOffset(src, copyOffset); + memcpy_s(dstPtr, copySize, srcPtr, copySize); +} + +void Buffer::transferDataToHostPtr(std::array copySize, std::array copyOffset) { + transferData(hostPtr, memoryStorage, copySize[0], copyOffset[0]); +} + +void Buffer::transferDataFromHostPtr(std::array copySize, std::array copyOffset) { + transferData(memoryStorage, hostPtr, copySize[0], copyOffset[0]); } size_t Buffer::calculateHostPtrSize(const size_t *origin, const size_t *region, size_t rowPitch, size_t slicePitch) { diff --git a/runtime/mem_obj/buffer.h b/runtime/mem_obj/buffer.h index a34e879196..1a0ac6f949 100644 --- a/runtime/mem_obj/buffer.h +++ b/runtime/mem_obj/buffer.h @@ -100,7 +100,8 @@ class Buffer : public MemObj { static size_t calculateHostPtrSize(const size_t *origin, const size_t *region, size_t rowPitch, size_t slicePitch); - void *transferDataToHostPtr() override; + void transferDataToHostPtr(std::array copySize, std::array copyOffset) override; + void transferDataFromHostPtr(std::array copySize, std::array copyOffset) override; bool isReadWriteOnCpuAllowed(cl_bool blocking, cl_uint numEventsInWaitList, void *ptr, size_t size); @@ -125,6 +126,8 @@ class Buffer : public MemObj { bool &allocateMemory, bool ©MemoryFromHostPtr, MemoryManager *memMngr); + + void transferData(void *dst, void *src, size_t copySize, size_t copyOffset); }; template diff --git a/runtime/mem_obj/image.cpp b/runtime/mem_obj/image.cpp index 0aa87f3a2a..6e900a0ce7 100644 --- a/runtime/mem_obj/image.cpp +++ b/runtime/mem_obj/image.cpp @@ -81,23 +81,25 @@ Image::Image(Context *context, setSurfaceOffsets(0, 0, 0, 0); } -void Image::transferData(void *src, size_t srcRowPitch, size_t srcSlicePitch, void *dest, size_t destRowPitch, size_t destSlicePitch, cl_image_desc *imageDesc, size_t pixelSize, size_t imageCount) { - size_t imageHeight = getValidParam(imageDesc->image_height); - size_t imageDepth = getValidParam(imageDesc->image_depth); - size_t lineWidth = getValidParam(imageDesc->image_width) * pixelSize; +void Image::transferData(void *dest, size_t destRowPitch, size_t destSlicePitch, + void *src, size_t srcRowPitch, size_t srcSlicePitch, + std::array ©Region, std::array ©Origin) { + + size_t pixelSize = surfaceFormatInfo.ImageElementSizeInBytes; + size_t lineWidth = copyRegion[0] * pixelSize; DBG_LOG(LogMemoryObject, __FUNCTION__, "memcpy dest:", dest, "sizeRowToCopy:", lineWidth, "src:", src); - for (size_t count = 0; count < imageCount; count++) { - for (size_t depth = 0; depth < imageDepth; ++depth) { - auto currentImage = std::max(depth, count); - auto srcPtr = ptrOffset(src, srcSlicePitch * currentImage); - auto destPtr = ptrOffset(dest, destSlicePitch * currentImage); - for (size_t height = 0; height < imageHeight; ++height) { - memcpy_s(destPtr, lineWidth, srcPtr, lineWidth); - srcPtr = ptrOffset(srcPtr, srcRowPitch); - destPtr = ptrOffset(destPtr, destRowPitch); - } + for (size_t slice = copyOrigin[2]; slice < (copyOrigin[2] + copyRegion[2]); slice++) { + auto srcSliceOffset = ptrOffset(src, srcSlicePitch * slice); + auto dstSliceOffset = ptrOffset(dest, destSlicePitch * slice); + + for (size_t height = copyOrigin[1]; height < (copyOrigin[1] + copyRegion[1]); height++) { + auto srcRowOffset = ptrOffset(srcSliceOffset, srcRowPitch * height); + auto dstRowOffset = ptrOffset(dstSliceOffset, destRowPitch * height); + + memcpy_s(ptrOffset(dstRowOffset, copyOrigin[0] * pixelSize), lineWidth, + ptrOffset(srcRowOffset, copyOrigin[0] * pixelSize), lineWidth); } } } @@ -212,39 +214,35 @@ Image *Image::create(Context *context, } else { gmm = new Gmm(); gmm->queryImageParams(imgInfo, hwInfo); + + errcodeRet = CL_OUT_OF_HOST_MEMORY; if (flags & CL_MEM_USE_HOST_PTR) { - errcodeRet = CL_INVALID_HOST_PTR; - if (hostPtr) { - size_t pointerPassedSize = hostPtrRowPitch * imageHeight * imageDepth * imageCount; - auto alignedSizePassedPointer = alignSizeWholePage(const_cast(hostPtr), pointerPassedSize); - auto alignedSizeRequiredForAllocation = alignSizeWholePage(const_cast(hostPtr), imgInfo.size); + size_t pointerPassedSize = hostPtrRowPitch * imageHeight * imageDepth * imageCount; + auto alignedSizePassedPointer = alignSizeWholePage(const_cast(hostPtr), pointerPassedSize); + auto alignedSizeRequiredForAllocation = alignSizeWholePage(const_cast(hostPtr), imgInfo.size); - // Passed pointer doesn't have enough memory, copy is needed - copyRequired = (alignedSizeRequiredForAllocation > alignedSizePassedPointer) | - (imgInfo.rowPitch != hostPtrRowPitch) | - (imgInfo.slicePitch != hostPtrSlicePitch) | - ((reinterpret_cast(hostPtr) & (MemoryConstants::cacheLineSize - 1)) != 0) | - isTilingAllowed; + // Passed pointer doesn't have enough memory, copy is needed + copyRequired = (alignedSizeRequiredForAllocation > alignedSizePassedPointer) | + (imgInfo.rowPitch != hostPtrRowPitch) | + (imgInfo.slicePitch != hostPtrSlicePitch) | + ((reinterpret_cast(hostPtr) & (MemoryConstants::cacheLineSize - 1)) != 0) | + isTilingAllowed; - if (copyRequired && !context->isSharedContext) { - errcodeRet = CL_OUT_OF_HOST_MEMORY; - memory = memoryManager->allocateGraphicsMemoryForImage(imgInfo, gmm); - zeroCopy = false; - transferNeeded = true; - } else { - // To avoid having two pointers in a MemObj we cast off the const here - // However, in USE_HOST_PTR cases we shouldn't be modifying the memory - memory = memoryManager->allocateGraphicsMemory(imgInfo.size, hostPtr); - memory->gmm = gmm; - zeroCopy = true; - } + if (copyRequired && !context->isSharedContext) { + memory = memoryManager->allocateGraphicsMemoryForImage(imgInfo, gmm); + zeroCopy = false; + transferNeeded = true; + } else { + memory = memoryManager->allocateGraphicsMemory(imgInfo.size, hostPtr); + memory->gmm = gmm; + zeroCopy = true; } } else { - errcodeRet = CL_OUT_OF_HOST_MEMORY; memory = memoryManager->allocateGraphicsMemoryForImage(imgInfo, gmm); zeroCopy = true; } } + transferNeeded |= !!(flags & CL_MEM_COPY_HOST_PTR); switch (imageDesc->image_type) { case CL_MEM_OBJECT_IMAGE3D: @@ -286,19 +284,6 @@ Image *Image::create(Context *context, DBG_LOG(LogMemoryObject, __FUNCTION__, "hostPtr:", hostPtr, "size:", memory->getUnderlyingBufferSize(), "memoryStorage:", memory->getUnderlyingBuffer(), "GPU address:", std::hex, memory->getGpuAddress()); - if (!isTilingAllowed) { - errcodeRet = CL_INVALID_VALUE; - if (flags & CL_MEM_COPY_HOST_PTR || transferNeeded) { - if (hostPtr) { - Image::transferData((void *)hostPtr, hostPtrRowPitch, hostPtrSlicePitch, - memory->getUnderlyingBuffer(), imgInfo.rowPitch, imgInfo.slicePitch, - (cl_image_desc *)imageDesc, surfaceFormat->ImageElementSizeInBytes, imageCount); - } else { - memoryManager->freeGraphicsMemory(memory); - break; - } - } - } if (parentImage) { imageDescriptor.image_height = imageHeight; imageDescriptor.image_width = imageWidth; @@ -341,39 +326,33 @@ Image *Image::create(Context *context, } errcodeRet = CL_SUCCESS; - if (isTilingAllowed) { - if (flags & CL_MEM_COPY_HOST_PTR || transferNeeded) { - if (!hostPtr) { - errcodeRet = CL_INVALID_VALUE; - image->release(); - image = nullptr; - memory = nullptr; - break; - } - auto cmdQ = context->getSpecialQueue(); + if (transferNeeded) { + std::array copyOrigin = {{0, 0, 0}}; + std::array copyRegion = {{imageWidth, imageHeight, std::max(imageDepth, imageCount)}}; - size_t Origin[] = {0, 0, 0}; - size_t Region[] = {imageWidth, imageHeight, imageDepth}; - if (imageDesc->image_type == CL_MEM_OBJECT_IMAGE2D_ARRAY) { - Region[2] = imageDesc->image_array_size; - } + if (isTilingAllowed) { + auto cmdQ = context->getSpecialQueue(); if (IsNV12Image(&image->getImageFormat())) { errcodeRet = image->writeNV12Planes(hostPtr, hostPtrRowPitch); } else { - errcodeRet = cmdQ->enqueueWriteImage(image, CL_TRUE, Origin, Region, + errcodeRet = cmdQ->enqueueWriteImage(image, CL_TRUE, ©Origin[0], ©Region[0], hostPtrRowPitch, hostPtrSlicePitch, hostPtr, 0, nullptr, nullptr); } - if (errcodeRet != CL_SUCCESS) { - image->release(); - image = nullptr; - memory = nullptr; - break; - } + } else { + image->transferData(memory->getUnderlyingBuffer(), imgInfo.rowPitch, imgInfo.slicePitch, + const_cast(hostPtr), hostPtrRowPitch, hostPtrSlicePitch, + copyRegion, copyOrigin); } } + if (errcodeRet != CL_SUCCESS) { + image->release(); + image = nullptr; + memory = nullptr; + break; + } } while (false); return image; @@ -860,16 +839,16 @@ Image *Image::redescribe() { return image; } -void *Image::transferDataToHostPtr() { - Image::transferData(graphicsAllocation->getUnderlyingBuffer(), imageDesc.image_row_pitch, imageDesc.image_slice_pitch, - hostPtr, hostPtrRowPitch, hostPtrSlicePitch, &imageDesc, surfaceFormatInfo.ImageElementSizeInBytes, imageCount); - return hostPtr; +void Image::transferDataToHostPtr(std::array copySize, std::array copyOffset) { + transferData(hostPtr, hostPtrRowPitch, hostPtrSlicePitch, + graphicsAllocation->getUnderlyingBuffer(), imageDesc.image_row_pitch, imageDesc.image_slice_pitch, + copySize, copyOffset); } -void Image::transferDataFromHostPtrToMemoryStorage() { - Image::transferData(hostPtr, hostPtrRowPitch, hostPtrSlicePitch, - memoryStorage, imageDesc.image_row_pitch, imageDesc.image_slice_pitch, - &imageDesc, surfaceFormatInfo.ImageElementSizeInBytes, imageCount); +void Image::transferDataFromHostPtr(std::array copySize, std::array copyOffset) { + transferData(memoryStorage, imageDesc.image_row_pitch, imageDesc.image_slice_pitch, + hostPtr, hostPtrRowPitch, hostPtrSlicePitch, + copySize, copyOffset); } cl_int Image::writeNV12Planes(const void *hostPtr, size_t hostPtrRowPitch) { diff --git a/runtime/mem_obj/image.h b/runtime/mem_obj/image.h index 11b100776a..a934b54339 100644 --- a/runtime/mem_obj/image.h +++ b/runtime/mem_obj/image.h @@ -138,12 +138,13 @@ class Image : public MemObj { const cl_image_desc &getImageDesc() const; const cl_image_format &getImageFormat() const; const SurfaceFormatInfo &getSurfaceFormatInfo() const; - void *transferDataToHostPtr() override; + + void transferDataToHostPtr(std::array copySize, std::array copyOffset) override; + void transferDataFromHostPtr(std::array copySize, std::array copyOffset) override; Image *redescribe(); Image *redescribeFillImage(); ImageCreatFunc createFunction; - void transferDataFromHostPtrToMemoryStorage() override; uint32_t getQPitch() { return qPitch; } void setQPitch(uint32_t qPitch) { this->qPitch = qPitch; } @@ -151,7 +152,7 @@ class Image : public MemObj { void setHostPtrRowPitch(size_t pitch) { this->hostPtrRowPitch = pitch; } size_t getHostPtrSlicePitch() { return hostPtrSlicePitch; } void setHostPtrSlicePitch(size_t pitch) { this->hostPtrSlicePitch = pitch; } - size_t getImageCount() { return imageCount; } + size_t getImageCount() const { return imageCount; } void setImageCount(size_t imageCount) { this->imageCount = imageCount; } bool allowTiling() const override { return this->isTiledImage; } void setImageRowPitch(size_t rowPitch) { imageDesc.image_row_pitch = rowPitch; } @@ -176,7 +177,6 @@ class Image : public MemObj { cl_int writeNV12Planes(const void *hostPtr, size_t hostPtrRowPitch); void setMcsSurfaceInfo(McsSurfaceInfo &info) { mcsSurfaceInfo = info; } const McsSurfaceInfo &getMcsSurfaceInfo() { return mcsSurfaceInfo; } - static void transferData(void *src, size_t srcRowPitch, size_t srcSlicePitch, void *dest, size_t destRowPitch, size_t destSlicePitch, cl_image_desc *imageDesc, size_t pixelSize, size_t imageCount); const bool isTiledImage; @@ -197,6 +197,10 @@ class Image : public MemObj { void getOsSpecificImageInfo(const cl_mem_info ¶mName, size_t *srcParamSize, void **srcParam); + void transferData(void *dst, size_t dstRowPitch, size_t dstSlicePitch, + void *src, size_t srcRowPitch, size_t srcSlicePitch, + std::array ©Region, std::array ©Origin); + cl_image_format imageFormat; cl_image_desc imageDesc; SurfaceFormatInfo surfaceFormatInfo; diff --git a/runtime/mem_obj/mem_obj.cpp b/runtime/mem_obj/mem_obj.cpp index 477a128338..de010a85e5 100644 --- a/runtime/mem_obj/mem_obj.cpp +++ b/runtime/mem_obj/mem_obj.cpp @@ -247,11 +247,6 @@ bool MemObj::isMemObjWithHostPtrSVM() const { return isHostPtrSVM; } -void MemObj::transferDataFromHostPtrToMemoryStorage() { - size_t dataBytesToTransfer = std::min(size, hostPtrMinSize); - memcpy_s(memoryStorage, size, hostPtr, dataBytesToTransfer); -} - GraphicsAllocation *MemObj::getGraphicsAllocation() { return graphicsAllocation; } diff --git a/runtime/mem_obj/mem_obj.h b/runtime/mem_obj/mem_obj.h index eefd374f65..05252932ed 100644 --- a/runtime/mem_obj/mem_obj.h +++ b/runtime/mem_obj/mem_obj.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace OCLRT { class GraphicsAllocation; @@ -88,8 +89,9 @@ class MemObj : public BaseObject<_cl_mem> { void decMapCount(); bool isMemObjZeroCopy() const; bool isMemObjWithHostPtrSVM() const; - virtual void *transferDataToHostPtr() { return nullptr; }; - virtual void transferDataFromHostPtrToMemoryStorage(); + virtual void transferDataToHostPtr(std::array copySize, std::array copyOffset) { UNRECOVERABLE_IF(true); }; + virtual void transferDataFromHostPtr(std::array copySize, std::array copyOffset) { UNRECOVERABLE_IF(true); }; + GraphicsAllocation *getGraphicsAllocation(); GraphicsAllocation *getMcsAllocation() { return mcsAllocation; } void setMcsAllocation(GraphicsAllocation *alloc) { mcsAllocation = alloc; } diff --git a/unit_tests/api/cl_create_image_tests.cpp b/unit_tests/api/cl_create_image_tests.cpp index eb9bb36692..61ed721c60 100644 --- a/unit_tests/api/cl_create_image_tests.cpp +++ b/unit_tests/api/cl_create_image_tests.cpp @@ -165,6 +165,30 @@ TEST_F(clCreateImageTest, NotNullHostPtrAndRowPitchIsNotMultipleOfElementSizeRet EXPECT_EQ(CL_INVALID_MEM_OBJECT, retVal); } +TEST_F(clCreateImageTest, givenNullHostPtrWhenCopyHostPtrFlagPassedThenReturnError) { + auto image = clCreateImage( + pContext, + CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, + &imageFormat, + &imageDesc, + nullptr, + &retVal); + ASSERT_EQ(CL_INVALID_HOST_PTR, retVal); + EXPECT_EQ(nullptr, image); +} + +TEST_F(clCreateImageTest, givenNullHostPtrWhenUseHostPtrFlagPassedThenReturnError) { + auto image = clCreateImage( + pContext, + CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, + &imageFormat, + &imageDesc, + nullptr, + &retVal); + ASSERT_EQ(CL_INVALID_HOST_PTR, retVal); + EXPECT_EQ(nullptr, image); +} + TEST_F(clCreateImageTest, NullHostPtrAndRowPitchIsNotZeroReturnsError) { imageDesc.image_row_pitch = 4; auto image = clCreateImage( diff --git a/unit_tests/mem_obj/CMakeLists.txt b/unit_tests/mem_obj/CMakeLists.txt index 114f9148cf..da1c1a4b9f 100644 --- a/unit_tests/mem_obj/CMakeLists.txt +++ b/unit_tests/mem_obj/CMakeLists.txt @@ -29,7 +29,7 @@ set(IGDRCL_SRCS_tests_mem_obj "${CMAKE_CURRENT_SOURCE_DIR}/destructor_callback_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/get_mem_object_info_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/get_mem_object_info_subbufer_tests.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/image_copy_tests.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/image_transfer_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/image_format_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/image_redescribe_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/image_release_mapped_ptr_tests.cpp" diff --git a/unit_tests/mem_obj/buffer_tests.cpp b/unit_tests/mem_obj/buffer_tests.cpp index 13fc273efd..c3f19d5ce7 100644 --- a/unit_tests/mem_obj/buffer_tests.cpp +++ b/unit_tests/mem_obj/buffer_tests.cpp @@ -856,3 +856,50 @@ HWTEST_F(BufferUnmapTest, givenBufferWithoutSharingHandlerWhenUnmappingThenDontU EXPECT_EQ(0u, cmdQ.EnqueueWriteBufferCounter); } + +using BufferTransferTests = BufferUnmapTest; + +TEST_F(BufferTransferTests, givenBufferWhenTransferToHostPtrCalledThenCopyRequestedSizeAndOffsetOnly) { + MockContext context(pDevice); + auto retVal = CL_SUCCESS; + const size_t bufferSize = 100; + size_t copyOffset = 20; + size_t copySize = 10; + size_t ignoredParam = 123; + + uint8_t hostPtr[bufferSize] = {}; + uint8_t expectedHostPtr[bufferSize] = {}; + std::unique_ptr buffer(Buffer::create(&context, CL_MEM_USE_HOST_PTR, bufferSize, hostPtr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + + auto srcPtr = buffer->getCpuAddress(); + EXPECT_NE(srcPtr, hostPtr); + memset(srcPtr, 123, bufferSize); + memset(ptrOffset(expectedHostPtr, copyOffset), 123, copySize); + + buffer->transferDataToHostPtr({{copySize, ignoredParam, ignoredParam}}, {{copyOffset, ignoredParam, ignoredParam}}); + + EXPECT_TRUE(memcmp(hostPtr, expectedHostPtr, copySize) == 0); +} + +TEST_F(BufferTransferTests, givenBufferWhenTransferFromHostPtrCalledThenCopyRequestedSizeAndOffsetOnly) { + MockContext context(pDevice); + auto retVal = CL_SUCCESS; + const size_t bufferSize = 100; + size_t copyOffset = 20; + size_t copySize = 10; + size_t ignoredParam = 123; + + uint8_t hostPtr[bufferSize] = {}; + uint8_t expectedBufferMemory[bufferSize] = {}; + std::unique_ptr buffer(Buffer::create(&context, CL_MEM_USE_HOST_PTR, bufferSize, hostPtr, retVal)); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_NE(buffer->getCpuAddress(), hostPtr); + memset(hostPtr, 123, bufferSize); + memset(ptrOffset(expectedBufferMemory, copyOffset), 123, copySize); + + buffer->transferDataFromHostPtr({{copySize, ignoredParam, ignoredParam}}, {{copyOffset, ignoredParam, ignoredParam}}); + + EXPECT_TRUE(memcmp(expectedBufferMemory, buffer->getCpuAddress(), copySize) == 0); +} diff --git a/unit_tests/mem_obj/image_copy_tests.cpp b/unit_tests/mem_obj/image_copy_tests.cpp deleted file mode 100644 index 2a853bde80..0000000000 --- a/unit_tests/mem_obj/image_copy_tests.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2017, 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/mem_obj/image.h" -#include "gtest/gtest.h" - -using namespace OCLRT; - -const char valueOfEmptyPixel = 0; -const char valueOfCopiedPixel = 1; -const char garbageValue = 2; - -const int imageCount = 2; -const int imageDimension = 25; -auto const elementSize = 4; - -class CopyImageTest : public testing::WithParamInterface /*srcPitch, destPitch*/>, - public testing::Test { - - public: - void SetUp() override { - std::tie(srcRowPitch, destRowPitch) = GetParam(); - // clang-format off - imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; - imageDesc.image_width = imageDimension; - imageDesc.image_height = imageDimension; - imageDesc.image_depth = 0; - imageDesc.image_array_size = imageCount; - 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 - lineWidth = imageDesc.image_width * elementSize; - srcSlicePitch = srcRowPitch * imageDimension; - destSlicePitch = destRowPitch * imageDimension; - srcPtrSize = srcSlicePitch * imageCount; - destPtrSize = destSlicePitch * imageCount; - srcPtr.reset(new char[srcPtrSize]); - destPtr.reset(new char[destPtrSize * 2]); - } - - cl_image_desc imageDesc; - size_t srcRowPitch; - size_t srcSlicePitch; - size_t destRowPitch; - size_t destSlicePitch; - size_t srcPtrSize; - size_t destPtrSize; - size_t lineWidth; - std::unique_ptr srcPtr; - std::unique_ptr destPtr; -}; - -TEST_P(CopyImageTest, givenSrcAndDestPitchesWhenTransferDataIsCalledThenSpecificValuesAreCopied) { - memset(destPtr.get(), valueOfEmptyPixel, 2 * destPtrSize); - memset(srcPtr.get(), garbageValue, srcPtrSize); - for (size_t i = 0; i < imageCount; ++i) { - for (size_t j = 0; j < imageDimension; ++j) { - memset(srcPtr.get() + i * srcSlicePitch + j * srcRowPitch, valueOfCopiedPixel, lineWidth); - } - } - Image::transferData(srcPtr.get(), srcRowPitch, srcSlicePitch, destPtr.get(), destRowPitch, destSlicePitch, &imageDesc, elementSize, imageCount); - size_t unconfirmedCopies = 0; - //expect no garbage copied - for (size_t i = 0; i < 2 * destPtrSize; ++i) { - if (destPtr.get()[i] == valueOfCopiedPixel) { - unconfirmedCopies++; - } - EXPECT_NE(garbageValue, destPtr.get()[i]); - } - //expect copied to right locations - for (size_t i = 0; i < imageCount; ++i) { - for (size_t j = 0; j < imageDimension; ++j) { - for (size_t k = 0; k < lineWidth; ++k) { - EXPECT_EQ(valueOfCopiedPixel, destPtr.get()[i * destSlicePitch + j * destRowPitch + k]); - unconfirmedCopies--; - } - } - } - //expect copied only to destPtr - for (size_t i = 0; i < destPtrSize; ++i) { - EXPECT_EQ(valueOfEmptyPixel, destPtr.get()[destPtrSize + i]); - } - EXPECT_EQ(0u, unconfirmedCopies); -} -size_t valuesOfPitchesInCopyTests[] = {100, 101, 102}; - -INSTANTIATE_TEST_CASE_P( - CopyImageTests, - CopyImageTest, - testing::Combine( - testing::ValuesIn(valuesOfPitchesInCopyTests), - testing::ValuesIn(valuesOfPitchesInCopyTests))); diff --git a/unit_tests/mem_obj/image_tests.cpp b/unit_tests/mem_obj/image_tests.cpp index 9a21d8c438..388c2b9a0d 100644 --- a/unit_tests/mem_obj/image_tests.cpp +++ b/unit_tests/mem_obj/image_tests.cpp @@ -472,22 +472,6 @@ TEST_P(CreateImageNoHostPtr, completionStamp) { delete image; } -TEST_P(CreateImageNoHostPtr, withUseHostPtrReturnsError) { - auto image = createImageWithFlags(flags | CL_MEM_USE_HOST_PTR); - - EXPECT_EQ(CL_INVALID_HOST_PTR, retVal); - EXPECT_EQ(nullptr, image); - - delete image; -} - -TEST_P(CreateImageNoHostPtr, withCopyHostPtrReturnsError) { - auto image = createImageWithFlags(flags | CL_MEM_COPY_HOST_PTR); - - EXPECT_EQ(CL_INVALID_VALUE, retVal); - EXPECT_EQ(nullptr, image); -} - TEST_P(CreateImageNoHostPtr, withImageGraphicsAllocationReportsImageType) { auto image = createImageWithFlags(flags); @@ -785,7 +769,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyImageWhenDataTransferedFromHostPtrToMemSto memset(memoryStorage, 0, memoryStorageSize); memset((char *)unalignedHostPtr + imageSize, 2, 100 - 4); - imageNonZeroCopy->transferDataFromHostPtrToMemoryStorage(); + auto &imgDesc = imageNonZeroCopy->getImageDesc(); + imageNonZeroCopy->transferDataFromHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, + {{0, 0, 0}}); void *foundData = memchr(memoryStorage, 2, memoryStorageSize); EXPECT_EQ(0, foundData); @@ -818,7 +804,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchImageWhenDataIsTransferedFr memset(memoryStorage, 0, memoryStorageSize); memset((char *)unalignedHostPtr + imageSize, 2, 100 - 4); - imageNonZeroCopy->transferDataFromHostPtrToMemoryStorage(); + auto &imgDesc = imageNonZeroCopy->getImageDesc(); + imageNonZeroCopy->transferDataFromHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, + {{0, 0, 0}}); void *foundData = memchr(memoryStorage, 2, memoryStorageSize); EXPECT_EQ(0, foundData); @@ -874,7 +862,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchWithExtraBytes1DArrayImageW unsigned char *internalRow = static_cast(memoryStorage); if (run == 1) { - imageNonZeroCopy->transferDataFromHostPtrToMemoryStorage(); + auto &imgDesc = imageNonZeroCopy->getImageDesc(); + imageNonZeroCopy->transferDataFromHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, + {{0, 0, 0}}); } for (size_t arrayIndex = 0; arrayIndex < imageCount; ++arrayIndex) { @@ -893,7 +883,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchWithExtraBytes1DArrayImageW } } - imageNonZeroCopy->transferDataToHostPtr(); + auto &imgDesc = imageNonZeroCopy->getImageDesc(); + imageNonZeroCopy->transferDataToHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, + {{0, 0, 0}}); row = static_cast(unalignedHostPtr); diff --git a/unit_tests/mem_obj/image_transfer_tests.cpp b/unit_tests/mem_obj/image_transfer_tests.cpp new file mode 100644 index 0000000000..e9808f34b4 --- /dev/null +++ b/unit_tests/mem_obj/image_transfer_tests.cpp @@ -0,0 +1,144 @@ +/* + * 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/image_fixture.h" +#include "unit_tests/mocks/mock_device.h" +#include "unit_tests/mocks/mock_context.h" +#include "gtest/gtest.h" + +using namespace OCLRT; + +class ImageHostPtrTransferTests : public testing::Test { + + public: + void SetUp() override { + device.reset(Device::create(*platformDevices)); + context.reset(new MockContext(device.get())); + } + + template + void createImageAndSetTestParams() { + image.reset(ImageHelper>::create(context.get())); + + imgDesc = &image->getImageDesc(); + copyOrigin = {{imgDesc->image_width / 2, imgDesc->image_height / 2, imgDesc->image_depth / 2}}; + copyRegion = copyOrigin; + + hostPtrSlicePitch = image->getHostPtrSlicePitch(); + hostPtrRowPitch = image->getHostPtrRowPitch(); + imageSlicePitch = image->getImageDesc().image_slice_pitch; + imageRowPitch = image->getImageDesc().image_row_pitch; + pixelSize = image->getSurfaceFormatInfo().ImageElementSizeInBytes; + } + + void setExpectedData(uint8_t *dstPtr, size_t slicePitch, size_t rowPitch) { + for (size_t slice = copyOrigin[2]; slice < (copyOrigin[2] + copyRegion[2]); slice++) { + auto sliceOffset = ptrOffset(dstPtr, slicePitch * slice); + for (size_t height = copyOrigin[1]; height < (copyOrigin[1] + copyRegion[1]); height++) { + auto rowOffset = ptrOffset(sliceOffset, rowPitch * height); + memset(ptrOffset(rowOffset, copyOrigin[0] * pixelSize), 123, copyRegion[0] * pixelSize); + } + } + } + + std::unique_ptr device; + std::unique_ptr context; + std::unique_ptr image; + + std::array copyRegion; + std::array copyOrigin; + + const cl_image_desc *imgDesc = nullptr; + size_t hostPtrSlicePitch, hostPtrRowPitch, imageSlicePitch, imageRowPitch, pixelSize; +}; + +TEST_F(ImageHostPtrTransferTests, given3dImageWhenTransferToHostPtrCalledThenCopyRequestedRegionAndOriginOnly) { + createImageAndSetTestParams(); + EXPECT_NE(hostPtrSlicePitch, imageSlicePitch); + EXPECT_NE(hostPtrRowPitch, imageRowPitch); + EXPECT_NE(image->getCpuAddress(), image->getHostPtr()); + + std::unique_ptr expectedHostPtr(new uint8_t[hostPtrSlicePitch * imgDesc->image_depth]); + memset(image->getHostPtr(), 0, hostPtrSlicePitch * imgDesc->image_depth); + memset(expectedHostPtr.get(), 0, hostPtrSlicePitch * imgDesc->image_depth); + memset(image->getCpuAddress(), 123, imageSlicePitch * imgDesc->image_depth); + + setExpectedData(expectedHostPtr.get(), hostPtrSlicePitch, hostPtrRowPitch); + + image->transferDataToHostPtr(copyRegion, copyOrigin); + + EXPECT_TRUE(memcmp(image->getHostPtr(), expectedHostPtr.get(), hostPtrSlicePitch * imgDesc->image_depth) == 0); +} + +TEST_F(ImageHostPtrTransferTests, given3dImageWhenTransferFromHostPtrCalledThenCopyRequestedRegionAndOriginOnly) { + createImageAndSetTestParams(); + EXPECT_NE(hostPtrSlicePitch, imageSlicePitch); + EXPECT_NE(hostPtrRowPitch, imageRowPitch); + EXPECT_NE(image->getCpuAddress(), image->getHostPtr()); + + std::unique_ptr expectedImageData(new uint8_t[imageSlicePitch * imgDesc->image_depth]); + memset(image->getHostPtr(), 123, hostPtrSlicePitch * imgDesc->image_depth); + memset(expectedImageData.get(), 0, imageSlicePitch * imgDesc->image_depth); + memset(image->getCpuAddress(), 0, imageSlicePitch * imgDesc->image_depth); + + setExpectedData(expectedImageData.get(), imageSlicePitch, imageRowPitch); + + image->transferDataFromHostPtr(copyRegion, copyOrigin); + + EXPECT_TRUE(memcmp(image->getCpuAddress(), expectedImageData.get(), imageSlicePitch * imgDesc->image_depth) == 0); +} + +TEST_F(ImageHostPtrTransferTests, given2dArrayImageWhenTransferToHostPtrCalledThenCopyRequestedRegionAndOriginOnly) { + createImageAndSetTestParams(); + EXPECT_NE(hostPtrSlicePitch, imageSlicePitch); + EXPECT_NE(hostPtrRowPitch, imageRowPitch); + EXPECT_NE(image->getCpuAddress(), image->getHostPtr()); + + std::unique_ptr expectedHostPtr(new uint8_t[hostPtrSlicePitch * imgDesc->image_depth]); + memset(image->getHostPtr(), 0, hostPtrSlicePitch * imgDesc->image_depth); + memset(expectedHostPtr.get(), 0, hostPtrSlicePitch * imgDesc->image_depth); + memset(image->getCpuAddress(), 123, imageSlicePitch * imgDesc->image_depth); + + setExpectedData(expectedHostPtr.get(), hostPtrSlicePitch, hostPtrRowPitch); + + image->transferDataToHostPtr(copyRegion, copyOrigin); + + EXPECT_TRUE(memcmp(image->getHostPtr(), expectedHostPtr.get(), hostPtrSlicePitch * imgDesc->image_depth) == 0); +} + +TEST_F(ImageHostPtrTransferTests, given2dArrayImageWhenTransferFromHostPtrCalledThenCopyRequestedRegionAndOriginOnly) { + createImageAndSetTestParams(); + EXPECT_NE(hostPtrSlicePitch, imageSlicePitch); + EXPECT_NE(hostPtrRowPitch, imageRowPitch); + EXPECT_NE(image->getCpuAddress(), image->getHostPtr()); + + std::unique_ptr expectedImageData(new uint8_t[imageSlicePitch * imgDesc->image_depth]); + memset(image->getHostPtr(), 123, hostPtrSlicePitch * imgDesc->image_depth); + memset(expectedImageData.get(), 0, imageSlicePitch * imgDesc->image_depth); + memset(image->getCpuAddress(), 0, imageSlicePitch * imgDesc->image_depth); + + setExpectedData(expectedImageData.get(), imageSlicePitch, imageRowPitch); + + image->transferDataFromHostPtr(copyRegion, copyOrigin); + + EXPECT_TRUE(memcmp(image->getCpuAddress(), expectedImageData.get(), imageSlicePitch * imgDesc->image_depth) == 0); +} diff --git a/unit_tests/mem_obj/mem_obj_tests.cpp b/unit_tests/mem_obj/mem_obj_tests.cpp index 53fd4a16bb..7b6debc0ba 100644 --- a/unit_tests/mem_obj/mem_obj_tests.cpp +++ b/unit_tests/mem_obj/mem_obj_tests.cpp @@ -63,15 +63,38 @@ TEST(MemObj, GivenMemObjWhenInititalizedFromHostPtrThenInitializeFields) { EXPECT_EQ(0u, memObj.getMappedOffset()); } -TEST(MemObj, GivenMemObjectWhenAskedForTransferDataThenNullPtrIsReturned) { - char buffer[64]; +TEST(MemObj, givenMemObjectWhenAskedForTransferToHostPtrThenDoNothing) { + const size_t size = 64; + uint8_t hostPtr[size] = {}; + uint8_t expectedHostPtr[size] = {}; MockContext context; - MockGraphicsAllocation *mockAllocation = new MockGraphicsAllocation(buffer, sizeof(buffer)); + MockGraphicsAllocation *mockAllocation = new MockGraphicsAllocation(hostPtr, sizeof(hostPtr)); MemObj memObj(&context, CL_MEM_OBJECT_BUFFER, CL_MEM_USE_HOST_PTR, - sizeof(buffer), buffer, buffer, mockAllocation, true, false, false); + size, hostPtr, hostPtr, mockAllocation, true, false, false); - auto ptr = memObj.transferDataToHostPtr(); - EXPECT_EQ(nullptr, ptr); + memset(memObj.getCpuAddress(), 123, size); + memset(hostPtr, 0, size); + + EXPECT_THROW(memObj.transferDataToHostPtr({{size, 0, 0}}, {{0, 0, 0}}), std::exception); + + EXPECT_TRUE(memcmp(hostPtr, expectedHostPtr, size) == 0); +} + +TEST(MemObj, givenMemObjectWhenAskedForTransferFromHostPtrThenDoNothing) { + const size_t size = 64; + uint8_t hostPtr[size] = {}; + uint8_t expectedBufferPtr[size] = {}; + MockContext context; + MockGraphicsAllocation *mockAllocation = new MockGraphicsAllocation(hostPtr, sizeof(hostPtr)); + MemObj memObj(&context, CL_MEM_OBJECT_PIPE, CL_MEM_USE_HOST_PTR, + size, hostPtr, hostPtr, mockAllocation, true, false, false); + + memset(memObj.getCpuAddress(), 123, size); + memset(expectedBufferPtr, 123, size); + + EXPECT_THROW(memObj.transferDataFromHostPtr({{size, 0, 0}}, {{0, 0, 0}}), std::exception); + + EXPECT_TRUE(memcmp(memObj.getCpuAddress(), expectedBufferPtr, size) == 0); } TEST(MemObj, givenMemObjWhenAllocatedMappedPtrIsSetThenGetMappedPtrIsDifferentThanAllocatedMappedPtr) { diff --git a/unit_tests/mocks/mock_gmm_resource_info.cpp b/unit_tests/mocks/mock_gmm_resource_info.cpp index a009641928..34f87feadc 100644 --- a/unit_tests/mocks/mock_gmm_resource_info.cpp +++ b/unit_tests/mocks/mock_gmm_resource_info.cpp @@ -67,6 +67,9 @@ void MockGmmResourceInfo::setupDefaultActions() { reqOffsetInfo.Render.XOffset = 32; reqOffsetInfo.Render.Offset = 64; } + if (reqOffsetInfo.Slice == 1) { + reqOffsetInfo.Render.YOffset = mockResourceCreateParams.BaseHeight; + } return GMM_SUCCESS; }));