1 /*
2  * Copyright (C) 2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "opencl/source/memory_manager/migration_controller.h"
9 
10 #include "shared/source/command_stream/command_stream_receiver.h"
11 #include "shared/source/memory_manager/memory_manager.h"
12 #include "shared/source/memory_manager/migration_sync_data.h"
13 
14 #include "opencl/source/command_queue/command_queue.h"
15 #include "opencl/source/context/context.h"
16 #include "opencl/source/mem_obj/image.h"
17 #include "opencl/source/mem_obj/mem_obj.h"
18 
19 namespace NEO {
handleMigration(Context & context,CommandStreamReceiver & targetCsr,MemObj * memObj)20 void MigrationController::handleMigration(Context &context, CommandStreamReceiver &targetCsr, MemObj *memObj) {
21     auto memoryManager = targetCsr.getMemoryManager();
22     auto targetRootDeviceIndex = targetCsr.getRootDeviceIndex();
23     auto migrationSyncData = memObj->getMultiGraphicsAllocation().getMigrationSyncData();
24     if (!migrationSyncData->isUsedByTheSameContext(targetCsr.getTagAddress())) {
25         migrationSyncData->waitOnCpu();
26     }
27     if (migrationSyncData->getCurrentLocation() != targetRootDeviceIndex) {
28         migrateMemory(context, *memoryManager, memObj, targetRootDeviceIndex);
29     }
30     migrationSyncData->signalUsage(targetCsr.getTagAddress(), targetCsr.peekTaskCount() + 1);
31 }
32 
migrateMemory(Context & context,MemoryManager & memoryManager,MemObj * memObj,uint32_t targetRootDeviceIndex)33 void MigrationController::migrateMemory(Context &context, MemoryManager &memoryManager, MemObj *memObj, uint32_t targetRootDeviceIndex) {
34     auto &multiGraphicsAllocation = memObj->getMultiGraphicsAllocation();
35     auto migrationSyncData = multiGraphicsAllocation.getMigrationSyncData();
36 
37     auto sourceRootDeviceIndex = migrationSyncData->getCurrentLocation();
38     if (sourceRootDeviceIndex == std::numeric_limits<uint32_t>::max()) {
39         migrationSyncData->setCurrentLocation(targetRootDeviceIndex);
40         return;
41     }
42 
43     migrationSyncData->startMigration();
44 
45     auto srcMemory = multiGraphicsAllocation.getGraphicsAllocation(sourceRootDeviceIndex);
46     auto dstMemory = multiGraphicsAllocation.getGraphicsAllocation(targetRootDeviceIndex);
47 
48     auto size = srcMemory->getUnderlyingBufferSize();
49     auto hostPtr = migrationSyncData->getHostPtr();
50 
51     if (srcMemory->isAllocationLockable()) {
52         auto srcLockPtr = memoryManager.lockResource(srcMemory);
53         memcpy_s(hostPtr, size, srcLockPtr, size);
54         memoryManager.unlockResource(srcMemory);
55     } else {
56 
57         auto srcCmdQ = context.getSpecialQueue(sourceRootDeviceIndex);
58         if (srcMemory->getAllocationType() == GraphicsAllocation::AllocationType::IMAGE) {
59             auto pImage = static_cast<Image *>(memObj);
60             size_t origin[3] = {};
61             size_t region[3] = {};
62             pImage->fillImageRegion(region);
63 
64             srcCmdQ->enqueueReadImage(pImage, CL_TRUE, origin, region, pImage->getHostPtrRowPitch(), pImage->getHostPtrSlicePitch(), hostPtr, nullptr, 0, nullptr, nullptr);
65         } else {
66             auto pBuffer = static_cast<Buffer *>(memObj);
67             srcCmdQ->enqueueReadBuffer(pBuffer, CL_TRUE, 0u, pBuffer->getSize(), hostPtr, nullptr, 0, nullptr, nullptr);
68         }
69         srcCmdQ->finish();
70     }
71 
72     if (dstMemory->isAllocationLockable()) {
73         auto dstLockPtr = memoryManager.lockResource(dstMemory);
74         memcpy_s(dstLockPtr, size, hostPtr, size);
75         memoryManager.unlockResource(dstMemory);
76     } else {
77 
78         auto dstCmdQ = context.getSpecialQueue(targetRootDeviceIndex);
79         if (dstMemory->getAllocationType() == GraphicsAllocation::AllocationType::IMAGE) {
80             auto pImage = static_cast<Image *>(memObj);
81             size_t origin[3] = {};
82             size_t region[3] = {};
83             pImage->fillImageRegion(region);
84 
85             dstCmdQ->enqueueWriteImage(pImage, CL_TRUE, origin, region, pImage->getHostPtrRowPitch(), pImage->getHostPtrSlicePitch(), hostPtr, nullptr, 0, nullptr, nullptr);
86         } else {
87             auto pBuffer = static_cast<Buffer *>(memObj);
88             dstCmdQ->enqueueWriteBuffer(pBuffer, CL_TRUE, 0u, pBuffer->getSize(), hostPtr, nullptr, 0, nullptr, nullptr);
89         }
90         dstCmdQ->finish();
91     }
92     migrationSyncData->setCurrentLocation(targetRootDeviceIndex);
93 }
94 } // namespace NEO