1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
/*
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/built_ins/built_ins.h"
#include "shared/source/command_stream/command_stream_receiver.h"
#include "shared/source/helpers/cache_policy.h"
#include "shared/source/helpers/engine_node_helper.h"
#include "shared/source/memory_manager/unified_memory_manager.h"
#include "shared/source/os_interface/os_context.h"
#include "opencl/source/command_queue/command_queue_hw.h"
#include "opencl/source/command_queue/enqueue_common.h"
#include "opencl/source/helpers/hardware_commands_helper.h"
#include "opencl/source/mem_obj/buffer.h"
#include "opencl/source/memory_manager/mem_obj_surface.h"
#include <new>
namespace NEO {
template <typename GfxFamily>
cl_int CommandQueueHw<GfxFamily>::enqueueReadBuffer(
Buffer *buffer,
cl_bool blockingRead,
size_t offset,
size_t size,
void *ptr,
GraphicsAllocation *mapAllocation,
cl_uint numEventsInWaitList,
const cl_event *eventWaitList,
cl_event *event) {
const cl_command_type cmdType = CL_COMMAND_READ_BUFFER;
auto &csr = getCommandStreamReceiverByCommandType(cmdType);
if (nullptr == mapAllocation) {
notifyEnqueueReadBuffer(buffer, !!blockingRead, EngineHelpers::isBcs(csr.getOsContext().getEngineType()));
}
auto rootDeviceIndex = getDevice().getRootDeviceIndex();
bool isMemTransferNeeded = buffer->isMemObjZeroCopy() ? buffer->checkIfMemoryTransferIsRequired(offset, 0, ptr, cmdType) : true;
bool isCpuCopyAllowed = bufferCpuCopyAllowed(buffer, cmdType, blockingRead, size, ptr,
numEventsInWaitList, eventWaitList);
//check if we are dealing with SVM pointer here for which we already have an allocation
if (!mapAllocation && this->getContext().getSVMAllocsManager()) {
auto svmEntry = this->getContext().getSVMAllocsManager()->getSVMAlloc(ptr);
if (svmEntry) {
if ((svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex)->getGpuAddress() + svmEntry->size) < (castToUint64(ptr) + size)) {
return CL_INVALID_OPERATION;
}
mapAllocation = svmEntry->cpuAllocation ? svmEntry->cpuAllocation : svmEntry->gpuAllocations.getGraphicsAllocation(rootDeviceIndex);
if (isCpuCopyAllowed) {
if (svmEntry->memoryType == DEVICE_UNIFIED_MEMORY) {
isCpuCopyAllowed = false;
}
}
}
}
if (isCpuCopyAllowed) {
if (isMemTransferNeeded) {
return enqueueReadWriteBufferOnCpuWithMemoryTransfer(cmdType, buffer, offset, size, ptr,
numEventsInWaitList, eventWaitList, event);
} else {
return enqueueReadWriteBufferOnCpuWithoutMemoryTransfer(cmdType, buffer, offset, size, ptr,
numEventsInWaitList, eventWaitList, event);
}
} else if (!isMemTransferNeeded) {
return enqueueMarkerForReadWriteOperation(buffer, ptr, cmdType, blockingRead,
numEventsInWaitList, eventWaitList, event);
}
auto eBuiltInOps = EBuiltInOps::CopyBufferToBuffer;
if (forceStateless(buffer->getSize())) {
eBuiltInOps = EBuiltInOps::CopyBufferToBufferStateless;
}
void *dstPtr = ptr;
MemObjSurface bufferSurf(buffer);
HostPtrSurface hostPtrSurf(dstPtr, size);
GeneralSurface mapSurface;
Surface *surfaces[] = {&bufferSurf, nullptr};
if (mapAllocation) {
surfaces[1] = &mapSurface;
mapSurface.setGraphicsAllocation(mapAllocation);
//get offset between base cpu ptr of map allocation and dst ptr
size_t dstOffset = ptrDiff(dstPtr, mapAllocation->getUnderlyingBuffer());
dstPtr = reinterpret_cast<void *>(mapAllocation->getGpuAddress() + dstOffset);
} else {
surfaces[1] = &hostPtrSurf;
if (size != 0) {
bool status = csr.createAllocationForHostSurface(hostPtrSurf, true);
if (!status) {
return CL_OUT_OF_RESOURCES;
}
dstPtr = reinterpret_cast<void *>(hostPtrSurf.getAllocation()->getGpuAddress());
}
}
void *alignedDstPtr = alignDown(dstPtr, 4);
size_t dstPtrOffset = ptrDiff(dstPtr, alignedDstPtr);
BuiltinOpParams dc;
dc.dstPtr = alignedDstPtr;
dc.dstOffset = {dstPtrOffset, 0, 0};
dc.srcMemObj = buffer;
dc.srcOffset = {offset, 0, 0};
dc.size = {size, 0, 0};
dc.transferAllocation = mapAllocation ? mapAllocation : hostPtrSurf.getAllocation();
MultiDispatchInfo dispatchInfo(dc);
if (context->isProvidingPerformanceHints()) {
context->providePerformanceHintForMemoryTransfer(CL_COMMAND_READ_BUFFER, true, static_cast<cl_mem>(buffer), ptr);
if (!isL3Capable(ptr, size)) {
context->providePerformanceHint(CL_CONTEXT_DIAGNOSTICS_LEVEL_BAD_INTEL, CL_ENQUEUE_READ_BUFFER_DOESNT_MEET_ALIGNMENT_RESTRICTIONS, ptr, size, MemoryConstants::pageSize, MemoryConstants::pageSize);
}
}
dispatchBcsOrGpgpuEnqueue<CL_COMMAND_READ_BUFFER>(dispatchInfo, surfaces, eBuiltInOps, numEventsInWaitList, eventWaitList, event, blockingRead);
return CL_SUCCESS;
}
} // namespace NEO
|