diff --git a/Jenkinsfile b/Jenkinsfile index e8db9ce8e6..2810b336c8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,4 +2,4 @@ neoDependenciesRev='735095-769' strategy='EQUAL' allowedF=42 -allowedCD=340 +allowedCD=338 diff --git a/runtime/api/api.cpp b/runtime/api/api.cpp index 1fcb7a2fa8..80c57dadcd 100644 --- a/runtime/api/api.cpp +++ b/runtime/api/api.cpp @@ -2483,9 +2483,6 @@ cl_int CL_API_CALL clEnqueueUnmapMemObject(cl_command_queue commandQueue, if (pMemObj->peekClMemObjType() == CL_MEM_OBJECT_PIPE) { return CL_INVALID_MEM_OBJECT; } - if (!mappedPtr || mappedPtr != pMemObj->getMappedPtr()) { - return CL_INVALID_VALUE; - } retVal = pCommandQueue->enqueueUnmapMemObject(pMemObj, mappedPtr, numEventsInWaitList, eventWaitList, event); } diff --git a/runtime/command_queue/command_queue.cpp b/runtime/command_queue/command_queue.cpp index 5e88010e33..65d3e16694 100644 --- a/runtime/command_queue/command_queue.cpp +++ b/runtime/command_queue/command_queue.cpp @@ -457,49 +457,75 @@ bool CommandQueue::sendPerfCountersConfig() { } cl_int CommandQueue::enqueueWriteMemObjForUnmap(MemObj *memObj, void *mappedPtr, EventsRequest &eventsRequest) { - cl_int retVal; - if (memObj->peekClMemObjType() == CL_MEM_OBJECT_BUFFER) { - auto buffer = castToObject(memObj); - retVal = enqueueWriteBuffer(buffer, CL_TRUE, buffer->getMappedOffset()[0], buffer->getMappedSize()[0], mappedPtr, - eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); - } else { - auto image = castToObject(memObj); - retVal = enqueueWriteImage(image, CL_FALSE, &image->getMappedOffset()[0], &image->getMappedSize()[0], - image->getHostPtrRowPitch(), image->getHostPtrSlicePitch(), mappedPtr, - eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); - bool mustCallFinish = true; - if (!(image->getFlags() & CL_MEM_USE_HOST_PTR)) { - mustCallFinish = true; - } else { - mustCallFinish = (CommandQueue::getTaskLevelFromWaitList(this->taskLevel, eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList) != Event::eventNotReady); - } - if (mustCallFinish) { - finish(true); - } + cl_int retVal = CL_SUCCESS; + + MapInfo unmapInfo; + if (!memObj->findMappedPtr(mappedPtr, unmapInfo)) { + return CL_INVALID_VALUE; } + if (!unmapInfo.readOnly) { + if (memObj->peekClMemObjType() == CL_MEM_OBJECT_BUFFER) { + auto buffer = castToObject(memObj); + retVal = enqueueWriteBuffer(buffer, CL_TRUE, unmapInfo.offset[0], unmapInfo.size[0], mappedPtr, + eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); + } else { + auto image = castToObject(memObj); + retVal = enqueueWriteImage(image, CL_FALSE, &unmapInfo.offset[0], &unmapInfo.size[0], + image->getHostPtrRowPitch(), image->getHostPtrSlicePitch(), mappedPtr, + eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); + bool mustCallFinish = true; + if (!(image->getFlags() & CL_MEM_USE_HOST_PTR)) { + mustCallFinish = true; + } else { + mustCallFinish = (CommandQueue::getTaskLevelFromWaitList(this->taskLevel, eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList) != Event::eventNotReady); + } + if (mustCallFinish) { + finish(true); + } + } + } else { + retVal = enqueueMarkerWithWaitList(eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); + } + + if (retVal == CL_SUCCESS) { + memObj->removeMappedPtr(mappedPtr); + if (eventsRequest.outEvent) { + auto event = castToObject(*eventsRequest.outEvent); + event->setCmdType(CL_COMMAND_UNMAP_MEM_OBJECT); + } + } return retVal; } void *CommandQueue::enqueueReadMemObjForMap(TransferProperties &transferProperties, EventsRequest &eventsRequest, cl_int &errcodeRet) { void *returnPtr = ptrOffset(transferProperties.memObj->getBasePtrForMap(), - transferProperties.memObj->calculateOffsetForMapping(transferProperties.offsetPtr)); + transferProperties.memObj->calculateOffsetForMapping(transferProperties.offset)); + + if (!transferProperties.memObj->addMappedPtr(returnPtr, transferProperties.memObj->calculateMappedPtrLength(transferProperties.size), + transferProperties.mapFlags, transferProperties.size, transferProperties.offset)) { + errcodeRet = CL_INVALID_OPERATION; + return nullptr; + } if (transferProperties.memObj->peekClMemObjType() == CL_MEM_OBJECT_BUFFER) { auto buffer = castToObject(transferProperties.memObj); - errcodeRet = enqueueReadBuffer(buffer, transferProperties.blocking, *transferProperties.offsetPtr, *transferProperties.sizePtr, returnPtr, + errcodeRet = enqueueReadBuffer(buffer, transferProperties.blocking, transferProperties.offset[0], transferProperties.size[0], returnPtr, eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); } else { auto image = castToObject(transferProperties.memObj); - errcodeRet = enqueueReadImage(image, transferProperties.blocking, transferProperties.offsetPtr, transferProperties.sizePtr, + errcodeRet = enqueueReadImage(image, transferProperties.blocking, &transferProperties.offset[0], &transferProperties.size[0], image->getHostPtrRowPitch(), image->getHostPtrSlicePitch(), returnPtr, eventsRequest.numEventsInWaitList, eventsRequest.eventWaitList, eventsRequest.outEvent); } - if (errcodeRet == CL_SUCCESS) { - transferProperties.memObj->setMapInfo(returnPtr, transferProperties.sizePtr, transferProperties.offsetPtr); - } else { - returnPtr = nullptr; + if (errcodeRet != CL_SUCCESS) { + transferProperties.memObj->removeMappedPtr(returnPtr); + return nullptr; + } + if (eventsRequest.outEvent) { + auto event = castToObject(*eventsRequest.outEvent); + event->setCmdType(transferProperties.cmdType); } return returnPtr; } @@ -528,7 +554,7 @@ void *CommandQueue::enqueueMapBuffer(Buffer *buffer, cl_bool blockingMap, const cl_event *eventWaitList, cl_event *event, cl_int &errcodeRet) { - TransferProperties transferProperties(buffer, CL_COMMAND_MAP_BUFFER, blockingMap != CL_FALSE, &offset, &size, nullptr); + TransferProperties transferProperties(buffer, CL_COMMAND_MAP_BUFFER, mapFlags, blockingMap != CL_FALSE, &offset, &size, nullptr); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); return enqueueMapMemObject(transferProperties, eventsRequest, errcodeRet); @@ -542,7 +568,7 @@ void *CommandQueue::enqueueMapImage(Image *image, cl_bool blockingMap, const cl_event *eventWaitList, cl_event *event, cl_int &errcodeRet) { - TransferProperties transferProperties(image, CL_COMMAND_MAP_IMAGE, blockingMap != CL_FALSE, + TransferProperties transferProperties(image, CL_COMMAND_MAP_IMAGE, mapFlags, blockingMap != CL_FALSE, const_cast(origin), const_cast(region), nullptr); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); @@ -559,7 +585,7 @@ void *CommandQueue::enqueueMapImage(Image *image, cl_bool blockingMap, cl_int CommandQueue::enqueueUnmapMemObject(MemObj *memObj, void *mappedPtr, cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) { - TransferProperties transferProperties(memObj, CL_COMMAND_UNMAP_MEM_OBJECT, false, nullptr, nullptr, mappedPtr); + TransferProperties transferProperties(memObj, CL_COMMAND_UNMAP_MEM_OBJECT, 0, false, nullptr, nullptr, mappedPtr); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); return enqueueUnmapMemObject(transferProperties, eventsRequest); @@ -569,6 +595,9 @@ void CommandQueue::enqueueBlockedMapUnmapOperation(const cl_event *eventWaitList size_t numEventsInWaitlist, MapOperationType opType, MemObj *memObj, + MemObjSizeArray ©Size, + MemObjOffsetArray ©Offset, + bool readOnly, EventBuilder &externalEventBuilder) { auto &commandStreamReceiver = device->getCommandStreamReceiver(); @@ -585,7 +614,7 @@ void CommandQueue::enqueueBlockedMapUnmapOperation(const cl_event *eventWaitList } //store task data in event - auto cmd = std::unique_ptr(new CommandMapUnmap(opType, *memObj, commandStreamReceiver, *this)); + auto cmd = std::unique_ptr(new CommandMapUnmap(opType, *memObj, copySize, copyOffset, readOnly, commandStreamReceiver, *this)); eventBuilder->getEvent()->setCommand(std::move(cmd)); //bind output event with input events diff --git a/runtime/command_queue/command_queue.h b/runtime/command_queue/command_queue.h index fde350c2aa..14cf62b060 100644 --- a/runtime/command_queue/command_queue.h +++ b/runtime/command_queue/command_queue.h @@ -385,6 +385,9 @@ class CommandQueue : public BaseObject<_cl_command_queue> { size_t numEventsInWaitlist, MapOperationType opType, MemObj *memObj, + MemObjSizeArray ©Size, + MemObjOffsetArray ©Offset, + bool readOnly, EventBuilder &externalEventBuilder); // taskCount of last task diff --git a/runtime/command_queue/cpu_data_transfer_handler.cpp b/runtime/command_queue/cpu_data_transfer_handler.cpp index bcd45f0d8b..015319b5f2 100644 --- a/runtime/command_queue/cpu_data_transfer_handler.cpp +++ b/runtime/command_queue/cpu_data_transfer_handler.cpp @@ -30,12 +30,30 @@ namespace OCLRT { void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferProperties, EventsRequest &eventsRequest, cl_int &retVal) { + MapInfo unmapInfo; void *returnPtr = nullptr; EventBuilder eventBuilder; bool eventCompleted = false; + bool mapOperation = transferProperties.cmdType == CL_COMMAND_MAP_BUFFER || transferProperties.cmdType == CL_COMMAND_MAP_IMAGE; + auto image = castToObject(transferProperties.memObj); ErrorCodeHelper err(&retVal, CL_SUCCESS); - auto image = castToObject(transferProperties.memObj); + if (mapOperation) { + returnPtr = ptrOffset(transferProperties.memObj->getCpuAddressForMapping(), + transferProperties.memObj->calculateOffsetForMapping(transferProperties.offset)); + + if (!transferProperties.memObj->addMappedPtr(returnPtr, transferProperties.memObj->calculateMappedPtrLength(transferProperties.size), + transferProperties.mapFlags, transferProperties.size, transferProperties.offset)) { + err.set(CL_INVALID_OPERATION); + return nullptr; + } + } else if (transferProperties.cmdType == CL_COMMAND_UNMAP_MEM_OBJECT) { + if (!transferProperties.memObj->findMappedPtr(transferProperties.ptr, unmapInfo)) { + err.set(CL_INVALID_VALUE); + return nullptr; + } + transferProperties.memObj->removeMappedPtr(unmapInfo.ptr); + } if (eventsRequest.outEvent) { eventBuilder.create(this, transferProperties.cmdType, Event::eventNotReady, Event::eventNotReady); @@ -62,10 +80,14 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie transferProperties.cmdType == CL_COMMAND_MAP_IMAGE || transferProperties.cmdType == CL_COMMAND_UNMAP_MEM_OBJECT)) { + // Pass size and offset only. Unblocked command will call transferData(size, offset) method enqueueBlockedMapUnmapOperation(eventsRequest.eventWaitList, static_cast(eventsRequest.numEventsInWaitList), - transferProperties.cmdType == CL_COMMAND_UNMAP_MEM_OBJECT ? UNMAP : MAP, + mapOperation ? MAP : UNMAP, transferProperties.memObj, + mapOperation ? transferProperties.size : unmapInfo.size, + mapOperation ? transferProperties.offset : unmapInfo.offset, + mapOperation ? transferProperties.mapFlags == CL_MAP_READ : unmapInfo.readOnly, eventBuilder); } @@ -94,40 +116,30 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie switch (transferProperties.cmdType) { case CL_COMMAND_MAP_BUFFER: if (!transferProperties.memObj->isMemObjZeroCopy()) { - transferProperties.memObj->transferDataToHostPtr({{transferProperties.memObj->getSize(), 0, 0}}, {{0, 0, 0}}); + transferProperties.memObj->transferDataToHostPtr(transferProperties.size, transferProperties.offset); eventCompleted = true; } break; case CL_COMMAND_MAP_IMAGE: if (!image->isMemObjZeroCopy()) { - 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}}); + image->transferDataToHostPtr(transferProperties.size, transferProperties.offset); eventCompleted = true; } break; case CL_COMMAND_UNMAP_MEM_OBJECT: if (!transferProperties.memObj->isMemObjZeroCopy()) { - 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)))}}; + if (!unmapInfo.readOnly) { + transferProperties.memObj->transferDataFromHostPtr(unmapInfo.size, unmapInfo.offset); } - transferProperties.memObj->transferDataFromHostPtr(copySize, {{0, 0, 0}}); eventCompleted = true; } - transferProperties.memObj->decMapCount(); break; case CL_COMMAND_READ_BUFFER: - memcpy_s(transferProperties.ptr, *transferProperties.sizePtr, ptrOffset(transferProperties.memObj->getCpuAddressForMemoryTransfer(), *transferProperties.offsetPtr), *transferProperties.sizePtr); + memcpy_s(transferProperties.ptr, transferProperties.size[0], ptrOffset(transferProperties.memObj->getCpuAddressForMemoryTransfer(), transferProperties.offset[0]), transferProperties.size[0]); eventCompleted = true; break; case CL_COMMAND_WRITE_BUFFER: - memcpy_s(ptrOffset(transferProperties.memObj->getCpuAddressForMemoryTransfer(), *transferProperties.offsetPtr), *transferProperties.sizePtr, transferProperties.ptr, *transferProperties.sizePtr); + memcpy_s(ptrOffset(transferProperties.memObj->getCpuAddressForMemoryTransfer(), transferProperties.offset[0]), transferProperties.size[0], transferProperties.ptr, transferProperties.size[0]); eventCompleted = true; break; case CL_COMMAND_MARKER: @@ -150,12 +162,6 @@ void *CommandQueue::cpuDataTransferHandler(TransferProperties &transferPropertie providePerformanceHint(transferProperties); } - if (transferProperties.cmdType == CL_COMMAND_MAP_BUFFER || transferProperties.cmdType == CL_COMMAND_MAP_IMAGE) { - returnPtr = ptrOffset(transferProperties.memObj->getCpuAddressForMapping(), - transferProperties.memObj->calculateOffsetForMapping(transferProperties.offsetPtr)); - transferProperties.memObj->setMapInfo(returnPtr, transferProperties.sizePtr, transferProperties.offsetPtr); - } - return returnPtr; // only map returns pointer } diff --git a/runtime/command_queue/enqueue_read_buffer.h b/runtime/command_queue/enqueue_read_buffer.h index 596a386897..33734e2254 100644 --- a/runtime/command_queue/enqueue_read_buffer.h +++ b/runtime/command_queue/enqueue_read_buffer.h @@ -51,7 +51,7 @@ cl_int CommandQueueHw::enqueueReadBuffer( buffer->isReadWriteOnCpuAllowed(blockingRead, numEventsInWaitList, ptr, size)) && context->getDevice(0)->getDeviceInfo().cpuCopyAllowed) { if (!isMemTransferNeeded) { - TransferProperties transferProperties(buffer, CL_COMMAND_MARKER, true, &offset, &size, ptr); + TransferProperties transferProperties(buffer, CL_COMMAND_MARKER, 0, true, &offset, &size, ptr); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); cpuDataTransferHandler(transferProperties, eventsRequest, retVal); if (event) { @@ -64,7 +64,7 @@ cl_int CommandQueueHw::enqueueReadBuffer( } return retVal; } - TransferProperties transferProperties(buffer, CL_COMMAND_READ_BUFFER, true, &offset, &size, ptr); + TransferProperties transferProperties(buffer, CL_COMMAND_READ_BUFFER, 0, true, &offset, &size, ptr); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); cpuDataTransferHandler(transferProperties, eventsRequest, retVal); diff --git a/runtime/command_queue/enqueue_write_buffer.h b/runtime/command_queue/enqueue_write_buffer.h index 227aa3d316..1c3dce7a81 100644 --- a/runtime/command_queue/enqueue_write_buffer.h +++ b/runtime/command_queue/enqueue_write_buffer.h @@ -50,7 +50,7 @@ cl_int CommandQueueHw::enqueueWriteBuffer( buffer->isReadWriteOnCpuAllowed(blockingWrite, numEventsInWaitList, const_cast(ptr), size)) && context->getDevice(0)->getDeviceInfo().cpuCopyAllowed) { if (!isMemTransferNeeded) { - TransferProperties transferProperties(buffer, CL_COMMAND_MARKER, true, &offset, &size, const_cast(ptr)); + TransferProperties transferProperties(buffer, CL_COMMAND_MARKER, 0, true, &offset, &size, const_cast(ptr)); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); cpuDataTransferHandler(transferProperties, eventsRequest, retVal); @@ -64,7 +64,7 @@ cl_int CommandQueueHw::enqueueWriteBuffer( } return retVal; } - TransferProperties transferProperties(buffer, CL_COMMAND_WRITE_BUFFER, true, &offset, &size, const_cast(ptr)); + TransferProperties transferProperties(buffer, CL_COMMAND_WRITE_BUFFER, 0, true, &offset, &size, const_cast(ptr)); EventsRequest eventsRequest(numEventsInWaitList, eventWaitList, event); cpuDataTransferHandler(transferProperties, eventsRequest, retVal); diff --git a/runtime/helpers/CMakeLists.txt b/runtime/helpers/CMakeLists.txt index 7f68932413..70845f2880 100644 --- a/runtime/helpers/CMakeLists.txt +++ b/runtime/helpers/CMakeLists.txt @@ -61,6 +61,7 @@ set(RUNTIME_SRCS_HELPERS_BASE ${CMAKE_CURRENT_SOURCE_DIR}/preamble.h ${CMAKE_CURRENT_SOURCE_DIR}/preamble.inl ${CMAKE_CURRENT_SOURCE_DIR}/properties_helper.h + ${CMAKE_CURRENT_SOURCE_DIR}/properties_helper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ptr_math.h ${CMAKE_CURRENT_SOURCE_DIR}/queue_helpers.h ${CMAKE_CURRENT_SOURCE_DIR}/sampler_helpers.h diff --git a/runtime/helpers/properties_helper.cpp b/runtime/helpers/properties_helper.cpp new file mode 100644 index 0000000000..636484ddeb --- /dev/null +++ b/runtime/helpers/properties_helper.cpp @@ -0,0 +1,42 @@ +/* +* 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/properties_helper.h" +#include "runtime/mem_obj/mem_obj.h" + +namespace OCLRT { +TransferProperties::TransferProperties(MemObj *memObj, cl_command_type cmdType, cl_map_flags mapFlags, bool blocking, + size_t *offsetPtr, size_t *sizePtr, void *ptr) + : memObj(memObj), cmdType(cmdType), mapFlags(mapFlags), blocking(blocking), ptr(ptr) { + + // no size or offset passed for unmap operation + if (cmdType != CL_COMMAND_UNMAP_MEM_OBJECT) { + if (memObj->peekClMemObjType() == CL_MEM_OBJECT_BUFFER) { + size[0] = *sizePtr; + offset[0] = *offsetPtr; + } else { + size = {{sizePtr[0], sizePtr[1], sizePtr[2]}}; + offset = {{offsetPtr[0], offsetPtr[1], offsetPtr[2]}}; + } + } +} +} // namespace OCLRT diff --git a/runtime/helpers/properties_helper.h b/runtime/helpers/properties_helper.h index a514cc8323..3ad7b99d62 100644 --- a/runtime/helpers/properties_helper.h +++ b/runtime/helpers/properties_helper.h @@ -45,27 +45,32 @@ struct EventsRequest { cl_event *outEvent; }; +using MemObjSizeArray = std::array; +using MemObjOffsetArray = std::array; + struct TransferProperties { TransferProperties() = delete; - TransferProperties(MemObj *memObj, cl_command_type cmdType, bool blocking, size_t *offsetPtr, size_t *sizePtr, void *ptr) - : memObj(memObj), cmdType(cmdType), blocking(blocking), offsetPtr(offsetPtr), sizePtr(sizePtr), ptr(ptr){}; + TransferProperties(MemObj *memObj, cl_command_type cmdType, cl_map_flags mapFlags, bool blocking, size_t *offsetPtr, size_t *sizePtr, + void *ptr); MemObj *memObj; cl_command_type cmdType; + cl_map_flags mapFlags; bool blocking; - size_t *offsetPtr; - size_t *sizePtr; + MemObjOffsetArray offset = {{0, 0, 0}}; + MemObjSizeArray size = {{0, 0, 0}}; void *ptr; }; struct MapInfo { - using SizeArray = std::array; - using OffsetArray = std::array; + MapInfo() = default; + MapInfo(void *ptr, size_t ptrLength, MemObjSizeArray size, MemObjOffsetArray offset) : ptr(ptr), ptrLength(ptrLength), size(size), offset(offset) {} void *ptr = nullptr; - SizeArray size = {{0, 0, 0}}; - OffsetArray offset = {{0, 0, 0}}; + size_t ptrLength = 0; + MemObjSizeArray size = {{0, 0, 0}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + bool readOnly = false; }; - } // namespace OCLRT diff --git a/runtime/helpers/task_information.cpp b/runtime/helpers/task_information.cpp index 0eb63e2bbe..3ac7a36a53 100644 --- a/runtime/helpers/task_information.cpp +++ b/runtime/helpers/task_information.cpp @@ -27,7 +27,7 @@ #include "runtime/device/device.h" #include "runtime/device_queue/device_queue.h" #include "runtime/gtpin/gtpin_notify.h" -#include "runtime/mem_obj/image.h" +#include "runtime/mem_obj/mem_obj.h" #include "runtime/memory_manager/surface.h" #include "runtime/helpers/aligned_memory.h" #include "runtime/helpers/string.h" @@ -46,8 +46,9 @@ KernelOperation::~KernelOperation() { alignedFree(commandStream->getBase()); } -CommandMapUnmap::CommandMapUnmap(MapOperationType op, MemObj &memObj, CommandStreamReceiver &csr, CommandQueue &cmdQ) - : memObj(memObj), csr(csr), cmdQ(cmdQ), op(op) { +CommandMapUnmap::CommandMapUnmap(MapOperationType op, MemObj &memObj, MemObjSizeArray ©Size, MemObjOffsetArray ©Offset, bool readOnly, + CommandStreamReceiver &csr, CommandQueue &cmdQ) + : memObj(memObj), copySize(copySize), copyOffset(copyOffset), readOnly(readOnly), csr(csr), cmdQ(cmdQ), op(op) { memObj.incRefInternal(); } @@ -91,21 +92,11 @@ CompletionStamp &CommandMapUnmap::submit(uint32_t taskLevel, bool terminated) { cmdQ.waitUntilComplete(completionStamp.taskCount, completionStamp.flushStamp); 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(copySize, {{0, 0, 0}}); - } else { + memObj.transferDataToHostPtr(copySize, copyOffset); + } else if (!readOnly) { DEBUG_BREAK_IF(op != UNMAP); - memObj.transferDataFromHostPtr(copySize, {{0, 0, 0}}); + memObj.transferDataFromHostPtr(copySize, copyOffset); } } diff --git a/runtime/helpers/task_information.h b/runtime/helpers/task_information.h index 51ecb86f9c..d535f63b4c 100644 --- a/runtime/helpers/task_information.h +++ b/runtime/helpers/task_information.h @@ -25,6 +25,7 @@ #include "runtime/indirect_heap/indirect_heap.h" #include "runtime/utilities/iflist.h" #include "runtime/helpers//completion_stamp.h" +#include "runtime/helpers/properties_helper.h" #include #include @@ -59,12 +60,16 @@ class Command : public IFNode { class CommandMapUnmap : public Command { public: - CommandMapUnmap(MapOperationType op, MemObj &memObj, CommandStreamReceiver &csr, CommandQueue &cmdQ); + CommandMapUnmap(MapOperationType op, MemObj &memObj, MemObjSizeArray ©Size, MemObjOffsetArray ©Offset, bool readOnly, + CommandStreamReceiver &csr, CommandQueue &cmdQ); ~CommandMapUnmap() override; CompletionStamp &submit(uint32_t taskLevel, bool terminated) override; private: MemObj &memObj; + MemObjSizeArray copySize; + MemObjOffsetArray copyOffset; + bool readOnly; CommandStreamReceiver &csr; CommandQueue &cmdQ; MapOperationType op; diff --git a/runtime/mem_obj/CMakeLists.txt b/runtime/mem_obj/CMakeLists.txt index 6a6949b2f7..5329bcf3f7 100644 --- a/runtime/mem_obj/CMakeLists.txt +++ b/runtime/mem_obj/CMakeLists.txt @@ -28,6 +28,8 @@ set(RUNTIME_SRCS_MEM_OBJ ${CMAKE_CURRENT_SOURCE_DIR}/image.h ${CMAKE_CURRENT_SOURCE_DIR}/image.inl ${CMAKE_CURRENT_SOURCE_DIR}/image_factory_init.inl + ${CMAKE_CURRENT_SOURCE_DIR}/map_operations_handler.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/map_operations_handler.h ${CMAKE_CURRENT_SOURCE_DIR}/mem_obj.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mem_obj.h ${CMAKE_CURRENT_SOURCE_DIR}/pipe.cpp diff --git a/runtime/mem_obj/buffer.cpp b/runtime/mem_obj/buffer.cpp index 60f3aae898..c0b51c5840 100644 --- a/runtime/mem_obj/buffer.cpp +++ b/runtime/mem_obj/buffer.cpp @@ -298,11 +298,11 @@ void Buffer::transferData(void *dst, void *src, size_t copySize, size_t copyOffs memcpy_s(dstPtr, copySize, srcPtr, copySize); } -void Buffer::transferDataToHostPtr(std::array copySize, std::array copyOffset) { +void Buffer::transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) { transferData(hostPtr, memoryStorage, copySize[0], copyOffset[0]); } -void Buffer::transferDataFromHostPtr(std::array copySize, std::array copyOffset) { +void Buffer::transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) { transferData(memoryStorage, hostPtr, copySize[0], copyOffset[0]); } diff --git a/runtime/mem_obj/buffer.h b/runtime/mem_obj/buffer.h index 1a0ac6f949..14090be97c 100644 --- a/runtime/mem_obj/buffer.h +++ b/runtime/mem_obj/buffer.h @@ -100,8 +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(std::array copySize, std::array copyOffset) override; - void transferDataFromHostPtr(std::array copySize, std::array copyOffset) override; + void transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override; + void transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override; bool isReadWriteOnCpuAllowed(cl_bool blocking, cl_uint numEventsInWaitList, void *ptr, size_t size); diff --git a/runtime/mem_obj/image.cpp b/runtime/mem_obj/image.cpp index b9865137c6..8c591d92ab 100644 --- a/runtime/mem_obj/image.cpp +++ b/runtime/mem_obj/image.cpp @@ -842,13 +842,13 @@ Image *Image::redescribe() { return image; } -void Image::transferDataToHostPtr(std::array copySize, std::array copyOffset) { +void Image::transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) { transferData(hostPtr, hostPtrRowPitch, hostPtrSlicePitch, graphicsAllocation->getUnderlyingBuffer(), imageDesc.image_row_pitch, imageDesc.image_slice_pitch, copySize, copyOffset); } -void Image::transferDataFromHostPtr(std::array copySize, std::array copyOffset) { +void Image::transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) { transferData(memoryStorage, imageDesc.image_row_pitch, imageDesc.image_slice_pitch, hostPtr, hostPtrRowPitch, hostPtrSlicePitch, copySize, copyOffset); @@ -1189,7 +1189,7 @@ bool Image::hasAlphaChannel(const cl_image_format *imageFormat) { (channelOrder == CL_ABGR); } -size_t Image::calculateOffsetForMapping(size_t *origin) const { +size_t Image::calculateOffsetForMapping(const MemObjOffsetArray &origin) const { size_t rowPitch = mappingOnCpuAllowed() ? imageDesc.image_row_pitch : getHostPtrRowPitch(); size_t slicePitch = mappingOnCpuAllowed() ? imageDesc.image_slice_pitch : getHostPtrSlicePitch(); diff --git a/runtime/mem_obj/image.h b/runtime/mem_obj/image.h index 8a5ecd1d2f..1514a628fb 100644 --- a/runtime/mem_obj/image.h +++ b/runtime/mem_obj/image.h @@ -133,8 +133,8 @@ class Image : public MemObj { const cl_image_format &getImageFormat() const; const SurfaceFormatInfo &getSurfaceFormatInfo() const; - void transferDataToHostPtr(std::array copySize, std::array copyOffset) override; - void transferDataFromHostPtr(std::array copySize, std::array copyOffset) override; + void transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override; + void transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override; Image *redescribe(); Image *redescribeFillImage(); @@ -171,7 +171,7 @@ class Image : public MemObj { cl_int writeNV12Planes(const void *hostPtr, size_t hostPtrRowPitch); void setMcsSurfaceInfo(McsSurfaceInfo &info) { mcsSurfaceInfo = info; } const McsSurfaceInfo &getMcsSurfaceInfo() { return mcsSurfaceInfo; } - size_t calculateOffsetForMapping(size_t *origin) const override; + size_t calculateOffsetForMapping(const MemObjOffsetArray &origin) const override; const bool isTiledImage; @@ -190,9 +190,6 @@ class Image : public MemObj { const SurfaceFormatInfo *surfaceFormatInfo = nullptr, const SurfaceOffsets *surfaceOffsets = nullptr); - void setMappedOffset(size_t *offset) override { mapInfo.offset = {{offset[0], offset[1], offset[2]}}; } - void setMappedSize(size_t *size) override { mapInfo.size = {{size[0], size[1], size[2]}}; } - void getOsSpecificImageInfo(const cl_mem_info ¶mName, size_t *srcParamSize, void **srcParam); void transferData(void *dst, size_t dstRowPitch, size_t dstSlicePitch, diff --git a/runtime/mem_obj/map_operations_handler.cpp b/runtime/mem_obj/map_operations_handler.cpp new file mode 100644 index 0000000000..4a1911d5f0 --- /dev/null +++ b/runtime/mem_obj/map_operations_handler.cpp @@ -0,0 +1,88 @@ +/* + * 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/mem_obj/map_operations_handler.h" +#include "runtime/helpers/ptr_math.h" + +using namespace OCLRT; + +size_t MapOperationsHandler::size() const { + std::lock_guard lock(mtx); + return mappedPointers.size(); +} + +bool MapOperationsHandler::add(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset) { + std::lock_guard lock(mtx); + MapInfo mapInfo(ptr, ptrLength, size, offset); + mapInfo.readOnly = (mapFlags == CL_MAP_READ); + + if (isOverlapping(mapInfo)) { + return false; + } + + mappedPointers.push_back(mapInfo); + return true; +} + +bool MapOperationsHandler::isOverlapping(MapInfo &inputMapInfo) { + if (inputMapInfo.readOnly) { + return false; + } + auto inputStartPtr = inputMapInfo.ptr; + auto inputEndPtr = ptrOffset(inputStartPtr, inputMapInfo.ptrLength); + + for (auto &mapInfo : mappedPointers) { + auto mappedStartPtr = mapInfo.ptr; + auto mappedEndPtr = ptrOffset(mappedStartPtr, mapInfo.ptrLength); + + // Requested ptr starts before or inside existing ptr range and overlapping end + if (inputStartPtr < mappedEndPtr && inputEndPtr >= mappedStartPtr) { + return true; + } + } + return false; +} + +bool MapOperationsHandler::find(void *mappedPtr, MapInfo &outMapInfo) { + std::lock_guard lock(mtx); + + for (auto &mapInfo : mappedPointers) { + if (mapInfo.ptr == mappedPtr) { + outMapInfo = mapInfo; + return true; + } + } + return false; +} + +void MapOperationsHandler::remove(void *mappedPtr) { + std::lock_guard lock(mtx); + + auto endIter = mappedPointers.end(); + for (auto it = mappedPointers.begin(); it != endIter; it++) { + if (it->ptr == mappedPtr) { + std::iter_swap(it, mappedPointers.end() - 1); + mappedPointers.pop_back(); + break; + } + } +} diff --git a/runtime/mem_obj/map_operations_handler.h b/runtime/mem_obj/map_operations_handler.h new file mode 100644 index 0000000000..353ff85474 --- /dev/null +++ b/runtime/mem_obj/map_operations_handler.h @@ -0,0 +1,46 @@ +/* + * 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/helpers/properties_helper.h" + +#include +#include + +namespace OCLRT { + +class MapOperationsHandler { + public: + virtual ~MapOperationsHandler() = default; + + bool add(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset); + void remove(void *mappedPtr); + bool find(void *mappedPtr, MapInfo &outMapInfo); + size_t size() const; + + protected: + bool isOverlapping(MapInfo &inputMapInfo); + std::vector mappedPointers; + mutable std::mutex mtx; +}; + +} // namespace OCLRT diff --git a/runtime/mem_obj/mem_obj.cpp b/runtime/mem_obj/mem_obj.cpp index ee8c675806..8c480c4922 100644 --- a/runtime/mem_obj/mem_obj.cpp +++ b/runtime/mem_obj/mem_obj.cpp @@ -59,7 +59,7 @@ MemObj::~MemObj() { if (allocatedMapPtr != nullptr) { needWait = true; } - if (mapInfo.ptr && !getCpuAddressForMapping()) { + if (mapOperationsHandler.size() > 0 && !getCpuAddressForMapping()) { needWait = true; } if (!destructorCallbacks.empty()) { @@ -112,6 +112,7 @@ cl_int MemObj::getMemObjectInfo(cl_mem_info paramName, void *srcParam = nullptr; cl_bool usesSVMPointer; cl_uint refCnt = 0; + cl_uint mapCount = 0; cl_mem clAssociatedMemObject = static_cast(this->associatedMemObject); cl_context ctx = nullptr; @@ -160,6 +161,7 @@ cl_int MemObj::getMemObjectInfo(cl_mem_info paramName, case CL_MEM_MAP_COUNT: srcParamSize = sizeof(mapCount); + mapCount = static_cast(mapOperationsHandler.size()); srcParam = &mapCount; break; @@ -214,22 +216,10 @@ CompletionStamp MemObj::getCompletionStamp() const { return completionStamp; } -void MemObj::setMappedPtr(void *mappedPtr) { - mapInfo.ptr = mappedPtr; -} - void MemObj::setAllocatedMapPtr(void *allocatedMapPtr) { this->allocatedMapPtr = allocatedMapPtr; } -void MemObj::incMapCount() { - this->mapCount++; -}; - -void MemObj::decMapCount() { - this->mapCount--; -}; - cl_mem_flags MemObj::getFlags() const { return flags; } @@ -341,11 +331,7 @@ void *MemObj::getBasePtrForMap() { } } -void MemObj::setMapInfo(void *mappedPtr, size_t *size, size_t *offset) { - TakeOwnershipWrapper memObjOwnership(*this); - setMappedPtr(mappedPtr); - setMappedSize(size); - setMappedOffset(offset); - incMapCount(); +bool MemObj::addMappedPtr(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset) { + return mapOperationsHandler.add(ptr, ptrLength, mapFlags, size, offset); } } // namespace OCLRT diff --git a/runtime/mem_obj/mem_obj.h b/runtime/mem_obj/mem_obj.h index 5e7904b32b..2556447a4a 100644 --- a/runtime/mem_obj/mem_obj.h +++ b/runtime/mem_obj/mem_obj.h @@ -25,11 +25,10 @@ #include "runtime/helpers/base_object.h" #include "runtime/helpers/completion_stamp.h" #include "runtime/sharings/sharing.h" -#include "runtime/helpers/properties_helper.h" +#include "runtime/mem_obj/map_operations_handler.h" #include #include #include -#include namespace OCLRT { class GraphicsAllocation; @@ -76,25 +75,21 @@ class MemObj : public BaseObject<_cl_mem> { void setCompletionStamp(CompletionStamp completionStamp, Device *pDevice, CommandQueue *pCmdQ); CompletionStamp getCompletionStamp() const; - void setMapInfo(void *mappedPtr, size_t *size, size_t *offset); + bool addMappedPtr(void *ptr, size_t ptrLength, cl_map_flags &mapFlags, MemObjSizeArray &size, MemObjOffsetArray &offset); + bool findMappedPtr(void *mappedPtr, MapInfo &outMapInfo) { return mapOperationsHandler.find(mappedPtr, outMapInfo); } + void removeMappedPtr(void *mappedPtr) { return mapOperationsHandler.remove(mappedPtr); } void *getBasePtrForMap(); - void *getMappedPtr() const { return mapInfo.ptr; }; MOCKABLE_VIRTUAL void setAllocatedMapPtr(void *allocatedMapPtr); void *getAllocatedMapPtr() const { return allocatedMapPtr; } - MapInfo::SizeArray getMappedSize() const { return mapInfo.size; } - MapInfo::OffsetArray getMappedOffset() const { return mapInfo.offset; } - void setHostPtrMinSize(size_t size); void releaseAllocatedMapPtr(); - void incMapCount(); - void decMapCount(); bool isMemObjZeroCopy() const; bool isMemObjWithHostPtrSVM() const; - virtual void transferDataToHostPtr(std::array copySize, std::array copyOffset) { UNRECOVERABLE_IF(true); }; - virtual void transferDataFromHostPtr(std::array copySize, std::array copyOffset) { UNRECOVERABLE_IF(true); }; + virtual void transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) { UNRECOVERABLE_IF(true); }; + virtual void transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) { UNRECOVERABLE_IF(true); }; GraphicsAllocation *getGraphicsAllocation(); GraphicsAllocation *getMcsAllocation() { return mcsAllocation; } @@ -124,16 +119,13 @@ class MemObj : public BaseObject<_cl_mem> { void destroyGraphicsAllocation(GraphicsAllocation *allocation, bool asyncDestroy); bool checkIfMemoryTransferIsRequired(size_t offsetInMemObjest, size_t offsetInHostPtr, const void *ptr, cl_command_type cmdType); bool mappingOnCpuAllowed() const { return !allowTiling() && !peekSharingHandler(); } - virtual size_t calculateOffsetForMapping(size_t *offset) const { return *offset; } + virtual size_t calculateOffsetForMapping(const MemObjOffsetArray &offset) const { return offset[0]; } + size_t calculateMappedPtrLength(const MemObjSizeArray &size) const { return calculateOffsetForMapping(size); } cl_mem_object_type peekClMemObjType() const { return memObjectType; } protected: void getOsSpecificMemObjectInfo(const cl_mem_info ¶mName, size_t *srcParamSize, void **srcParam); - void setMappedPtr(void *mappedPtr); - virtual void setMappedSize(size_t *size) { mapInfo.size[0] = *size; } - virtual void setMappedOffset(size_t *offset) { mapInfo.offset[0] = *offset; } - Context *context; cl_mem_object_type memObjectType; cl_mem_flags flags; @@ -142,10 +134,9 @@ class MemObj : public BaseObject<_cl_mem> { void *memoryStorage; void *hostPtr; void *allocatedMapPtr = nullptr; - MapInfo mapInfo; + MapOperationsHandler mapOperationsHandler; size_t offset = 0; MemObj *associatedMemObject = nullptr; - std::atomic mapCount{0}; cl_uint refCount = 0; CompletionStamp completionStamp; CommandQueue *cmdQueuePtr = nullptr; diff --git a/unit_tests/api/cl_enqueue_unmap_mem_object_tests.cpp b/unit_tests/api/cl_enqueue_unmap_mem_object_tests.cpp index 11239edb5c..3b35f09850 100644 --- a/unit_tests/api/cl_enqueue_unmap_mem_object_tests.cpp +++ b/unit_tests/api/cl_enqueue_unmap_mem_object_tests.cpp @@ -46,8 +46,9 @@ TEST_F(clEnqueueUnmapMemObjTests, givenValidAddressWhenUnmappingThenReturnSucces EXPECT_EQ(CL_SUCCESS, retVal); } -TEST_F(clEnqueueUnmapMemObjTests, givenInvalidAddressWhenUnmappingThenReturnError) { +TEST_F(clEnqueueUnmapMemObjTests, givenInvalidAddressWhenUnmappingOnCpuThenReturnError) { auto buffer = std::unique_ptr(BufferHelper>::create(pContext)); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); cl_int retVal = CL_SUCCESS; auto mappedPtr = clEnqueueMapBuffer(pCommandQueue, buffer.get(), CL_TRUE, CL_MAP_READ, 0, 1, 0, nullptr, nullptr, &retVal); @@ -63,17 +64,19 @@ TEST_F(clEnqueueUnmapMemObjTests, givenInvalidAddressWhenUnmappingThenReturnErro EXPECT_EQ(CL_INVALID_VALUE, retVal); } -TEST_F(clEnqueueUnmapMemObjTests, givenNullAddressWhenUnmappingThenReturnError) { +TEST_F(clEnqueueUnmapMemObjTests, givenInvalidAddressWhenUnmappingOnGpuThenReturnError) { auto buffer = std::unique_ptr(BufferHelper>::create(pContext)); + buffer->setSharingHandler(new SharingHandler()); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); cl_int retVal = CL_SUCCESS; - clEnqueueMapBuffer(pCommandQueue, buffer.get(), CL_TRUE, CL_MAP_READ, 0, 1, 0, nullptr, nullptr, &retVal); + auto mappedPtr = clEnqueueMapBuffer(pCommandQueue, buffer.get(), CL_TRUE, CL_MAP_READ, 0, 1, 0, nullptr, nullptr, &retVal); EXPECT_EQ(CL_SUCCESS, retVal); retVal = clEnqueueUnmapMemObject( pCommandQueue, buffer.get(), - nullptr, + ptrOffset(mappedPtr, buffer->getSize() + 1), 0, nullptr, nullptr); diff --git a/unit_tests/command_queue/CMakeLists.txt b/unit_tests/command_queue/CMakeLists.txt index 740edee184..3dcad61303 100644 --- a/unit_tests/command_queue/CMakeLists.txt +++ b/unit_tests/command_queue/CMakeLists.txt @@ -98,6 +98,8 @@ set(IGDRCL_SRCS_tests_command_queue "${CMAKE_CURRENT_SOURCE_DIR}/local_id_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/local_work_size_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/multi_dispatch_info_tests.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/multiple_map_buffer_tests.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/multiple_map_image_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/oom_buffer_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/oom_image_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/oom_tests.cpp" diff --git a/unit_tests/command_queue/command_queue_hw_tests.cpp b/unit_tests/command_queue/command_queue_hw_tests.cpp index a389b62c7c..87e32ec44a 100644 --- a/unit_tests/command_queue/command_queue_hw_tests.cpp +++ b/unit_tests/command_queue/command_queue_hw_tests.cpp @@ -58,9 +58,6 @@ struct CommandQueueHwTest using ContextFixture::SetUp; - CommandQueueHwTest() { - } - void SetUp() override { MemoryManagementFixture::SetUp(); DeviceFixture::SetUp(); @@ -114,10 +111,13 @@ HWTEST_F(CommandQueueHwTest, enqueueBlockedMapUnmapOperationCreatesVirtualEvent) pHwQ->virtualEvent = nullptr; MockEventBuilder eventBuilder; + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(nullptr, 0, MAP, &buffer, + size, offset, false, eventBuilder); ASSERT_NE(nullptr, pHwQ->virtualEvent); @@ -126,7 +126,6 @@ HWTEST_F(CommandQueueHwTest, enqueueBlockedMapUnmapOperationCreatesVirtualEvent) } HWTEST_F(CommandQueueHwTest, givenBlockedMapBufferCallWhenMemObjectIsPassedToCommandThenItsRefCountIsBeingIncreased) { - CommandQueueHw *pHwQ = reinterpret_cast *>(pCmdQ); MockBuffer buffer; pHwQ->virtualEvent = nullptr; @@ -134,10 +133,13 @@ HWTEST_F(CommandQueueHwTest, givenBlockedMapBufferCallWhenMemObjectIsPassedToCom auto currentRefCount = buffer.getRefInternalCount(); MockEventBuilder eventBuilder; + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(nullptr, 0, MAP, &buffer, + size, offset, false, eventBuilder); EXPECT_EQ(currentRefCount + 1, buffer.getRefInternalCount()); @@ -149,7 +151,6 @@ HWTEST_F(CommandQueueHwTest, givenBlockedMapBufferCallWhenMemObjectIsPassedToCom } HWTEST_F(CommandQueueHwTest, givenNoReturnEventWhenCallingEnqueueBlockedMapUnmapOperationThenVirtualEventIncrementsCommandQueueInternalRefCount) { - CommandQueueHw *pHwQ = reinterpret_cast *>(pCmdQ); MockBuffer buffer; @@ -158,10 +159,13 @@ HWTEST_F(CommandQueueHwTest, givenNoReturnEventWhenCallingEnqueueBlockedMapUnmap auto initialRefCountInternal = pHwQ->getRefInternalCount(); MockEventBuilder eventBuilder; + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(nullptr, 0, MAP, &buffer, + size, offset, false, eventBuilder); ASSERT_NE(nullptr, pHwQ->virtualEvent); @@ -174,7 +178,6 @@ HWTEST_F(CommandQueueHwTest, givenNoReturnEventWhenCallingEnqueueBlockedMapUnmap } HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDoesntAddDependenciesIntoChild) { - auto buffer = new MockBuffer; CommandQueueHw *pHwQ = reinterpret_cast *>(pCmdQ); auto returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0); @@ -184,10 +187,13 @@ HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDoesntAddDependenciesInt pHwQ->virtualEvent = nullptr; MockEventBuilder eventBuilder(returnEvent); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(&eventWaitList, 1, MAP, buffer, + size, offset, false, eventBuilder); EXPECT_EQ(returnEvent, pHwQ->virtualEvent); @@ -201,15 +207,17 @@ HWTEST_F(CommandQueueHwTest, addMapUnmapToWaitlistEventsDoesntAddDependenciesInt } HWTEST_F(CommandQueueHwTest, givenMapCommandWhenZeroStateCommandIsSubmittedThenTaskCountIsBeingWaited) { - auto buffer = new MockBuffer; CommandQueueHw *pHwQ = reinterpret_cast *>(pCmdQ); MockEventBuilder eventBuilder; + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(nullptr, 0, MAP, buffer, + size, offset, false, eventBuilder); EXPECT_NE(nullptr, pHwQ->virtualEvent); @@ -220,17 +228,19 @@ HWTEST_F(CommandQueueHwTest, givenMapCommandWhenZeroStateCommandIsSubmittedThenT } HWTEST_F(CommandQueueHwTest, enqueueBlockedMapUnmapOperationInjectedCommand) { - CommandQueueHw *pHwQ = reinterpret_cast *>(pCmdQ); Event *returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0); auto buffer = new MockBuffer; pHwQ->virtualEvent = nullptr; MockEventBuilder eventBuilder(returnEvent); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(nullptr, 0, MAP, buffer, + size, offset, false, eventBuilder); eventBuilder.finalizeAndRelease(); @@ -245,7 +255,6 @@ HWTEST_F(CommandQueueHwTest, enqueueBlockedMapUnmapOperationInjectedCommand) { } HWTEST_F(CommandQueueHwTest, enqueueBlockedMapUnmapOperationPreviousEventHasNotInjectedChild) { - auto buffer = new MockBuffer; CommandQueueHw *pHwQ = reinterpret_cast *>(pCmdQ); Event *returnEvent = new Event(pHwQ, CL_COMMAND_MAP_BUFFER, 0, 0); @@ -258,10 +267,13 @@ HWTEST_F(CommandQueueHwTest, enqueueBlockedMapUnmapOperationPreviousEventHasNotI pHwQ->virtualEvent->incRefInternal(); MockEventBuilder eventBuilder(returnEvent); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; pHwQ->enqueueBlockedMapUnmapOperation(nullptr, 0, MAP, buffer, + size, offset, false, eventBuilder); EXPECT_EQ(returnEvent, pHwQ->virtualEvent); @@ -771,14 +783,14 @@ struct MockBuilder : BuiltinDispatchInfoBuilder { }; HWTEST_F(CommandQueueHwTest, givenCommandQueueThatIsBlockedAndUsesCpuCopyWhenEventIsReturnedItIsNotReady) { - CommandQueueHw *cmdQHw = static_cast *>(this->pCmdQ); + MockBuffer buffer; cl_event returnEvent = nullptr; auto retVal = CL_SUCCESS; cmdQHw->taskLevel = Event::eventNotReady; size_t offset = 0; size_t size = 4096u; - TransferProperties transferProperties(nullptr, CL_COMMAND_READ_BUFFER, false, &offset, &size, nullptr); + TransferProperties transferProperties(&buffer, CL_COMMAND_READ_BUFFER, 0, false, &offset, &size, nullptr); EventsRequest eventsRequest(0, nullptr, &returnEvent); cmdQHw->cpuDataTransferHandler(transferProperties, eventsRequest, retVal); EXPECT_EQ(CL_SUCCESS, retVal); diff --git a/unit_tests/command_queue/enqueue_map_buffer_tests.cpp b/unit_tests/command_queue/enqueue_map_buffer_tests.cpp index bd4d45cf79..35b6934fe6 100644 --- a/unit_tests/command_queue/enqueue_map_buffer_tests.cpp +++ b/unit_tests/command_queue/enqueue_map_buffer_tests.cpp @@ -273,10 +273,11 @@ TEST_F(EnqueueMapBufferTest, MapBufferReturnsSuccess) { EXPECT_EQ(CL_SUCCESS, retVal); } -TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferOnZeroCopyBufferWhenItIsCalledThenSynchronizationIsNotMadeUntilWaitForEvents) { +TEST_F(EnqueueMapBufferTest, givenNonBlockingReadOnlyMapBufferOnZeroCopyBufferWhenItIsCalledThenSynchronizationIsNotMadeUntilWaitForEvents) { DebugManagerStateRestore dbgRestore; DebugManager.flags.EnableAsyncEventsHandler.set(false); - cl_event eventReturned = nullptr; + cl_event mapEventReturned = nullptr; + cl_event unmapEventReturned = nullptr; *pTagMemory = 0; MockKernelWithInternals kernel(*pDevice); size_t GWS = 1; @@ -316,7 +317,7 @@ TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferOnZeroCopyBufferWhenItIsCa 8, 0, nullptr, - &eventReturned, + &mapEventReturned, &retVal); EXPECT_NE(nullptr, ptrResult); EXPECT_EQ(CL_SUCCESS, retVal); @@ -327,20 +328,21 @@ TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferOnZeroCopyBufferWhenItIsCa taskCount = commandStreamReceiver.peekTaskCount(); EXPECT_EQ(1u, taskCount); - auto neoEvent = castToObject(eventReturned); + auto neoEvent = castToObject(mapEventReturned); //if task count of csr is higher then event task count with proper dc flushing then we are fine EXPECT_EQ(1u, neoEvent->getCompletionStamp()); //this can't be completed as task count is not reached yet EXPECT_FALSE(neoEvent->updateStatusAndCheckCompletion()); + EXPECT_TRUE(CL_COMMAND_MAP_BUFFER == neoEvent->getCommandType()); auto callbackCalled = 0u; *pTagMemory += 4; - clSetEventCallback(eventReturned, CL_COMPLETE, E2Clb::SignalEv2, (void *)&callbackCalled); + clSetEventCallback(mapEventReturned, CL_COMPLETE, E2Clb::SignalEv2, (void *)&callbackCalled); //wait for events needs to flush DC as event requires this. - retVal = clWaitForEvents(1, &eventReturned); + retVal = clWaitForEvents(1, &mapEventReturned); EXPECT_EQ(CL_SUCCESS, retVal); //wait for event do not sent flushTask @@ -357,13 +359,105 @@ TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferOnZeroCopyBufferWhenItIsCa ptrResult, 0, nullptr, - nullptr); + &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(1u, commandStreamReceiver.peekTaskCount()); + + auto unmapEvent = castToObject(unmapEventReturned); + EXPECT_TRUE(CL_COMMAND_UNMAP_MEM_OBJECT == unmapEvent->getCommandType()); + retVal = clWaitForEvents(1, &unmapEventReturned); EXPECT_EQ(CL_SUCCESS, retVal); retVal = clReleaseMemObject(buffer); EXPECT_EQ(CL_SUCCESS, retVal); - clReleaseEvent(eventReturned); + clReleaseEvent(mapEventReturned); + clReleaseEvent(unmapEventReturned); +} + +TEST_F(EnqueueMapBufferTest, givenNonReadOnlyBufferWhenMappedOnGpuThenSetValidEventCmds) { + DebugManagerStateRestore dbgRestore; + DebugManager.flags.EnableAsyncEventsHandler.set(false); + cl_event mapEventReturned = nullptr; + cl_event unmapEventReturned = nullptr; + *pTagMemory = 5; + + std::unique_ptr buffer(Buffer::create(BufferDefaults::context, CL_MEM_READ_WRITE, 20, nullptr, retVal)); + buffer->setSharingHandler(new SharingHandler()); + buffer->forceDisallowCPUCopy = true; + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, buffer.get()); + + auto &commandStreamReceiver = pDevice->getCommandStreamReceiver(); + EXPECT_EQ(0u, commandStreamReceiver.peekTaskCount()); + + auto ptrResult = clEnqueueMapBuffer(pCmdQ, buffer.get(), CL_FALSE, CL_MAP_WRITE, 0, 8, 0, + nullptr, &mapEventReturned, &retVal); + EXPECT_NE(nullptr, ptrResult); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_EQ(1u, commandStreamReceiver.peekTaskCount()); + + auto mapEvent = castToObject(mapEventReturned); + EXPECT_TRUE(CL_COMMAND_MAP_BUFFER == mapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &mapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + retVal = clEnqueueUnmapMemObject(pCmdQ, buffer.get(), ptrResult, 0, nullptr, &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(2u, commandStreamReceiver.peekTaskCount()); + + auto unmapEvent = castToObject(unmapEventReturned); + EXPECT_TRUE(CL_COMMAND_UNMAP_MEM_OBJECT == unmapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + clReleaseEvent(mapEventReturned); + clReleaseEvent(unmapEventReturned); +} + +TEST_F(EnqueueMapBufferTest, givenReadOnlyBufferWhenMappedOnGpuThenSetValidEventCmds) { + DebugManagerStateRestore dbgRestore; + DebugManager.flags.EnableAsyncEventsHandler.set(false); + cl_event mapEventReturned = nullptr; + cl_event unmapEventReturned = nullptr; + *pTagMemory = 5; + + std::unique_ptr buffer(Buffer::create(BufferDefaults::context, CL_MEM_READ_WRITE, 20, nullptr, retVal)); + buffer->setSharingHandler(new SharingHandler()); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_NE(nullptr, buffer.get()); + + auto &commandStreamReceiver = pDevice->getCommandStreamReceiver(); + EXPECT_EQ(0u, commandStreamReceiver.peekTaskCount()); + + auto ptrResult = clEnqueueMapBuffer(pCmdQ, buffer.get(), CL_FALSE, CL_MAP_READ, 0, 8, 0, + nullptr, &mapEventReturned, &retVal); + EXPECT_NE(nullptr, ptrResult); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_EQ(1u, commandStreamReceiver.peekTaskCount()); + + auto mapEvent = castToObject(mapEventReturned); + EXPECT_TRUE(CL_COMMAND_MAP_BUFFER == mapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &mapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + retVal = clEnqueueUnmapMemObject(pCmdQ, buffer.get(), ptrResult, 0, nullptr, &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(1u, commandStreamReceiver.peekTaskCount()); + + auto unmapEvent = castToObject(unmapEventReturned); + EXPECT_TRUE(CL_COMMAND_UNMAP_MEM_OBJECT == unmapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + clReleaseEvent(mapEventReturned); + clReleaseEvent(unmapEventReturned); } TEST_F(EnqueueMapBufferTest, givenNonBlockingMapBufferAfterL3IsAlreadyFlushedThenEventIsSignaledAsCompleted) { @@ -582,13 +676,18 @@ TEST_F(EnqueueMapBufferTest, givenBufferWithoutUseHostPtrFlagWhenMappedOnCpuThen auto mappedPtr = clEnqueueMapBuffer(pCmdQ, buffer.get(), CL_FALSE, CL_MAP_READ, mapOffset, mapSize, 0, nullptr, nullptr, &retVal); EXPECT_NE(nullptr, mappedPtr); - EXPECT_EQ(mapOffset, buffer->getMappedOffset()[0]); - EXPECT_EQ(0u, buffer->getMappedOffset()[1]); - EXPECT_EQ(0u, buffer->getMappedOffset()[2]); + MapInfo mappedInfo; + auto success = buffer->findMappedPtr(mappedPtr, mappedInfo); + EXPECT_TRUE(success); + EXPECT_NE(nullptr, mappedInfo.ptr); - EXPECT_EQ(mapSize, buffer->getMappedSize()[0]); - EXPECT_EQ(0u, buffer->getMappedSize()[1]); - EXPECT_EQ(0u, buffer->getMappedSize()[2]); + EXPECT_EQ(mapOffset, mappedInfo.offset[0]); + EXPECT_EQ(0u, mappedInfo.offset[1]); + EXPECT_EQ(0u, mappedInfo.offset[2]); + + EXPECT_EQ(mapSize, mappedInfo.size[0]); + EXPECT_EQ(0u, mappedInfo.size[1]); + EXPECT_EQ(0u, mappedInfo.size[2]); auto expectedPtr = ptrOffset(buffer->getCpuAddressForMapping(), mapOffset); @@ -607,13 +706,18 @@ TEST_F(EnqueueMapBufferTest, givenBufferWithUseHostPtrFlagWhenMappedOnCpuThenSet auto mappedPtr = clEnqueueMapBuffer(pCmdQ, buffer.get(), CL_FALSE, CL_MAP_READ, mapOffset, mapSize, 0, nullptr, nullptr, &retVal); EXPECT_NE(nullptr, mappedPtr); - EXPECT_EQ(mapOffset, buffer->getMappedOffset()[0]); - EXPECT_EQ(0u, buffer->getMappedOffset()[1]); - EXPECT_EQ(0u, buffer->getMappedOffset()[2]); + MapInfo mappedInfo; + auto success = buffer->findMappedPtr(mappedPtr, mappedInfo); + EXPECT_TRUE(success); + EXPECT_NE(nullptr, mappedInfo.ptr); - EXPECT_EQ(mapSize, buffer->getMappedSize()[0]); - EXPECT_EQ(0u, buffer->getMappedSize()[1]); - EXPECT_EQ(0u, buffer->getMappedSize()[2]); + EXPECT_EQ(mapOffset, mappedInfo.offset[0]); + EXPECT_EQ(0u, mappedInfo.offset[1]); + EXPECT_EQ(0u, mappedInfo.offset[2]); + + EXPECT_EQ(mapSize, mappedInfo.size[0]); + EXPECT_EQ(0u, mappedInfo.size[1]); + EXPECT_EQ(0u, mappedInfo.size[2]); auto expectedPtr = ptrOffset(buffer->getCpuAddressForMapping(), mapOffset); diff --git a/unit_tests/command_queue/enqueue_map_image_tests.cpp b/unit_tests/command_queue/enqueue_map_image_tests.cpp index f643892dcb..5377a09b40 100644 --- a/unit_tests/command_queue/enqueue_map_image_tests.cpp +++ b/unit_tests/command_queue/enqueue_map_image_tests.cpp @@ -225,12 +225,13 @@ TEST_F(EnqueueMapImageTest, checkRetVal) { EXPECT_EQ(imageSlicePitch, imageSlicePitchRef); } -TEST_F(EnqueueMapImageTest, MapImageWaitEvent) { +TEST_F(EnqueueMapImageTest, givenNonReadOnlyMapWithOutEventWhenMappedThenSetEventAndIncraseTaskCountFromWriteImage) { DebugManagerStateRestore dbgRestore; DebugManager.flags.EnableAsyncEventsHandler.set(false); - cl_event eventReturned = nullptr; + cl_event mapEventReturned = nullptr; + cl_event unmapEventReturned = nullptr; uint32_t tagHW = 0; - auto mapFlags = CL_MAP_READ; + auto mapFlags = CL_MAP_WRITE; const size_t origin[3] = {0, 0, 0}; const size_t region[3] = {1, 1, 1}; size_t imageRowPitch = 0; @@ -268,18 +269,20 @@ TEST_F(EnqueueMapImageTest, MapImageWaitEvent) { &imageSlicePitch, 0, nullptr, - &eventReturned, + &mapEventReturned, retVal); EXPECT_NE(nullptr, ptr); EXPECT_EQ(CL_SUCCESS, retVal); + auto mapEvent = castToObject(mapEventReturned); + EXPECT_TRUE(CL_COMMAND_MAP_IMAGE == mapEvent->getCommandType()); taskCount = commandStreamReceiver.peekTaskCount(); EXPECT_EQ(3u, taskCount); - clSetEventCallback(eventReturned, CL_COMPLETE, E2Clb::SignalEv2, (void *)pTagMemory); + clSetEventCallback(mapEventReturned, CL_COMPLETE, E2Clb::SignalEv2, (void *)pTagMemory); - retVal = clWaitForEvents(1, &eventReturned); + retVal = clWaitForEvents(1, &mapEventReturned); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(4u, *pTagMemory); taskCount = commandStreamReceiver.peekTaskCount(); @@ -292,13 +295,60 @@ TEST_F(EnqueueMapImageTest, MapImageWaitEvent) { ptr, 0, nullptr, - nullptr); + &unmapEventReturned); EXPECT_EQ(CL_SUCCESS, retVal); + auto unmapEvent = castToObject(unmapEventReturned); + EXPECT_TRUE(CL_COMMAND_UNMAP_MEM_OBJECT == unmapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &unmapEventReturned); taskCount = commandStreamReceiver.peekTaskCount(); EXPECT_EQ(4u, taskCount); - clReleaseEvent(eventReturned); + clReleaseEvent(mapEventReturned); + clReleaseEvent(unmapEventReturned); +} + +TEST_F(EnqueueMapImageTest, givenReadOnlyMapWithOutEventWhenMappedThenSetEventAndDontIncraseTaskCountFromWriteImage) { + DebugManagerStateRestore dbgRestore; + DebugManager.flags.EnableAsyncEventsHandler.set(false); + cl_event mapEventReturned = nullptr; + cl_event unmapEventReturned = nullptr; + auto mapFlags = CL_MAP_READ; + const size_t origin[3] = {0, 0, 0}; + const size_t region[3] = {1, 1, 1}; + *pTagMemory = 5; + + auto &commandStreamReceiver = pDevice->getCommandStreamReceiver(); + + EXPECT_EQ(1u, commandStreamReceiver.peekTaskCount()); + + auto ptr = pCmdQ->enqueueMapImage(image, false, mapFlags, origin, region, nullptr, nullptr, 0, + nullptr, &mapEventReturned, retVal); + + EXPECT_NE(nullptr, ptr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(2u, commandStreamReceiver.peekTaskCount()); + + auto mapEvent = castToObject(mapEventReturned); + EXPECT_TRUE(CL_COMMAND_MAP_IMAGE == mapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &mapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + retVal = clEnqueueUnmapMemObject(pCmdQ, image, ptr, 0, nullptr, &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + EXPECT_EQ(2u, commandStreamReceiver.peekTaskCount()); + + auto unmapEvent = castToObject(unmapEventReturned); + EXPECT_TRUE(CL_COMMAND_UNMAP_MEM_OBJECT == unmapEvent->getCommandType()); + + retVal = clWaitForEvents(1, &unmapEventReturned); + EXPECT_EQ(CL_SUCCESS, retVal); + + clReleaseEvent(mapEventReturned); + clReleaseEvent(unmapEventReturned); } HWTEST_F(EnqueueMapImageTest, MapImageEventProperties) { @@ -448,8 +498,8 @@ TEST_F(EnqueueMapImageTest, GivenNonZeroCopyImageWhenMappedWithOffsetThenCorrect delete nonZeroCopyImage; } -HWTEST_F(EnqueueMapImageTest, givenSharingHandlerWhenMapAndUnmapOnNonTiledImageIsCalledThenMakeGpuCopy) { - auto image = ImageHelper>::create(context); +HWTEST_F(EnqueueMapImageTest, givenSharingHandlerWhenNonReadOnlyMapAndUnmapOnNonTiledImageIsCalledThenMakeGpuCopy) { + std::unique_ptr image(ImageHelper>::create(context)); ASSERT_NE(nullptr, image); image->setSharingHandler(new SharingHandler()); EXPECT_FALSE(image->allowTiling()); @@ -462,17 +512,40 @@ HWTEST_F(EnqueueMapImageTest, givenSharingHandlerWhenMapAndUnmapOnNonTiledImageI size_t origin[] = {0, 0, 0}; size_t region[] = {1, 1, 1}; - void *data = clEnqueueMapImage(pCmdQ, image, CL_TRUE, CL_MAP_READ, origin, region, nullptr, nullptr, 0, NULL, NULL, &retVal); + void *data = clEnqueueMapImage(pCmdQ, image.get(), CL_TRUE, CL_MAP_WRITE, origin, region, nullptr, nullptr, 0, NULL, NULL, &retVal); EXPECT_NE(nullptr, data); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(2u, pCmdQ->taskCount); EXPECT_EQ(2u, pCmdQ->taskLevel); - retVal = clEnqueueUnmapMemObject(pCmdQ, image, data, 0, NULL, NULL); + retVal = clEnqueueUnmapMemObject(pCmdQ, image.get(), data, 0, NULL, NULL); EXPECT_EQ(3u, pCmdQ->taskCount); EXPECT_EQ(3u, pCmdQ->taskLevel); +} - delete image; +HWTEST_F(EnqueueMapImageTest, givenSharingHandlerWhenReadOnlyMapAndUnmapOnNonTiledImageIsCalledThenMakeGpuCopy) { + std::unique_ptr image(ImageHelper>::create(context)); + ASSERT_NE(nullptr, image); + image->setSharingHandler(new SharingHandler()); + EXPECT_FALSE(image->allowTiling()); + + auto &csr = pDevice->getUltCommandStreamReceiver(); + csr.taskCount = 1; + csr.taskLevel = 1; + pCmdQ->taskCount = 1; + pCmdQ->taskLevel = 1; + + size_t origin[] = {0, 0, 0}; + size_t region[] = {1, 1, 1}; + void *data = clEnqueueMapImage(pCmdQ, image.get(), CL_TRUE, CL_MAP_READ, origin, region, nullptr, nullptr, 0, NULL, NULL, &retVal); + EXPECT_NE(nullptr, data); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(2u, pCmdQ->taskCount); + EXPECT_EQ(2u, pCmdQ->taskLevel); + + retVal = clEnqueueUnmapMemObject(pCmdQ, image.get(), data, 0, NULL, NULL); + EXPECT_EQ(2u, pCmdQ->taskCount); + EXPECT_EQ(2u, pCmdQ->taskLevel); } HWTEST_F(EnqueueMapImageTest, givenImageWithouUsetHostPtrFlagWhenMappedOnCpuThenSetAllMapProperties) { @@ -485,15 +558,20 @@ HWTEST_F(EnqueueMapImageTest, givenImageWithouUsetHostPtrFlagWhenMappedOnCpuThen void *mappedPtr = clEnqueueMapImage(pCmdQ, image.get(), CL_TRUE, CL_MAP_READ, origin, region, nullptr, nullptr, 0, NULL, NULL, &retVal); EXPECT_NE(nullptr, mappedPtr); - EXPECT_EQ(origin[0], image->getMappedOffset()[0]); - EXPECT_EQ(origin[1], image->getMappedOffset()[1]); - EXPECT_EQ(origin[2], image->getMappedOffset()[2]); + MapInfo mappedInfo; + auto success = image->findMappedPtr(mappedPtr, mappedInfo); + EXPECT_TRUE(success); + EXPECT_NE(nullptr, mappedInfo.ptr); - EXPECT_EQ(region[0], image->getMappedSize()[0]); - EXPECT_EQ(region[1], image->getMappedSize()[1]); - EXPECT_EQ(region[2], image->getMappedSize()[2]); + EXPECT_EQ(origin[0], mappedInfo.offset[0]); + EXPECT_EQ(origin[1], mappedInfo.offset[1]); + EXPECT_EQ(origin[2], mappedInfo.offset[2]); - auto expectedPtr = ptrOffset(image->getCpuAddressForMapping(), image->calculateOffsetForMapping(origin)); + EXPECT_EQ(region[0], mappedInfo.size[0]); + EXPECT_EQ(region[1], mappedInfo.size[1]); + EXPECT_EQ(region[2], mappedInfo.size[2]); + + auto expectedPtr = ptrOffset(image->getCpuAddressForMapping(), image->calculateOffsetForMapping(mappedInfo.offset)); EXPECT_EQ(mappedPtr, expectedPtr); } @@ -508,15 +586,20 @@ HWTEST_F(EnqueueMapImageTest, givenImageWithUseHostPtrFlagWhenMappedOnCpuThenSet void *mappedPtr = clEnqueueMapImage(pCmdQ, image.get(), CL_TRUE, CL_MAP_READ, origin, region, nullptr, nullptr, 0, NULL, NULL, &retVal); EXPECT_NE(nullptr, mappedPtr); - EXPECT_EQ(origin[0], image->getMappedOffset()[0]); - EXPECT_EQ(origin[1], image->getMappedOffset()[1]); - EXPECT_EQ(origin[2], image->getMappedOffset()[2]); + MapInfo mappedInfo; + auto success = image->findMappedPtr(mappedPtr, mappedInfo); + EXPECT_TRUE(success); + EXPECT_NE(nullptr, mappedInfo.ptr); - EXPECT_EQ(region[0], image->getMappedSize()[0]); - EXPECT_EQ(region[1], image->getMappedSize()[1]); - EXPECT_EQ(region[2], image->getMappedSize()[2]); + EXPECT_EQ(origin[0], mappedInfo.offset[0]); + EXPECT_EQ(origin[1], mappedInfo.offset[1]); + EXPECT_EQ(origin[2], mappedInfo.offset[2]); - auto expectedPtr = ptrOffset(image->getCpuAddressForMapping(), image->calculateOffsetForMapping(origin)); + EXPECT_EQ(region[0], mappedInfo.size[0]); + EXPECT_EQ(region[1], mappedInfo.size[1]); + EXPECT_EQ(region[2], mappedInfo.size[2]); + + auto expectedPtr = ptrOffset(image->getCpuAddressForMapping(), image->calculateOffsetForMapping(mappedInfo.offset)); EXPECT_EQ(mappedPtr, expectedPtr); } diff --git a/unit_tests/command_queue/multiple_map_buffer_tests.cpp b/unit_tests/command_queue/multiple_map_buffer_tests.cpp new file mode 100644 index 0000000000..989525be47 --- /dev/null +++ b/unit_tests/command_queue/multiple_map_buffer_tests.cpp @@ -0,0 +1,384 @@ +/* + * 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/command_queue/command_queue_hw.h" +#include "runtime/mem_obj/buffer.h" +#include "unit_tests/fixtures/device_fixture.h" +#include "unit_tests/mocks/mock_context.h" +#include "test.h" + +using namespace OCLRT; + +struct MultipleMapBufferTest : public DeviceFixture, public ::testing::Test { + template + struct MockBuffer : public BufferHw { + using Buffer::mapOperationsHandler; + + template + MockBuffer(Params... params) : BufferHw(params...) { + this->createFunction = BufferHw::create; + }; + + void transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override { + this->copySize = copySize[0]; + this->copyOffset = copyOffset[0]; + transferToHostPtrCalled++; + }; + void transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override { + this->copySize = copySize[0]; + this->copyOffset = copyOffset[0]; + transferFromHostPtrCalled++; + }; + + size_t copySize = 0; + size_t copyOffset = 0; + uint32_t transferToHostPtrCalled = 0; + uint32_t transferFromHostPtrCalled = 0; + }; + + template + struct MockCmdQ : public CommandQueueHw { + MockCmdQ(Context *context, Device *device) : CommandQueueHw(context, device, 0) {} + + cl_int enqueueReadBuffer(Buffer *buffer, cl_bool blockingRead, size_t offset, size_t size, void *ptr, + cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) override { + enqueueSize = size; + enqueueOffset = offset; + readBufferCalled++; + if (failOnReadBuffer) { + return CL_OUT_OF_RESOURCES; + } + return CommandQueueHw::enqueueReadBuffer(buffer, blockingRead, offset, size, ptr, numEventsInWaitList, eventWaitList, event); + } + + cl_int enqueueWriteBuffer(Buffer *buffer, cl_bool blockingWrite, size_t offset, size_t cb, const void *ptr, + cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) override { + enqueueSize = cb; + enqueueOffset = offset; + unmapPtr = ptr; + writeBufferCalled++; + if (failOnWriteBuffer) { + return CL_OUT_OF_RESOURCES; + } + return CommandQueueHw::enqueueWriteBuffer(buffer, blockingWrite, offset, cb, ptr, numEventsInWaitList, eventWaitList, event); + } + + cl_int enqueueMarkerWithWaitList(cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) override { + enqueueMarkerCalled++; + return CommandQueueHw::enqueueMarkerWithWaitList(numEventsInWaitList, eventWaitList, event); + } + + uint32_t writeBufferCalled = 0; + uint32_t readBufferCalled = 0; + uint32_t enqueueMarkerCalled = 0; + bool failOnReadBuffer = false; + bool failOnWriteBuffer = false; + size_t enqueueSize = 0; + size_t enqueueOffset = 0; + const void *unmapPtr = nullptr; + }; + + template + std::unique_ptr> createMockBuffer(bool mapOnGpu) { + auto mockAlloc = pDevice->getMemoryManager()->allocateGraphicsMemory(1024); + auto buffer = new MockBuffer(context, 0, 1024, mockAlloc->getUnderlyingBuffer(), mockAlloc->getUnderlyingBuffer(), + mockAlloc, false, false, false); + if (mapOnGpu) { + buffer->setSharingHandler(new SharingHandler()); + } + return std::unique_ptr>(buffer); + } + + template + std::unique_ptr> createMockCmdQ() { + return std::unique_ptr>(new MockCmdQ(context, pDevice)); + } + + void SetUp() override { + DeviceFixture::SetUp(); + context = new MockContext(pDevice); + } + + void TearDown() override { + delete context; + DeviceFixture::TearDown(); + } + + MockContext *context = nullptr; + cl_int retVal = CL_INVALID_VALUE; +}; + +HWTEST_F(MultipleMapBufferTest, givenValidReadAndWriteBufferWhenMappedOnGpuThenAddMappedPtrAndRemoveOnUnmap) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, offset, size, 0, nullptr, nullptr, nullptr); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->readBufferCalled, 1u); + EXPECT_EQ(cmdQ->enqueueSize, size); + EXPECT_EQ(cmdQ->enqueueOffset, offset); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->writeBufferCalled, 1u); + EXPECT_EQ(cmdQ->enqueueSize, size); + EXPECT_EQ(cmdQ->enqueueOffset, offset); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtr); +} + +HWTEST_F(MultipleMapBufferTest, givenReadOnlyMapWhenUnmappedOnGpuThenEnqueueMarker) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_READ, offset, size, 0, nullptr, nullptr, nullptr); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->readBufferCalled, 1u); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->writeBufferCalled, 0u); + EXPECT_EQ(cmdQ->enqueueMarkerCalled, 1u); +} + +HWTEST_F(MultipleMapBufferTest, givenNotMappedPtrWhenUnmapedOnGpuThenReturnError) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); + + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), buffer->getBasePtrForMap(), 0, nullptr, nullptr); + EXPECT_EQ(CL_INVALID_VALUE, retVal); +} + +HWTEST_F(MultipleMapBufferTest, givenErrorFromReadBufferWhenMappedOnGpuThenDontAddMappedPtr) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); + cmdQ->failOnReadBuffer = true; + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_READ, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_EQ(nullptr, mappedPtr); + EXPECT_EQ(CL_OUT_OF_RESOURCES, retVal); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); +} + +HWTEST_F(MultipleMapBufferTest, givenErrorFromWriteBufferWhenUnmappedOnGpuThenDontRemoveMappedPtr) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); + cmdQ->failOnWriteBuffer = true; + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(1u, cmdQ->writeBufferCalled); + EXPECT_EQ(CL_OUT_OF_RESOURCES, retVal); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); +} + +HWTEST_F(MultipleMapBufferTest, givenUnblockedQueueWhenMappedOnCpuThenAddMappedPtrAndRemoveOnUnmap) { + auto buffer = createMockBuffer(false); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(1u, buffer->transferToHostPtrCalled); + EXPECT_EQ(buffer->copySize, size); + EXPECT_EQ(buffer->copyOffset, offset); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(1u, buffer->transferFromHostPtrCalled); + EXPECT_EQ(buffer->copySize, size); + EXPECT_EQ(buffer->copyOffset, offset); +} + +HWTEST_F(MultipleMapBufferTest, givenUnblockedQueueWhenReadOnlyMappedOnCpuThenDontMakeCpuCopy) { + auto buffer = createMockBuffer(false); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_READ, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(1u, buffer->transferToHostPtrCalled); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(0u, buffer->transferFromHostPtrCalled); +} + +HWTEST_F(MultipleMapBufferTest, givenBlockedQueueWhenMappedOnCpuThenAddMappedPtrAndRemoveOnUnmap) { + auto buffer = createMockBuffer(false); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); + + UserEvent mapEvent, unmapEvent; + cl_event clMapEvent = &mapEvent; + cl_event clUnmapEvent = &unmapEvent; + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, offset, size, 1, &clMapEvent, nullptr, &retVal); + mapEvent.setStatus(CL_COMPLETE); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(buffer->copySize, size); + EXPECT_EQ(buffer->copyOffset, offset); + EXPECT_EQ(1u, buffer->transferToHostPtrCalled); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 1, &clUnmapEvent, nullptr); + unmapEvent.setStatus(CL_COMPLETE); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(buffer->copySize, size); + EXPECT_EQ(buffer->copyOffset, offset); + EXPECT_EQ(1u, buffer->transferFromHostPtrCalled); +} + +HWTEST_F(MultipleMapBufferTest, givenBlockedQueueWhenMappedReadOnlyOnCpuThenDontMakeCpuCopy) { + auto buffer = createMockBuffer(false); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); + + UserEvent mapEvent, unmapEvent; + cl_event clMapEvent = &mapEvent; + cl_event clUnmapEvent = &unmapEvent; + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_READ, offset, size, 1, &clMapEvent, nullptr, &retVal); + mapEvent.setStatus(CL_COMPLETE); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, buffer->transferToHostPtrCalled); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtr, 1, &clUnmapEvent, nullptr); + unmapEvent.setStatus(CL_COMPLETE); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(0u, buffer->transferFromHostPtrCalled); +} + +HWTEST_F(MultipleMapBufferTest, givenInvalidPtrWhenUnmappedOnCpuThenReturnError) { + auto buffer = createMockBuffer(false); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), buffer->getBasePtrForMap(), 0, nullptr, nullptr); + EXPECT_EQ(CL_INVALID_VALUE, retVal); +} + +HWTEST_F(MultipleMapBufferTest, givenMultimpleMapsWhenUnmappingThenRemoveCorrectPointers) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + + MapInfo mappedPtrs[3] = { + {nullptr, 1, {{1, 0, 0}}, {{1, 0, 0}}}, + {nullptr, 1, {{2, 0, 0}}, {{2, 0, 0}}}, + {nullptr, 1, {{5, 0, 0}}, {{5, 0, 0}}}, + }; + + for (size_t i = 0; i < 3; i++) { + mappedPtrs[i].ptr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, + mappedPtrs[i].offset[0], mappedPtrs[i].size[0], 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtrs[i].ptr); + EXPECT_EQ(i + 1, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->enqueueSize, mappedPtrs[i].size[0]); + EXPECT_EQ(cmdQ->enqueueOffset, mappedPtrs[i].offset[0]); + } + + // reordered unmap + clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtrs[1].ptr, 0, nullptr, nullptr); + EXPECT_EQ(2u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtrs[1].ptr); + EXPECT_EQ(cmdQ->enqueueSize, mappedPtrs[1].size[0]); + EXPECT_EQ(cmdQ->enqueueOffset, mappedPtrs[1].offset[0]); + + clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtrs[2].ptr, 0, nullptr, nullptr); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtrs[2].ptr); + EXPECT_EQ(cmdQ->enqueueSize, mappedPtrs[2].size[0]); + EXPECT_EQ(cmdQ->enqueueOffset, mappedPtrs[2].offset[0]); + + clEnqueueUnmapMemObject(cmdQ.get(), buffer.get(), mappedPtrs[0].ptr, 0, nullptr, nullptr); + EXPECT_EQ(0u, buffer->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtrs[0].ptr); + EXPECT_EQ(cmdQ->enqueueSize, mappedPtrs[0].size[0]); + EXPECT_EQ(cmdQ->enqueueOffset, mappedPtrs[0].offset[0]); +} + +HWTEST_F(MultipleMapBufferTest, givenOverlapingPtrWhenMappingOnGpuForWriteThenReturnError) { + auto buffer = createMockBuffer(true); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(buffer->mappingOnCpuAllowed()); + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_READ, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + + offset++; + void *mappedPtr2 = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_EQ(nullptr, mappedPtr2); + EXPECT_EQ(CL_INVALID_OPERATION, retVal); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); +} + +HWTEST_F(MultipleMapBufferTest, givenOverlapingPtrWhenMappingOnCpuForWriteThenReturnError) { + auto buffer = createMockBuffer(false); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(buffer->mappingOnCpuAllowed()); + + size_t offset = 1; + size_t size = 3; + void *mappedPtr = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_READ, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); + + offset++; + void *mappedPtr2 = clEnqueueMapBuffer(cmdQ.get(), buffer.get(), CL_FALSE, CL_MAP_WRITE, offset, size, 0, nullptr, nullptr, &retVal); + EXPECT_EQ(nullptr, mappedPtr2); + EXPECT_EQ(CL_INVALID_OPERATION, retVal); + EXPECT_EQ(1u, buffer->mapOperationsHandler.size()); +} diff --git a/unit_tests/command_queue/multiple_map_image_tests.cpp b/unit_tests/command_queue/multiple_map_image_tests.cpp new file mode 100644 index 0000000000..864f6045dd --- /dev/null +++ b/unit_tests/command_queue/multiple_map_image_tests.cpp @@ -0,0 +1,393 @@ +/* + * 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/gmm_helper/gmm_helper.h" +#include "runtime/command_queue/command_queue_hw.h" +#include "unit_tests/fixtures/device_fixture.h" +#include "unit_tests/fixtures/image_fixture.h" +#include "unit_tests/mocks/mock_context.h" +#include "test.h" + +using namespace OCLRT; + +struct MultipleMapImageTest : public DeviceFixture, public ::testing::Test { + template + struct MockImage : public ImageHw { + using Image::mapOperationsHandler; + + template + MockImage(Params... params) : ImageHw(params...) { + this->createFunction = ImageHw::create; + }; + + void transferDataToHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override { + copyRegion = copySize; + copyOrigin = copyOffset; + transferToHostPtrCalled++; + }; + void transferDataFromHostPtr(MemObjSizeArray ©Size, MemObjOffsetArray ©Offset) override { + copyRegion = copySize; + copyOrigin = copyOffset; + transferFromHostPtrCalled++; + }; + + MemObjSizeArray copyRegion = {{0, 0, 0}}; + MemObjOffsetArray copyOrigin = {{0, 0, 0}}; + uint32_t transferToHostPtrCalled = 0; + uint32_t transferFromHostPtrCalled = 0; + }; + + template + struct MockCmdQ : public CommandQueueHw { + MockCmdQ(Context *context, Device *device) : CommandQueueHw(context, device, 0) {} + + cl_int enqueueReadImage(Image *srcImage, cl_bool blockingRead, const size_t *origin, const size_t *region, size_t rowPitch, size_t slicePitch, void *ptr, + cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) override { + enqueueRegion = {{region[0], region[1], region[2]}}; + enqueueOrigin = {{origin[0], origin[1], origin[2]}}; + readImageCalled++; + if (failOnReadImage) { + return CL_OUT_OF_RESOURCES; + } + return CommandQueueHw::enqueueReadImage(srcImage, blockingRead, origin, region, rowPitch, slicePitch, ptr, numEventsInWaitList, eventWaitList, event); + } + + cl_int enqueueWriteImage(Image *dstImage, cl_bool blockingWrite, const size_t *origin, const size_t *region, size_t inputRowPitch, + size_t inputSlicePitch, const void *ptr, cl_uint numEventsInWaitList, const cl_event *eventWaitList, + cl_event *event) override { + enqueueRegion = {{region[0], region[1], region[2]}}; + enqueueOrigin = {{origin[0], origin[1], origin[2]}}; + unmapPtr = ptr; + writeImageCalled++; + if (failOnWriteImage) { + return CL_OUT_OF_RESOURCES; + } + return CommandQueueHw::enqueueWriteImage(dstImage, blockingWrite, origin, region, inputRowPitch, inputSlicePitch, ptr, + numEventsInWaitList, eventWaitList, event); + } + + cl_int enqueueMarkerWithWaitList(cl_uint numEventsInWaitList, const cl_event *eventWaitList, cl_event *event) override { + enqueueMarkerCalled++; + return CommandQueueHw::enqueueMarkerWithWaitList(numEventsInWaitList, eventWaitList, event); + } + + uint32_t writeImageCalled = 0; + uint32_t readImageCalled = 0; + uint32_t enqueueMarkerCalled = 0; + bool failOnReadImage = false; + bool failOnWriteImage = false; + MemObjSizeArray enqueueRegion = {{0, 0, 0}}; + MemObjOffsetArray enqueueOrigin = {{0, 0, 0}}; + const void *unmapPtr = nullptr; + }; + + template + std::unique_ptr> createMockImage() { + auto mockAlloc = pDevice->getMemoryManager()->allocateGraphicsMemory(1024); + auto tiledImage = Gmm::allowTiling(Traits::imageDesc); + + auto surfaceFormat = Image::getSurfaceFormatFromTable(Traits::flags, &Traits::imageFormat); + auto img = new MockImage(context, Traits::flags, 1024, Traits::hostPtr, + Traits::imageFormat, Traits::imageDesc, false, mockAlloc, false, + tiledImage, 0, surfaceFormat); + return std::unique_ptr>(img); + } + + template + std::unique_ptr> createMockCmdQ() { + return std::unique_ptr>(new MockCmdQ(context, pDevice)); + } + + void SetUp() override { + DeviceFixture::SetUp(); + context = new MockContext(pDevice); + } + + void TearDown() override { + delete context; + DeviceFixture::TearDown(); + } + + MockContext *context = nullptr; + cl_int retVal = CL_INVALID_VALUE; +}; + +HWTEST_F(MultipleMapImageTest, givenValidReadAndWriteImageWhenMappedOnGpuThenAddMappedPtrAndRemoveOnUnmap) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_WRITE, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->enqueueRegion, region); + EXPECT_EQ(cmdQ->enqueueOrigin, origin); + EXPECT_EQ(cmdQ->readImageCalled, 1u); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->enqueueRegion, region); + EXPECT_EQ(cmdQ->enqueueOrigin, origin); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtr); + EXPECT_EQ(cmdQ->writeImageCalled, 1u); +} + +HWTEST_F(MultipleMapImageTest, givenReadOnlyMapWhenUnmappedOnGpuThenEnqueueMarker) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_READ, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->enqueueRegion, region); + EXPECT_EQ(cmdQ->enqueueOrigin, origin); + EXPECT_EQ(cmdQ->readImageCalled, 1u); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->writeImageCalled, 0u); + EXPECT_EQ(cmdQ->enqueueMarkerCalled, 1u); +} + +HWTEST_F(MultipleMapImageTest, givenNotMappedPtrWhenUnmapedOnGpuThenReturnError) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), image->getBasePtrForMap(), 0, nullptr, nullptr); + EXPECT_EQ(CL_INVALID_VALUE, retVal); +} + +HWTEST_F(MultipleMapImageTest, givenErrorFromReadImageWhenMappedOnGpuThenDontAddMappedPtr) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + cmdQ->failOnReadImage = true; + + size_t origin[] = {2, 1, 1}; + size_t region[] = {2, 1, 1}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_READ, origin, region, nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_EQ(nullptr, mappedPtr); + EXPECT_EQ(CL_OUT_OF_RESOURCES, retVal); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); +} + +HWTEST_F(MultipleMapImageTest, givenErrorFromWriteImageWhenUnmappedOnGpuThenDontRemoveMappedPtr) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + cmdQ->failOnWriteImage = true; + + size_t origin[] = {2, 1, 1}; + size_t region[] = {2, 1, 1}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_WRITE, origin, region, nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(CL_OUT_OF_RESOURCES, retVal); + EXPECT_EQ(cmdQ->writeImageCalled, 1u); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); +} + +HWTEST_F(MultipleMapImageTest, givenUnblockedQueueWhenMappedOnCpuThenAddMappedPtrAndRemoveOnUnmap) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_WRITE, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(1u, image->transferToHostPtrCalled); + EXPECT_EQ(image->copyRegion, region); + EXPECT_EQ(image->copyOrigin, origin); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(1u, image->transferFromHostPtrCalled); + EXPECT_EQ(image->copyRegion, region); + EXPECT_EQ(image->copyOrigin, origin); +} + +HWTEST_F(MultipleMapImageTest, givenUnblockedQueueWhenReadOnlyMappedOnCpuThenDontMakeCpuCopy) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_READ, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(1u, image->transferToHostPtrCalled); + EXPECT_EQ(image->copyRegion, region); + EXPECT_EQ(image->copyOrigin, origin); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 0, nullptr, nullptr); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(0u, image->transferFromHostPtrCalled); +} + +HWTEST_F(MultipleMapImageTest, givenBlockedQueueWhenMappedOnCpuThenAddMappedPtrAndRemoveOnUnmap) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + UserEvent mapEvent, unmapEvent; + cl_event clMapEvent = &mapEvent; + cl_event clUnmapEvent = &unmapEvent; + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_FALSE, CL_MAP_WRITE, &origin[0], ®ion[0], nullptr, nullptr, 1, &clMapEvent, nullptr, &retVal); + mapEvent.setStatus(CL_COMPLETE); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->transferToHostPtrCalled); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(image->copyRegion, region); + EXPECT_EQ(image->copyOrigin, origin); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 1, &clUnmapEvent, nullptr); + unmapEvent.setStatus(CL_COMPLETE); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(1u, image->transferFromHostPtrCalled); + EXPECT_EQ(image->copyRegion, region); + EXPECT_EQ(image->copyOrigin, origin); +} + +HWTEST_F(MultipleMapImageTest, givenBlockedQueueWhenMappedReadOnlyOnCpuThenDontMakeCpuCopy) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + UserEvent mapEvent, unmapEvent; + cl_event clMapEvent = &mapEvent; + cl_event clUnmapEvent = &unmapEvent; + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_FALSE, CL_MAP_READ, &origin[0], ®ion[0], nullptr, nullptr, 1, &clMapEvent, nullptr, &retVal); + mapEvent.setStatus(CL_COMPLETE); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(1u, image->transferToHostPtrCalled); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(image->copyRegion, region); + EXPECT_EQ(image->copyOrigin, origin); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtr, 1, &clUnmapEvent, nullptr); + unmapEvent.setStatus(CL_COMPLETE); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(0u, image->transferFromHostPtrCalled); +} + +HWTEST_F(MultipleMapImageTest, givenInvalidPtrWhenUnmappedOnCpuThenReturnError) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + retVal = clEnqueueUnmapMemObject(cmdQ.get(), image.get(), image->getBasePtrForMap(), 0, nullptr, nullptr); + EXPECT_EQ(CL_INVALID_VALUE, retVal); +} + +HWTEST_F(MultipleMapImageTest, givenMultimpleMapsWhenUnmappingThenRemoveCorrectPointers) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + + MapInfo mappedPtrs[3] = { + {nullptr, 1, {{1, 1, 1}}, {{1, 1, 1}}}, + {nullptr, 1, {{4, 4, 2}}, {{4, 4, 4}}}, + {nullptr, 1, {{10, 10, 10}}, {{10, 10, 10}}}}; + + for (size_t i = 0; i < 3; i++) { + mappedPtrs[i].ptr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_WRITE, &mappedPtrs[i].offset[0], &mappedPtrs[i].size[0], + nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtrs[i].ptr); + EXPECT_EQ(i + 1, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->enqueueRegion, mappedPtrs[i].size); + EXPECT_EQ(cmdQ->enqueueOrigin, mappedPtrs[i].offset); + } + + // reordered unmap + clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtrs[1].ptr, 0, nullptr, nullptr); + EXPECT_EQ(2u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtrs[1].ptr); + EXPECT_EQ(cmdQ->enqueueRegion, mappedPtrs[1].size); + EXPECT_EQ(cmdQ->enqueueOrigin, mappedPtrs[1].offset); + + clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtrs[2].ptr, 0, nullptr, nullptr); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtrs[2].ptr); + EXPECT_EQ(cmdQ->enqueueRegion, mappedPtrs[2].size); + EXPECT_EQ(cmdQ->enqueueOrigin, mappedPtrs[2].offset); + + clEnqueueUnmapMemObject(cmdQ.get(), image.get(), mappedPtrs[0].ptr, 0, nullptr, nullptr); + EXPECT_EQ(0u, image->mapOperationsHandler.size()); + EXPECT_EQ(cmdQ->unmapPtr, mappedPtrs[0].ptr); + EXPECT_EQ(cmdQ->enqueueRegion, mappedPtrs[0].size); + EXPECT_EQ(cmdQ->enqueueOrigin, mappedPtrs[0].offset); +} + +HWTEST_F(MultipleMapImageTest, givenOverlapingPtrWhenMappingOnGpuForWriteThenReturnError) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_READ, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + + origin[0]++; + void *mappedPtr2 = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_WRITE, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_EQ(nullptr, mappedPtr2); + EXPECT_EQ(CL_INVALID_OPERATION, retVal); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); +} + +HWTEST_F(MultipleMapImageTest, givenOverlapingPtrWhenMappingOnCpuForWriteThenReturnError) { + auto image = createMockImage(); + auto cmdQ = createMockCmdQ(); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + MemObjOffsetArray origin = {{1, 2, 1}}; + MemObjSizeArray region = {{3, 4, 1}}; + void *mappedPtr = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_READ, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_NE(nullptr, mappedPtr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); + + origin[0]++; + void *mappedPtr2 = clEnqueueMapImage(cmdQ.get(), image.get(), CL_TRUE, CL_MAP_WRITE, &origin[0], ®ion[0], nullptr, nullptr, 0, nullptr, nullptr, &retVal); + EXPECT_EQ(nullptr, mappedPtr2); + EXPECT_EQ(CL_INVALID_OPERATION, retVal); + EXPECT_EQ(1u, image->mapOperationsHandler.size()); +} diff --git a/unit_tests/event/event_tests.cpp b/unit_tests/event/event_tests.cpp index d99fba66a4..9973dfa11a 100644 --- a/unit_tests/event/event_tests.cpp +++ b/unit_tests/event/event_tests.cpp @@ -633,7 +633,9 @@ TEST_F(InternalsEventTest, processBlockedCommandsMapOperation) { auto &csr = pDevice->getCommandStreamReceiver(); auto buffer = new MockBuffer; - event.setCommand(std::unique_ptr(new CommandMapUnmap(MAP, *buffer, csr, *pCmdQ))); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + event.setCommand(std::unique_ptr(new CommandMapUnmap(MAP, *buffer, size, offset, false, csr, *pCmdQ))); auto taskLevelBefore = csr.peekTaskLevel(); @@ -653,7 +655,9 @@ TEST_F(InternalsEventTest, processBlockedCommandsMapOperationNonZeroCopyBuffer) auto &csr = pDevice->getCommandStreamReceiver(); auto buffer = new UnalignedBuffer; - event.setCommand(std::unique_ptr(new CommandMapUnmap(MAP, *buffer, csr, *pCmdQ))); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + event.setCommand(std::unique_ptr(new CommandMapUnmap(MAP, *buffer, size, offset, false, csr, *pCmdQ))); auto taskLevelBefore = csr.peekTaskLevel(); @@ -738,7 +742,9 @@ TEST_F(InternalsEventTest, GIVENProfilingWHENMapOperationTHENTimesSet) { auto &csr = pDevice->getCommandStreamReceiver(); UnalignedBuffer buffer; - event->setCommand(std::unique_ptr(new CommandMapUnmap(MAP, buffer, csr, *pCmdQ))); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + event->setCommand(std::unique_ptr(new CommandMapUnmap(MAP, buffer, size, offset, false, csr, *pCmdQ))); auto taskLevelBefore = csr.peekTaskLevel(); @@ -762,7 +768,9 @@ TEST_F(InternalsEventTest, processBlockedCommandsUnMapOperation) { auto &csr = pDevice->getCommandStreamReceiver(); auto buffer = new UnalignedBuffer; - event.setCommand(std::unique_ptr(new CommandMapUnmap(UNMAP, *buffer, csr, *pCmdQ))); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + event.setCommand(std::unique_ptr(new CommandMapUnmap(UNMAP, *buffer, size, offset, false, csr, *pCmdQ))); auto taskLevelBefore = csr.peekTaskLevel(); @@ -783,7 +791,9 @@ TEST_F(InternalsEventTest, processBlockedCommandsUnMapOperationNonZeroCopyBuffer auto &csr = pDevice->getCommandStreamReceiver(); auto buffer = new UnalignedBuffer; - event.setCommand(std::unique_ptr(new CommandMapUnmap(UNMAP, *buffer, csr, *pCmdQ))); + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + event.setCommand(std::unique_ptr(new CommandMapUnmap(UNMAP, *buffer, size, offset, false, csr, *pCmdQ))); auto taskLevelBefore = csr.peekTaskLevel(); @@ -939,7 +949,9 @@ HWTEST_F(InternalsEventTest, GivenBufferWithoutZeroCopyOnCommandMapOrUnmapFlushe MockCsr csr(executionStamp); csr.setMemoryManager(pDevice->getMemoryManager()); - auto commandMap = std::unique_ptr(new CommandMapUnmap(MAP, buffer, csr, *pCmdQ)); + MemObjSizeArray size = {{4, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + auto commandMap = std::unique_ptr(new CommandMapUnmap(MAP, buffer, size, offset, false, csr, *pCmdQ)); EXPECT_EQ(0, executionStamp); EXPECT_EQ(-1, csr.flushTaskStamp); EXPECT_EQ(-1, buffer.dataTransferedStamp); @@ -957,7 +969,8 @@ HWTEST_F(InternalsEventTest, GivenBufferWithoutZeroCopyOnCommandMapOrUnmapFlushe csr.flushTaskStamp = -1; buffer.dataTransferedStamp = -1; buffer.swapCopyDirection(); - auto commandUnMap = std::unique_ptr(new CommandMapUnmap(UNMAP, buffer, csr, *pCmdQ)); + + auto commandUnMap = std::unique_ptr(new CommandMapUnmap(UNMAP, buffer, size, offset, false, csr, *pCmdQ)); EXPECT_EQ(0, executionStamp); EXPECT_EQ(-1, csr.flushTaskStamp); EXPECT_EQ(-1, buffer.dataTransferedStamp); diff --git a/unit_tests/helpers/task_information_tests.cpp b/unit_tests/helpers/task_information_tests.cpp index 0a7275f8bc..d3c15fa6ba 100644 --- a/unit_tests/helpers/task_information_tests.cpp +++ b/unit_tests/helpers/task_information_tests.cpp @@ -39,7 +39,10 @@ TEST(CommandTest, mapUnmapSubmitWithoutTerminateFlagFlushesCsr) { MockBuffer buffer; auto initialTaskCount = csr.peekTaskCount(); - std::unique_ptr command(new CommandMapUnmap(MapOperationType::MAP, buffer, csr, *cmdQ.get())); + + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + std::unique_ptr command(new CommandMapUnmap(MapOperationType::MAP, buffer, size, offset, false, csr, *cmdQ.get())); CompletionStamp completionStamp = command->submit(20, false); auto expectedTaskCount = initialTaskCount + 1; @@ -53,7 +56,10 @@ TEST(CommandTest, mapUnmapSubmitWithTerminateFlagAbortsFlush) { MockBuffer buffer; auto initialTaskCount = csr.peekTaskCount(); - std::unique_ptr command(new CommandMapUnmap(MapOperationType::MAP, buffer, csr, *cmdQ.get())); + + MemObjSizeArray size = {{1, 1, 1}}; + MemObjOffsetArray offset = {{0, 0, 0}}; + std::unique_ptr command(new CommandMapUnmap(MapOperationType::MAP, buffer, size, offset, false, csr, *cmdQ.get())); CompletionStamp completionStamp = command->submit(20, true); auto submitTaskCount = csr.peekTaskCount(); diff --git a/unit_tests/mem_obj/CMakeLists.txt b/unit_tests/mem_obj/CMakeLists.txt index da1c1a4b9f..6fee14b678 100644 --- a/unit_tests/mem_obj/CMakeLists.txt +++ b/unit_tests/mem_obj/CMakeLists.txt @@ -43,6 +43,7 @@ set(IGDRCL_SRCS_tests_mem_obj "${CMAKE_CURRENT_SOURCE_DIR}/image_array_size_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/image2d_from_buffer_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/image_tiled_tests.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/map_operations_handler_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/mem_obj_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/mem_obj_destruction_tests.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/nv12_image_tests.cpp" diff --git a/unit_tests/mem_obj/buffer_tests.cpp b/unit_tests/mem_obj/buffer_tests.cpp index c3f19d5ce7..caaac45c04 100644 --- a/unit_tests/mem_obj/buffer_tests.cpp +++ b/unit_tests/mem_obj/buffer_tests.cpp @@ -44,6 +44,28 @@ TEST(Buffer, FromCL_nullptr_returnsNullPtr) { EXPECT_EQ(nullptr, castToObject(nullptr)); } +TEST(Buffer, giveBufferWhenAskedForPtrOffsetForMappingThenReturnCorrectValue) { + MockContext ctx; + cl_int retVal; + std::unique_ptr buffer(Buffer::create(&ctx, 0, 1, nullptr, retVal)); + + MemObjOffsetArray offset = {{4, 5, 6}}; + + auto retOffset = buffer->calculateOffsetForMapping(offset); + EXPECT_EQ(offset[0], retOffset); +} + +TEST(Buffer, givenBufferWhenAskedForPtrLengthThenReturnCorrectValue) { + MockContext ctx; + cl_int retVal; + std::unique_ptr buffer(Buffer::create(&ctx, 0, 1, nullptr, retVal)); + + MemObjSizeArray size = {{4, 5, 6}}; + + auto retOffset = buffer->calculateMappedPtrLength(size); + EXPECT_EQ(size[0], retOffset); +} + class BufferTest : public DeviceFixture, public testing::TestWithParam { public: @@ -827,7 +849,7 @@ HWTEST_F(BufferUnmapTest, givenBufferWithSharingHandlerWhenUnmappingThenUseEnque buffer->setSharingHandler(new SharingHandler()); EXPECT_NE(nullptr, buffer->peekSharingHandler()); - auto mappedPtr = clEnqueueMapBuffer(&cmdQ, buffer.get(), CL_TRUE, CL_MAP_READ, 0, 1, 0, nullptr, nullptr, &retVal); + auto mappedPtr = clEnqueueMapBuffer(&cmdQ, buffer.get(), CL_TRUE, CL_MAP_WRITE, 0, 1, 0, nullptr, nullptr, &retVal); EXPECT_EQ(CL_SUCCESS, retVal); EXPECT_EQ(0u, cmdQ.EnqueueWriteBufferCounter); @@ -863,9 +885,9 @@ TEST_F(BufferTransferTests, givenBufferWhenTransferToHostPtrCalledThenCopyReques MockContext context(pDevice); auto retVal = CL_SUCCESS; const size_t bufferSize = 100; - size_t copyOffset = 20; - size_t copySize = 10; size_t ignoredParam = 123; + MemObjOffsetArray copyOffset = {{20, ignoredParam, ignoredParam}}; + MemObjSizeArray copySize = {{10, ignoredParam, ignoredParam}}; uint8_t hostPtr[bufferSize] = {}; uint8_t expectedHostPtr[bufferSize] = {}; @@ -875,20 +897,20 @@ TEST_F(BufferTransferTests, givenBufferWhenTransferToHostPtrCalledThenCopyReques auto srcPtr = buffer->getCpuAddress(); EXPECT_NE(srcPtr, hostPtr); memset(srcPtr, 123, bufferSize); - memset(ptrOffset(expectedHostPtr, copyOffset), 123, copySize); + memset(ptrOffset(expectedHostPtr, copyOffset[0]), 123, copySize[0]); - buffer->transferDataToHostPtr({{copySize, ignoredParam, ignoredParam}}, {{copyOffset, ignoredParam, ignoredParam}}); + buffer->transferDataToHostPtr(copySize, copyOffset); - EXPECT_TRUE(memcmp(hostPtr, expectedHostPtr, copySize) == 0); + EXPECT_TRUE(memcmp(hostPtr, expectedHostPtr, copySize[0]) == 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; + MemObjOffsetArray copyOffset = {{20, ignoredParam, ignoredParam}}; + MemObjSizeArray copySize = {{10, ignoredParam, ignoredParam}}; uint8_t hostPtr[bufferSize] = {}; uint8_t expectedBufferMemory[bufferSize] = {}; @@ -897,9 +919,9 @@ TEST_F(BufferTransferTests, givenBufferWhenTransferFromHostPtrCalledThenCopyRequ EXPECT_NE(buffer->getCpuAddress(), hostPtr); memset(hostPtr, 123, bufferSize); - memset(ptrOffset(expectedBufferMemory, copyOffset), 123, copySize); + memset(ptrOffset(expectedBufferMemory, copyOffset[0]), 123, copySize[0]); - buffer->transferDataFromHostPtr({{copySize, ignoredParam, ignoredParam}}, {{copyOffset, ignoredParam, ignoredParam}}); + buffer->transferDataFromHostPtr(copySize, copyOffset); - EXPECT_TRUE(memcmp(expectedBufferMemory, buffer->getCpuAddress(), copySize) == 0); + EXPECT_TRUE(memcmp(expectedBufferMemory, buffer->getCpuAddress(), copySize[0]) == 0); } diff --git a/unit_tests/mem_obj/image_release_mapped_ptr_tests.cpp b/unit_tests/mem_obj/image_release_mapped_ptr_tests.cpp index 60d56b18e2..c582ec03aa 100644 --- a/unit_tests/mem_obj/image_release_mapped_ptr_tests.cpp +++ b/unit_tests/mem_obj/image_release_mapped_ptr_tests.cpp @@ -70,10 +70,11 @@ class ImageUnmapTest : public ::testing::Test { HWTEST_F(ImageUnmapTest, givenImageWhenUnmapMemObjIsCalledThenEnqueueNonBlockingMapImage) { std::unique_ptr> commandQueue(new MyMockCommandQueue(&context)); void *ptr = alignedMalloc(MemoryConstants::cacheLineSize, MemoryConstants::cacheLineSize); - size_t origin[3] = {0, 0, 0}; - size_t region[3] = {1, 1, 1}; + MemObjOffsetArray origin = {{0, 0, 0}}; + MemObjSizeArray region = {{1, 1, 1}}; image->setAllocatedMapPtr(ptr); - image->setMapInfo(ptr, region, origin); + cl_map_flags mapFlags = CL_MAP_WRITE; + image->addMappedPtr(ptr, 1, mapFlags, region, origin); commandQueue->enqueueUnmapMemObject(image.get(), ptr, 0, nullptr, nullptr); EXPECT_EQ(ptr, commandQueue->passedPtr); EXPECT_EQ((cl_bool)CL_FALSE, commandQueue->passedBlockingWrite); @@ -83,13 +84,23 @@ HWTEST_F(ImageUnmapTest, givenImageWhenUnmapMemObjIsCalledThenEnqueueNonBlocking HWTEST_F(ImageUnmapTest, givenImageWhenUnmapMemObjIsCalledWithMemUseHostPtrAndWithoutEventsThenFinishIsCalled) { std::unique_ptr> commandQueue(new MyMockCommandQueue(&context)); image.reset(ImageHelper>::create(&context)); - commandQueue->enqueueUnmapMemObject(image.get(), nullptr, 0, nullptr, nullptr); + auto ptr = image->getBasePtrForMap(); + MemObjOffsetArray origin = {{0, 0, 0}}; + MemObjSizeArray region = {{1, 1, 1}}; + cl_map_flags mapFlags = CL_MAP_WRITE; + image->addMappedPtr(ptr, 1, mapFlags, region, origin); + commandQueue->enqueueUnmapMemObject(image.get(), ptr, 0, nullptr, nullptr); EXPECT_EQ(1u, commandQueue->finishCalled); } HWTEST_F(ImageUnmapTest, givenImageWhenUnmapMemObjIsCalledWithoutMemUseHostPtrThenFinishIsCalled) { std::unique_ptr> commandQueue(new MyMockCommandQueue(&context)); - commandQueue->enqueueUnmapMemObject(image.get(), nullptr, 0, nullptr, nullptr); + auto ptr = image->getBasePtrForMap(); + MemObjOffsetArray origin = {{0, 0, 0}}; + MemObjSizeArray region = {{1, 1, 1}}; + cl_map_flags mapFlags = CL_MAP_WRITE; + image->addMappedPtr(ptr, 2, mapFlags, region, origin); + commandQueue->enqueueUnmapMemObject(image.get(), ptr, 0, nullptr, nullptr); EXPECT_EQ(1u, commandQueue->finishCalled); } @@ -110,7 +121,12 @@ HWTEST_F(ImageUnmapTest, givenImageWhenUnmapMemObjIsCalledWithMemUseHostPtrAndWi MockEvent mockEvent(&context); mockEvent.setStatus(0); cl_event clEvent = &mockEvent; - commandQueue->enqueueUnmapMemObject(image.get(), nullptr, 1, &clEvent, nullptr); + auto ptr = image->getBasePtrForMap(); + MemObjOffsetArray origin = {{0, 0, 0}}; + MemObjSizeArray region = {{1, 1, 1}}; + cl_map_flags mapFlags = CL_MAP_WRITE; + image->addMappedPtr(ptr, 1, mapFlags, region, origin); + commandQueue->enqueueUnmapMemObject(image.get(), ptr, 1, &clEvent, nullptr); EXPECT_EQ(1u, commandQueue->finishCalled); } diff --git a/unit_tests/mem_obj/image_tests.cpp b/unit_tests/mem_obj/image_tests.cpp index 6e175de004..91a951e624 100644 --- a/unit_tests/mem_obj/image_tests.cpp +++ b/unit_tests/mem_obj/image_tests.cpp @@ -770,8 +770,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyImageWhenDataTransferedFromHostPtrToMemSto memset((char *)unalignedHostPtr + imageSize, 2, 100 - 4); auto &imgDesc = imageNonZeroCopy->getImageDesc(); - imageNonZeroCopy->transferDataFromHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, - {{0, 0, 0}}); + MemObjOffsetArray copyOffset = {{0, 0, 0}}; + MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; + imageNonZeroCopy->transferDataFromHostPtr(copySize, copyOffset); void *foundData = memchr(memoryStorage, 2, memoryStorageSize); EXPECT_EQ(0, foundData); @@ -805,8 +806,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchImageWhenDataIsTransferedFr memset((char *)unalignedHostPtr + imageSize, 2, 100 - 4); auto &imgDesc = imageNonZeroCopy->getImageDesc(); - imageNonZeroCopy->transferDataFromHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, - {{0, 0, 0}}); + MemObjOffsetArray copyOffset = {{0, 0, 0}}; + MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; + imageNonZeroCopy->transferDataFromHostPtr(copySize, copyOffset); void *foundData = memchr(memoryStorage, 2, memoryStorageSize); EXPECT_EQ(0, foundData); @@ -863,8 +865,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchWithExtraBytes1DArrayImageW if (run == 1) { auto &imgDesc = imageNonZeroCopy->getImageDesc(); - imageNonZeroCopy->transferDataFromHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, - {{0, 0, 0}}); + MemObjOffsetArray copyOffset = {{0, 0, 0}}; + MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; + imageNonZeroCopy->transferDataFromHostPtr(copySize, copyOffset); } for (size_t arrayIndex = 0; arrayIndex < imageCount; ++arrayIndex) { @@ -884,8 +887,9 @@ TEST_F(ImageTransfer, GivenNonZeroCopyNonZeroRowPitchWithExtraBytes1DArrayImageW } auto &imgDesc = imageNonZeroCopy->getImageDesc(); - imageNonZeroCopy->transferDataToHostPtr({{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}, - {{0, 0, 0}}); + MemObjOffsetArray copyOffset = {{0, 0, 0}}; + MemObjSizeArray copySize = {{imgDesc.image_width, imgDesc.image_height, imgDesc.image_depth}}; + imageNonZeroCopy->transferDataToHostPtr(copySize, copyOffset); row = static_cast(unalignedHostPtr); @@ -997,7 +1001,7 @@ TEST(ImageTest, givenImageWhenAskedForPtrOffsetForGpuMappingThenReturnCorrectVal std::unique_ptr image(ImageHelper::create(&ctx)); EXPECT_FALSE(image->mappingOnCpuAllowed()); - size_t origin[3] = {4, 5, 6}; + MemObjOffsetArray origin = {{4, 5, 6}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().ImageElementSizeInBytes * origin[0] + @@ -1011,10 +1015,9 @@ TEST(ImageTest, givenImageWhenAskedForPtrOffsetForCpuMappingThenReturnCorrectVal DebugManager.flags.ForceLinearImages.set(true); MockContext ctx; std::unique_ptr image(ImageHelper::create(&ctx)); - EXPECT_TRUE(image->mappingOnCpuAllowed()); - size_t origin[3] = {4, 5, 6}; + MemObjOffsetArray origin = {{4, 5, 6}}; auto retOffset = image->calculateOffsetForMapping(origin); size_t expectedOffset = image->getSurfaceFormatInfo().ImageElementSizeInBytes * origin[0] + @@ -1023,3 +1026,34 @@ TEST(ImageTest, givenImageWhenAskedForPtrOffsetForCpuMappingThenReturnCorrectVal EXPECT_EQ(expectedOffset, retOffset); } + +TEST(ImageTest, givenImageWhenAskedForPtrLengthForGpuMappingThenReturnCorrectValue) { + MockContext ctx; + std::unique_ptr image(ImageHelper::create(&ctx)); + EXPECT_FALSE(image->mappingOnCpuAllowed()); + + MemObjSizeArray region = {{4, 5, 6}}; + + auto retLength = image->calculateMappedPtrLength(region); + size_t expectedLength = image->getSurfaceFormatInfo().ImageElementSizeInBytes * region[0] + + image->getHostPtrRowPitch() * region[1] + image->getHostPtrSlicePitch() * region[2]; + + EXPECT_EQ(expectedLength, retLength); +} + +TEST(ImageTest, givenImageWhenAskedForPtrLengthForCpuMappingThenReturnCorrectValue) { + DebugManagerStateRestore restore; + DebugManager.flags.ForceLinearImages.set(true); + MockContext ctx; + std::unique_ptr image(ImageHelper::create(&ctx)); + EXPECT_TRUE(image->mappingOnCpuAllowed()); + + MemObjSizeArray region = {{4, 5, 6}}; + + auto retLength = image->calculateMappedPtrLength(region); + size_t expectedLength = image->getSurfaceFormatInfo().ImageElementSizeInBytes * region[0] + + image->getImageDesc().image_row_pitch * region[1] + + image->getImageDesc().image_slice_pitch * region[2]; + + EXPECT_EQ(expectedLength, retLength); +} diff --git a/unit_tests/mem_obj/map_operations_handler_tests.cpp b/unit_tests/mem_obj/map_operations_handler_tests.cpp new file mode 100644 index 0000000000..1b55351fbf --- /dev/null +++ b/unit_tests/mem_obj/map_operations_handler_tests.cpp @@ -0,0 +1,176 @@ +/* + * 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/mem_obj/map_operations_handler.h" +#include "test.h" + +#include + +using namespace OCLRT; + +struct MockMapOperationsHandler : public MapOperationsHandler { + using MapOperationsHandler::isOverlapping; + using MapOperationsHandler::mappedPointers; +}; + +struct MapOperationsHandlerTests : public ::testing::Test { + MockMapOperationsHandler mockHandler; + MapInfo mappedPtrs[3] = { + {(void *)0x1000, 1, {{1, 2, 3}}, {{4, 5, 6}}}, + {(void *)0x2000, 1, {{7, 8, 9}}, {{10, 11, 12}}}, + {(void *)0x3000, 1, {{13, 14, 15}}, {{16, 17, 18}}}, + }; + cl_map_flags mapFlags = CL_MAP_READ; +}; + +TEST_F(MapOperationsHandlerTests, givenMapInfoWhenFindingThenReturnCorrectvalues) { + for (size_t i = 0; i < 3; i++) { + EXPECT_TRUE(mockHandler.add(mappedPtrs[i].ptr, mappedPtrs[i].ptrLength, mapFlags, mappedPtrs[i].size, mappedPtrs[i].offset)); + } + EXPECT_EQ(3u, mockHandler.size()); + + for (int i = 2; i >= 0; i--) { + MapInfo receivedMapInfo; + EXPECT_TRUE(mockHandler.find(mappedPtrs[i].ptr, receivedMapInfo)); + EXPECT_EQ(receivedMapInfo.ptr, mappedPtrs[i].ptr); + EXPECT_EQ(receivedMapInfo.size, mappedPtrs[i].size); + EXPECT_EQ(receivedMapInfo.offset, mappedPtrs[i].offset); + } +} + +TEST_F(MapOperationsHandlerTests, givenMapInfoWhenRemovingThenRemoveCorrectPointers) { + for (size_t i = 0; i < 3; i++) { + mockHandler.add(mappedPtrs[i].ptr, mappedPtrs[i].ptrLength, mapFlags, mappedPtrs[i].size, mappedPtrs[i].offset); + } + + for (int i = 2; i >= 0; i--) { + mockHandler.remove(mappedPtrs[i].ptr); + MapInfo receivedMapInfo; + EXPECT_FALSE(mockHandler.find(mappedPtrs[i].ptr, receivedMapInfo)); + } + EXPECT_EQ(0u, mockHandler.size()); +} + +TEST_F(MapOperationsHandlerTests, givenMappedPtrsWhenDoubleRemovedThenDoNothing) { + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + mockHandler.add(mappedPtrs[1].ptr, mappedPtrs[1].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + + EXPECT_EQ(2u, mockHandler.size()); + mockHandler.remove(mappedPtrs[1].ptr); + mockHandler.remove(mappedPtrs[1].ptr); + EXPECT_EQ(1u, mockHandler.size()); + + MapInfo receivedMapInfo; + EXPECT_FALSE(mockHandler.find(mappedPtrs[1].ptr, receivedMapInfo)); + EXPECT_TRUE(mockHandler.find(mappedPtrs[0].ptr, receivedMapInfo)); +} + +TEST_F(MapOperationsHandlerTests, givenMapInfoWhenAddedThenSetReadOnlyFlag) { + mapFlags = CL_MAP_READ; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + EXPECT_TRUE(mockHandler.mappedPointers.back().readOnly); + mockHandler.remove(mappedPtrs[0].ptr); + + mapFlags = CL_MAP_WRITE; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly); + mockHandler.remove(mappedPtrs[0].ptr); + + mapFlags = CL_MAP_WRITE_INVALIDATE_REGION; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly); + mockHandler.remove(mappedPtrs[0].ptr); + + mapFlags = CL_MAP_READ | CL_MAP_WRITE; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly); + mockHandler.remove(mappedPtrs[0].ptr); + + mapFlags = CL_MAP_READ | CL_MAP_WRITE_INVALIDATE_REGION; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly); + mockHandler.remove(mappedPtrs[0].ptr); +} + +TEST_F(MapOperationsHandlerTests, givenNonReadOnlyOverlappingPtrWhenAddingThenReturnFalseAndDontAdd) { + mapFlags = CL_MAP_WRITE; + mappedPtrs->readOnly = false; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + + EXPECT_EQ(1u, mockHandler.size()); + EXPECT_FALSE(mockHandler.mappedPointers.back().readOnly); + EXPECT_TRUE(mockHandler.isOverlapping(mappedPtrs[0])); + EXPECT_FALSE(mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset)); + EXPECT_EQ(1u, mockHandler.size()); +} + +TEST_F(MapOperationsHandlerTests, givenReadOnlyOverlappingPtrWhenAddingThenReturnTrueAndAdd) { + mapFlags = CL_MAP_READ; + mappedPtrs->readOnly = true; + mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset); + + EXPECT_EQ(1u, mockHandler.size()); + EXPECT_TRUE(mockHandler.mappedPointers.back().readOnly); + EXPECT_FALSE(mockHandler.isOverlapping(mappedPtrs[0])); + EXPECT_TRUE(mockHandler.add(mappedPtrs[0].ptr, mappedPtrs[0].ptrLength, mapFlags, mappedPtrs[0].size, mappedPtrs[0].offset)); + EXPECT_EQ(2u, mockHandler.size()); + EXPECT_TRUE(mockHandler.mappedPointers.back().readOnly); +} + +const std::tuple overlappingCombinations[] = { + // mappedPtrStart, mappedPtrLength, requestPtrStart, requestPtrLength, expectOverlap + std::make_tuple((void *)5000, 50, (void *)4000, 1, false), //requested before, non-overlapping + std::make_tuple((void *)5000, 50, (void *)4999, 10, true), //requested before, overlapping inside + std::make_tuple((void *)5000, 50, (void *)4999, 100, true), //requested before, overlapping outside + std::make_tuple((void *)5000, 50, (void *)5001, 1, true), //requested inside, overlapping inside + std::make_tuple((void *)5000, 50, (void *)5001, 100, true), //requested inside, overlapping outside + std::make_tuple((void *)5000, 50, (void *)6000, 1, false), //requested after, non-overlapping + std::make_tuple((void *)5000, 50, (void *)5000, 1, true), //requested on start, overlapping inside + std::make_tuple((void *)5000, 50, (void *)5000, 100, true), //requested on start, overlapping outside +}; + +struct MapOperationsHandlerOverlapTests : public ::testing::WithParamInterface>, + public ::testing::Test {}; + +TEST_P(MapOperationsHandlerOverlapTests, givenAlreadyMappedPtrWhenAskingForOverlapThenReturnCorrectValue) { + cl_map_flags mapFlags = CL_MAP_WRITE; + void *mappedPtr = std::get<0>(GetParam()); + size_t mappedPtrLength = std::get<1>(GetParam()); + void *requestedPtr = std::get<2>(GetParam()); + size_t requestedPtrLength = std::get<3>(GetParam()); + bool expectOverlap = std::get<4>(GetParam()); + + // size and offset arrays are ignored + MapInfo mappedInfo(mappedPtr, mappedPtrLength, {{0, 0, 0}}, {{0, 0, 0}}); + MapInfo requestedInfo(requestedPtr, requestedPtrLength, {{0, 0, 0}}, {{0, 0, 0}}); + requestedInfo.readOnly = false; + + MockMapOperationsHandler mockHandler; + mockHandler.add(mappedInfo.ptr, mappedInfo.ptrLength, mapFlags, mappedInfo.size, mappedInfo.offset); + + EXPECT_EQ(expectOverlap, mockHandler.isOverlapping(requestedInfo)); +} + +INSTANTIATE_TEST_CASE_P(MapOperationsHandlerOverlapTests, + MapOperationsHandlerOverlapTests, + ::testing::ValuesIn(overlappingCombinations)); diff --git a/unit_tests/mem_obj/mem_obj_destruction_tests.cpp b/unit_tests/mem_obj/mem_obj_destruction_tests.cpp index d938a9024d..b8d3325c81 100644 --- a/unit_tests/mem_obj/mem_obj_destruction_tests.cpp +++ b/unit_tests/mem_obj/mem_obj_destruction_tests.cpp @@ -189,13 +189,14 @@ HWTEST_P(MemObjAsyncDestructionTest, givenUsedMemObjWithAsyncDestructionsEnabled if (!hasAllocatedMappedPtr) { delete memObj; allocation = memoryManager->allocateGraphicsMemory(size, MemoryConstants::pageSize); - size_t origin[3] = {0, 0, 0}; - size_t region[3] = {1, 1, 1}; + MemObjOffsetArray origin = {{0, 0, 0}}; + MemObjSizeArray region = {{1, 1, 1}}; + cl_map_flags mapFlags = CL_MAP_READ; memObj = new MemObj(&context, CL_MEM_OBJECT_BUFFER, CL_MEM_READ_WRITE, size, storage, nullptr, allocation, true, false, false); - memObj->setMapInfo(storage, region, origin); + memObj->addMappedPtr(storage, 1, mapFlags, region, origin); } else { memObj->setAllocatedMapPtr(storage); } diff --git a/unit_tests/mem_obj/mem_obj_tests.cpp b/unit_tests/mem_obj/mem_obj_tests.cpp index 7687f538ea..a83f8ae99a 100644 --- a/unit_tests/mem_obj/mem_obj_tests.cpp +++ b/unit_tests/mem_obj/mem_obj_tests.cpp @@ -59,13 +59,6 @@ TEST(MemObj, GivenMemObjWhenInititalizedFromHostPtrThenInitializeFields) { EXPECT_EQ(&buffer, memObj.getHostPtr()); EXPECT_EQ(size, memObj.getSize()); EXPECT_EQ(static_cast(CL_MEM_USE_HOST_PTR), memObj.getFlags()); - EXPECT_EQ(nullptr, memObj.getMappedPtr()); - EXPECT_EQ(0u, memObj.getMappedSize()[0]); - EXPECT_EQ(0u, memObj.getMappedSize()[1]); - EXPECT_EQ(0u, memObj.getMappedSize()[2]); - EXPECT_EQ(0u, memObj.getMappedOffset()[0]); - EXPECT_EQ(0u, memObj.getMappedOffset()[1]); - EXPECT_EQ(0u, memObj.getMappedOffset()[2]); } TEST(MemObj, givenMemObjectWhenAskedForTransferToHostPtrThenDoNothing) { @@ -80,7 +73,9 @@ TEST(MemObj, givenMemObjectWhenAskedForTransferToHostPtrThenDoNothing) { memset(memObj.getCpuAddress(), 123, size); memset(hostPtr, 0, size); - EXPECT_THROW(memObj.transferDataToHostPtr({{size, 0, 0}}, {{0, 0, 0}}), std::exception); + MemObjOffsetArray copyOffset = {{0, 0, 0}}; + MemObjSizeArray copySize = {{size, 0, 0}}; + EXPECT_THROW(memObj.transferDataToHostPtr(copySize, copyOffset), std::exception); EXPECT_TRUE(memcmp(hostPtr, expectedHostPtr, size) == 0); } @@ -97,26 +92,13 @@ TEST(MemObj, givenMemObjectWhenAskedForTransferFromHostPtrThenDoNothing) { memset(memObj.getCpuAddress(), 123, size); memset(expectedBufferPtr, 123, size); - EXPECT_THROW(memObj.transferDataFromHostPtr({{size, 0, 0}}, {{0, 0, 0}}), std::exception); + MemObjOffsetArray copyOffset = {{0, 0, 0}}; + MemObjSizeArray copySize = {{size, 0, 0}}; + EXPECT_THROW(memObj.transferDataFromHostPtr(copySize, copyOffset), std::exception); EXPECT_TRUE(memcmp(memObj.getCpuAddress(), expectedBufferPtr, size) == 0); } -TEST(MemObj, givenMemObjWhenAllocatedMappedPtrIsSetThenGetMappedPtrIsDifferentThanAllocatedMappedPtr) { - void *mockPtr = (void *)0x01234; - MockContext context; - - MemObj memObj(&context, CL_MEM_OBJECT_BUFFER, CL_MEM_USE_HOST_PTR, - 1, nullptr, nullptr, nullptr, true, false, false); - - EXPECT_EQ(nullptr, memObj.getAllocatedMapPtr()); - EXPECT_EQ(nullptr, memObj.getMappedPtr()); - memObj.setAllocatedMapPtr(mockPtr); - EXPECT_EQ(mockPtr, memObj.getAllocatedMapPtr()); - EXPECT_NE(mockPtr, memObj.getMappedPtr()); - memObj.setAllocatedMapPtr(nullptr); -} - TEST(MemObj, givenHostPtrAndUseHostPtrFlagWhenAskingForBaseMapPtrThenReturnHostPtr) { uint8_t hostPtr = 0; MockContext context;