1 /*
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "platform.h"
9 
10 #include "shared/source/built_ins/sip.h"
11 #include "shared/source/command_stream/command_stream_receiver.h"
12 #include "shared/source/compiler_interface/compiler_interface.h"
13 #include "shared/source/compiler_interface/oclc_extensions.h"
14 #include "shared/source/debug_settings/debug_settings_manager.h"
15 #include "shared/source/device/root_device.h"
16 #include "shared/source/execution_environment/execution_environment.h"
17 #include "shared/source/execution_environment/root_device_environment.h"
18 #include "shared/source/gmm_helper/gmm_helper.h"
19 #include "shared/source/helpers/debug_helpers.h"
20 #include "shared/source/helpers/get_info.h"
21 #include "shared/source/helpers/hw_helper.h"
22 #include "shared/source/helpers/string.h"
23 #include "shared/source/os_interface/device_factory.h"
24 #include "shared/source/os_interface/os_interface.h"
25 #include "shared/source/source_level_debugger/source_level_debugger.h"
26 
27 #include "opencl/source/api/api.h"
28 #include "opencl/source/cl_device/cl_device.h"
29 #include "opencl/source/gtpin/gtpin_notify.h"
30 #include "opencl/source/helpers/get_info_status_mapper.h"
31 #include "opencl/source/sharings/sharing_factory.h"
32 
33 #include "CL/cl_ext.h"
34 
35 #include <algorithm>
36 #include <map>
37 namespace NEO {
38 
39 std::vector<std::unique_ptr<Platform>> *platformsImpl = nullptr;
40 
Platform(ExecutionEnvironment & executionEnvironmentIn)41 Platform::Platform(ExecutionEnvironment &executionEnvironmentIn) : executionEnvironment(executionEnvironmentIn) {
42     clDevices.reserve(4);
43     executionEnvironment.incRefInternal();
44 }
45 
~Platform()46 Platform::~Platform() {
47     for (auto clDevice : this->clDevices) {
48         clDevice->decRefInternal();
49     }
50 
51     gtpinNotifyPlatformShutdown();
52     executionEnvironment.decRefInternal();
53 }
54 
getInfo(cl_platform_info paramName,size_t paramValueSize,void * paramValue,size_t * paramValueSizeRet)55 cl_int Platform::getInfo(cl_platform_info paramName,
56                          size_t paramValueSize,
57                          void *paramValue,
58                          size_t *paramValueSizeRet) {
59     auto retVal = CL_INVALID_VALUE;
60     const std::string *param = nullptr;
61     size_t paramSize = GetInfo::invalidSourceSize;
62     auto getInfoStatus = GetInfoStatus::INVALID_VALUE;
63 
64     switch (paramName) {
65     case CL_PLATFORM_HOST_TIMER_RESOLUTION: {
66         auto pVal = static_cast<uint64_t>(this->clDevices[0]->getPlatformHostTimerResolution());
67         paramSize = sizeof(uint64_t);
68         getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, &pVal, paramSize);
69         break;
70     }
71     case CL_PLATFORM_NUMERIC_VERSION: {
72         auto pVal = platformInfo->numericVersion;
73         paramSize = sizeof(pVal);
74         getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, &pVal, paramSize);
75         break;
76     }
77     case CL_PLATFORM_EXTENSIONS_WITH_VERSION: {
78         std::call_once(initializeExtensionsWithVersionOnce, [this]() {
79             this->clDevices[0]->getDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_VERSION, 0, nullptr, nullptr);
80             this->platformInfo->extensionsWithVersion = this->clDevices[0]->getDeviceInfo().extensionsWithVersion;
81         });
82 
83         auto pVal = platformInfo->extensionsWithVersion.data();
84         paramSize = platformInfo->extensionsWithVersion.size() * sizeof(cl_name_version);
85         getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, pVal, paramSize);
86         break;
87     }
88     case CL_PLATFORM_PROFILE:
89         param = &platformInfo->profile;
90         break;
91     case CL_PLATFORM_VERSION:
92         param = &platformInfo->version;
93         break;
94     case CL_PLATFORM_NAME:
95         param = &platformInfo->name;
96         break;
97     case CL_PLATFORM_VENDOR:
98         param = &platformInfo->vendor;
99         break;
100     case CL_PLATFORM_EXTENSIONS:
101         param = &platformInfo->extensions;
102         break;
103     case CL_PLATFORM_ICD_SUFFIX_KHR:
104         param = &platformInfo->icdSuffixKhr;
105         break;
106     default:
107         break;
108     }
109 
110     // Case for string parameters
111     if (param) {
112         paramSize = param->length() + 1;
113         getInfoStatus = GetInfo::getInfo(paramValue, paramValueSize, param->c_str(), paramSize);
114     }
115 
116     retVal = changeGetInfoStatusToCLResultType(getInfoStatus);
117     GetInfo::setParamValueReturnSize(paramValueSizeRet, paramSize, getInfoStatus);
118 
119     return retVal;
120 }
121 
initialize(std::vector<std::unique_ptr<Device>> devices)122 bool Platform::initialize(std::vector<std::unique_ptr<Device>> devices) {
123 
124     TakeOwnershipWrapper<Platform> platformOwnership(*this);
125     if (devices.empty()) {
126         return false;
127     }
128     if (state == StateInited) {
129         return true;
130     }
131 
132     state = StateIniting;
133 
134     for (auto &inputDevice : devices) {
135         ClDevice *pClDevice = nullptr;
136         auto pDevice = inputDevice.release();
137         UNRECOVERABLE_IF(!pDevice);
138         pClDevice = new ClDevice{*pDevice, this};
139         this->clDevices.push_back(pClDevice);
140 
141         if (pClDevice->getPreemptionMode() == PreemptionMode::MidThread || pClDevice->isDebuggerActive()) {
142             bool ret = SipKernel::initSipKernel(SipKernel::getSipKernelType(*pDevice), *pDevice);
143             UNRECOVERABLE_IF(!ret);
144         }
145     }
146 
147     DEBUG_BREAK_IF(this->platformInfo);
148     this->platformInfo.reset(new PlatformInfo);
149 
150     this->platformInfo->extensions = this->clDevices[0]->getDeviceInfo().deviceExtensions;
151 
152     switch (this->clDevices[0]->getEnabledClVersion()) {
153     case 30:
154         this->platformInfo->version = "OpenCL 3.0 ";
155         this->platformInfo->numericVersion = CL_MAKE_VERSION(3, 0, 0);
156         break;
157     case 21:
158         this->platformInfo->version = "OpenCL 2.1 ";
159         this->platformInfo->numericVersion = CL_MAKE_VERSION(2, 1, 0);
160         break;
161     default:
162         this->platformInfo->version = "OpenCL 1.2 ";
163         this->platformInfo->numericVersion = CL_MAKE_VERSION(1, 2, 0);
164         break;
165     }
166 
167     this->fillGlobalDispatchTable();
168     DEBUG_BREAK_IF(DebugManager.flags.CreateMultipleSubDevices.get() > 1 && !this->clDevices[0]->getDefaultEngine().commandStreamReceiver->peekTimestampPacketWriteEnabled());
169     state = StateInited;
170     return true;
171 }
172 
fillGlobalDispatchTable()173 void Platform::fillGlobalDispatchTable() {
174     sharingFactory.fillGlobalDispatchTable();
175 }
176 
isInitialized()177 bool Platform::isInitialized() {
178     TakeOwnershipWrapper<Platform> platformOwnership(*this);
179     bool ret = (this->state == StateInited);
180     return ret;
181 }
182 
getClDevice(size_t deviceOrdinal)183 ClDevice *Platform::getClDevice(size_t deviceOrdinal) {
184     TakeOwnershipWrapper<Platform> platformOwnership(*this);
185 
186     if (this->state != StateInited || deviceOrdinal >= clDevices.size()) {
187         return nullptr;
188     }
189 
190     auto pClDevice = clDevices[deviceOrdinal];
191     DEBUG_BREAK_IF(pClDevice == nullptr);
192 
193     return pClDevice;
194 }
195 
getNumDevices() const196 size_t Platform::getNumDevices() const {
197     TakeOwnershipWrapper<const Platform> platformOwnership(*this);
198 
199     if (this->state != StateInited) {
200         return 0;
201     }
202 
203     return clDevices.size();
204 }
205 
getClDevices()206 ClDevice **Platform::getClDevices() {
207     TakeOwnershipWrapper<Platform> platformOwnership(*this);
208 
209     if (this->state != StateInited) {
210         return nullptr;
211     }
212 
213     return clDevices.data();
214 }
215 
getPlatformInfo() const216 const PlatformInfo &Platform::getPlatformInfo() const {
217     DEBUG_BREAK_IF(!platformInfo);
218     return *platformInfo;
219 }
220 
__anond14040e80202(ExecutionEnvironment &executionEnvironment) 221 std::unique_ptr<Platform> (*Platform::createFunc)(ExecutionEnvironment &) = [](ExecutionEnvironment &executionEnvironment) -> std::unique_ptr<Platform> {
222     return std::make_unique<Platform>(executionEnvironment);
223 };
224 
groupDevices(DeviceVector devices)225 std::vector<DeviceVector> Platform::groupDevices(DeviceVector devices) {
226     std::map<PRODUCT_FAMILY, size_t> platformsMap;
227     std::vector<DeviceVector> outDevices;
228     for (auto &device : devices) {
229         auto productFamily = device->getHardwareInfo().platform.eProductFamily;
230         auto result = platformsMap.find(productFamily);
231         if (result == platformsMap.end()) {
232             platformsMap.insert({productFamily, platformsMap.size()});
233             outDevices.push_back(DeviceVector{});
234         }
235         auto platformId = platformsMap[productFamily];
236         outDevices[platformId].push_back(std::move(device));
237     }
238     std::sort(outDevices.begin(), outDevices.end(), [](DeviceVector &lhs, DeviceVector &rhs) -> bool {
239         return lhs[0]->getHardwareInfo().platform.eProductFamily > rhs[0]->getHardwareInfo().platform.eProductFamily;
240     });
241     return outDevices;
242 }
243 
244 } // namespace NEO
245