1 /*
2 * Copyright (C) 2020-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include "opencl/source/cl_device/cl_device.h"
9
10 #include "shared/source/compiler_interface/oclc_extensions.h"
11 #include "shared/source/debug_settings/debug_settings_manager.h"
12 #include "shared/source/device/device.h"
13 #include "shared/source/device/sub_device.h"
14 #include "shared/source/execution_environment/root_device_environment.h"
15 #include "shared/source/helpers/hw_helper.h"
16 #include "shared/source/helpers/string.h"
17 #include "shared/source/os_interface/driver_info.h"
18 #include "shared/source/os_interface/os_interface.h"
19 #include "shared/source/source_level_debugger/source_level_debugger.h"
20
21 #include "opencl/source/helpers/cl_hw_helper.h"
22 #include "opencl/source/platform/platform.h"
23
24 namespace NEO {
25
ClDevice(Device & device,ClDevice & rootClDevice,Platform * platform)26 ClDevice::ClDevice(Device &device, ClDevice &rootClDevice, Platform *platform) : device(device), rootClDevice(rootClDevice), platformId(platform) {
27 device.incRefInternal();
28 device.setSpecializedDevice(this);
29 deviceExtensions.reserve(1000);
30 name.reserve(100);
31 auto osInterface = getRootDeviceEnvironment().osInterface.get();
32 driverInfo.reset(DriverInfo::create(&device.getHardwareInfo(), osInterface));
33 initializeCaps();
34 OpenClCFeaturesContainer emptyOpenClCFeatures;
35 compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(deviceInfo.deviceExtensions, emptyOpenClCFeatures);
36 compilerExtensionsWithFeatures = convertEnabledExtensionsToCompilerInternalOptions(deviceInfo.deviceExtensions, deviceInfo.openclCFeatures);
37
38 for (auto &subDevice : device.getSubDevices()) {
39 if (!subDevice) {
40 continue;
41 }
42
43 auto pClSubDevice = std::make_unique<ClDevice>(*subDevice, rootClDevice, platform);
44 pClSubDevice->incRefInternal();
45 pClSubDevice->decRefApi();
46
47 auto &deviceInfo = pClSubDevice->deviceInfo;
48 deviceInfo.parentDevice = this;
49 deviceInfo.partitionType[0] = CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN;
50 deviceInfo.partitionType[1] = CL_DEVICE_AFFINITY_DOMAIN_NUMA;
51 deviceInfo.partitionType[2] = 0;
52
53 subDevices.push_back(std::move(pClSubDevice));
54 }
55
56 if (getSharedDeviceInfo().debuggerActive && getSourceLevelDebugger()) {
57 auto osInterface = device.getRootDeviceEnvironment().osInterface.get();
58 getSourceLevelDebugger()->notifyNewDevice(osInterface ? osInterface->getDriverModel()->getDeviceHandle() : 0);
59 }
60 }
61
ClDevice(Device & device,Platform * platformId)62 ClDevice::ClDevice(Device &device, Platform *platformId) : ClDevice(device, *this, platformId) {
63 }
64
~ClDevice()65 ClDevice::~ClDevice() {
66
67 if (getSharedDeviceInfo().debuggerActive && getSourceLevelDebugger()) {
68 getSourceLevelDebugger()->notifyDeviceDestruction();
69 }
70
71 for (auto &subDevice : subDevices) {
72 subDevice.reset();
73 }
74 device.decRefInternal();
75 }
76
incRefInternal()77 void ClDevice::incRefInternal() {
78 if (deviceInfo.parentDevice == nullptr) {
79 BaseObject<_cl_device_id>::incRefInternal();
80 return;
81 }
82 auto pParentDevice = static_cast<ClDevice *>(deviceInfo.parentDevice);
83 pParentDevice->incRefInternal();
84 }
85
decRefInternal()86 unique_ptr_if_unused<ClDevice> ClDevice::decRefInternal() {
87 if (deviceInfo.parentDevice == nullptr) {
88 return BaseObject<_cl_device_id>::decRefInternal();
89 }
90 auto pParentDevice = static_cast<ClDevice *>(deviceInfo.parentDevice);
91 return pParentDevice->decRefInternal();
92 }
93
isOcl21Conformant() const94 bool ClDevice::isOcl21Conformant() const {
95 auto &hwInfo = device.getHardwareInfo();
96 return (hwInfo.capabilityTable.supportsOcl21Features && hwInfo.capabilityTable.supportsDeviceEnqueue &&
97 hwInfo.capabilityTable.supportsPipes && hwInfo.capabilityTable.supportsIndependentForwardProgress);
98 }
99
retainApi()100 void ClDevice::retainApi() {
101 auto parentDeviceId = deviceInfo.parentDevice;
102 if (parentDeviceId) {
103 auto pParentClDevice = static_cast<ClDevice *>(parentDeviceId);
104 pParentClDevice->incRefInternal();
105 this->incRefApi();
106 }
107 };
releaseApi()108 unique_ptr_if_unused<ClDevice> ClDevice::releaseApi() {
109 auto parentDeviceId = deviceInfo.parentDevice;
110 if (!parentDeviceId) {
111 return unique_ptr_if_unused<ClDevice>(this, false);
112 }
113 auto pParentClDevice = static_cast<ClDevice *>(parentDeviceId);
114 pParentClDevice->decRefInternal();
115 return this->decRefApi();
116 }
117
getSharedDeviceInfo() const118 const DeviceInfo &ClDevice::getSharedDeviceInfo() const {
119 return device.getDeviceInfo();
120 }
121
getSubDevice(uint32_t deviceId) const122 ClDevice *ClDevice::getSubDevice(uint32_t deviceId) const {
123 UNRECOVERABLE_IF(deviceId >= subDevices.size());
124 return subDevices[deviceId].get();
125 }
126
getNearestGenericSubDevice(uint32_t deviceId)127 ClDevice *ClDevice::getNearestGenericSubDevice(uint32_t deviceId) {
128 /*
129 * EngineInstanced: Upper level
130 * Generic SubDevice: 'this'
131 * RootCsr Device: Next level SubDevice (generic)
132 */
133
134 if (getDevice().isEngineInstanced()) {
135 return rootClDevice.getNearestGenericSubDevice(Math::log2(static_cast<uint32_t>(getDeviceBitfield().to_ulong())));
136 }
137
138 if (subDevices.empty() || !getDevice().hasRootCsr()) {
139 return const_cast<ClDevice *>(this);
140 }
141 UNRECOVERABLE_IF(deviceId >= subDevices.size());
142 return subDevices[deviceId].get();
143 }
144
getDeviceAndHostTimer(uint64_t * deviceTimestamp,uint64_t * hostTimestamp) const145 bool ClDevice::getDeviceAndHostTimer(uint64_t *deviceTimestamp, uint64_t *hostTimestamp) const { return device.getDeviceAndHostTimer(deviceTimestamp, hostTimestamp); }
getHostTimer(uint64_t * hostTimestamp) const146 bool ClDevice::getHostTimer(uint64_t *hostTimestamp) const { return device.getHostTimer(hostTimestamp); }
getHardwareInfo() const147 const HardwareInfo &ClDevice::getHardwareInfo() const { return device.getHardwareInfo(); }
getEngine(aub_stream::EngineType engineType,EngineUsage engineUsage)148 EngineControl &ClDevice::getEngine(aub_stream::EngineType engineType, EngineUsage engineUsage) { return device.getEngine(engineType, engineUsage); }
getDefaultEngine()149 EngineControl &ClDevice::getDefaultEngine() { return device.getDefaultEngine(); }
getInternalEngine()150 EngineControl &ClDevice::getInternalEngine() { return device.getInternalEngine(); }
getSelectorCopyEngine()151 SelectorCopyEngine &ClDevice::getSelectorCopyEngine() { return device.getSelectorCopyEngine(); }
getMemoryManager() const152 MemoryManager *ClDevice::getMemoryManager() const { return device.getMemoryManager(); }
getGmmHelper() const153 GmmHelper *ClDevice::getGmmHelper() const { return device.getGmmHelper(); }
getGmmClientContext() const154 GmmClientContext *ClDevice::getGmmClientContext() const { return device.getGmmClientContext(); }
getProfilingTimerResolution()155 double ClDevice::getProfilingTimerResolution() { return device.getProfilingTimerResolution(); }
getPlatformHostTimerResolution() const156 double ClDevice::getPlatformHostTimerResolution() const { return device.getPlatformHostTimerResolution(); }
isSimulation() const157 bool ClDevice::isSimulation() const { return device.isSimulation(); }
getRenderCoreFamily() const158 GFXCORE_FAMILY ClDevice::getRenderCoreFamily() const { return device.getRenderCoreFamily(); }
getPerformanceCounters()159 PerformanceCounters *ClDevice::getPerformanceCounters() { return device.getPerformanceCounters(); }
getPreemptionMode() const160 PreemptionMode ClDevice::getPreemptionMode() const { return device.getPreemptionMode(); }
isDebuggerActive() const161 bool ClDevice::isDebuggerActive() const { return device.isDebuggerActive(); }
getDebugger()162 Debugger *ClDevice::getDebugger() { return device.getDebugger(); }
getSourceLevelDebugger()163 SourceLevelDebugger *ClDevice::getSourceLevelDebugger() { return device.getSourceLevelDebugger(); }
getExecutionEnvironment() const164 ExecutionEnvironment *ClDevice::getExecutionEnvironment() const { return device.getExecutionEnvironment(); }
getRootDeviceEnvironment() const165 const RootDeviceEnvironment &ClDevice::getRootDeviceEnvironment() const { return device.getRootDeviceEnvironment(); }
isFullRangeSvm() const166 bool ClDevice::isFullRangeSvm() const { return device.isFullRangeSvm(); }
areSharedSystemAllocationsAllowed() const167 bool ClDevice::areSharedSystemAllocationsAllowed() const { return device.areSharedSystemAllocationsAllowed(); }
getRootDeviceIndex() const168 uint32_t ClDevice::getRootDeviceIndex() const { return device.getRootDeviceIndex(); }
getNumGenericSubDevices() const169 uint32_t ClDevice::getNumGenericSubDevices() const { return device.getNumGenericSubDevices(); }
getNumSubDevices() const170 uint32_t ClDevice::getNumSubDevices() const { return static_cast<uint32_t>(subDevices.size()); }
171
ClDeviceVector(const cl_device_id * devices,cl_uint numDevices)172 ClDeviceVector::ClDeviceVector(const cl_device_id *devices,
173 cl_uint numDevices) {
174 for (cl_uint i = 0; i < numDevices; i++) {
175 auto pClDevice = castToObject<ClDevice>(devices[i]);
176 this->push_back(pClDevice);
177 }
178 }
179
toDeviceIDs(std::vector<cl_device_id> & devIDs) const180 void ClDeviceVector::toDeviceIDs(std::vector<cl_device_id> &devIDs) const {
181 int i = 0;
182 devIDs.resize(this->size());
183
184 for (auto &it : *this) {
185 devIDs[i] = it;
186 i++;
187 }
188 }
peekCompilerExtensions() const189 const std::string &ClDevice::peekCompilerExtensions() const {
190 return compilerExtensions;
191 }
peekCompilerExtensionsWithFeatures() const192 const std::string &ClDevice::peekCompilerExtensionsWithFeatures() const {
193 return compilerExtensionsWithFeatures;
194 }
getDeviceBitfield() const195 DeviceBitfield ClDevice::getDeviceBitfield() const {
196 return device.getDeviceBitfield();
197 }
198
isDeviceEnqueueSupported() const199 bool ClDevice::isDeviceEnqueueSupported() const {
200 if (DebugManager.flags.ForceDeviceEnqueueSupport.get() != -1) {
201 return DebugManager.flags.ForceDeviceEnqueueSupport.get();
202 }
203 return device.getHardwareInfo().capabilityTable.supportsDeviceEnqueue;
204 }
205
arePipesSupported() const206 bool ClDevice::arePipesSupported() const {
207 if (DebugManager.flags.ForcePipeSupport.get() != -1) {
208 return DebugManager.flags.ForcePipeSupport.get();
209 }
210 return device.getHardwareInfo().capabilityTable.supportsPipes;
211 }
212
getQueueFamilyCapabilitiesAll()213 cl_command_queue_capabilities_intel ClDevice::getQueueFamilyCapabilitiesAll() {
214 return CL_QUEUE_CAPABILITY_CREATE_SINGLE_QUEUE_EVENTS_INTEL |
215 CL_QUEUE_CAPABILITY_CREATE_CROSS_QUEUE_EVENTS_INTEL |
216 CL_QUEUE_CAPABILITY_SINGLE_QUEUE_EVENT_WAIT_LIST_INTEL |
217 CL_QUEUE_CAPABILITY_CROSS_QUEUE_EVENT_WAIT_LIST_INTEL |
218 CL_QUEUE_CAPABILITY_TRANSFER_BUFFER_INTEL |
219 CL_QUEUE_CAPABILITY_TRANSFER_BUFFER_RECT_INTEL |
220 CL_QUEUE_CAPABILITY_MAP_BUFFER_INTEL |
221 CL_QUEUE_CAPABILITY_FILL_BUFFER_INTEL |
222 CL_QUEUE_CAPABILITY_TRANSFER_IMAGE_INTEL |
223 CL_QUEUE_CAPABILITY_MAP_IMAGE_INTEL |
224 CL_QUEUE_CAPABILITY_FILL_IMAGE_INTEL |
225 CL_QUEUE_CAPABILITY_TRANSFER_BUFFER_IMAGE_INTEL |
226 CL_QUEUE_CAPABILITY_TRANSFER_IMAGE_BUFFER_INTEL |
227 CL_QUEUE_CAPABILITY_MARKER_INTEL |
228 CL_QUEUE_CAPABILITY_BARRIER_INTEL |
229 CL_QUEUE_CAPABILITY_KERNEL_INTEL;
230 }
231
getQueueFamilyCapabilities(EngineGroupType type)232 cl_command_queue_capabilities_intel ClDevice::getQueueFamilyCapabilities(EngineGroupType type) {
233 auto &hwHelper = NEO::HwHelper::get(getHardwareInfo().platform.eRenderCoreFamily);
234 auto &clHwHelper = NEO::ClHwHelper::get(getHardwareInfo().platform.eRenderCoreFamily);
235
236 cl_command_queue_capabilities_intel disabledProperties = 0u;
237 if (hwHelper.isCopyOnlyEngineType(type)) {
238 disabledProperties |= static_cast<cl_command_queue_capabilities_intel>(CL_QUEUE_CAPABILITY_KERNEL_INTEL);
239 disabledProperties |= static_cast<cl_command_queue_capabilities_intel>(CL_QUEUE_CAPABILITY_FILL_BUFFER_INTEL); // clEnqueueFillBuffer
240 disabledProperties |= static_cast<cl_command_queue_capabilities_intel>(CL_QUEUE_CAPABILITY_TRANSFER_IMAGE_INTEL); // clEnqueueCopyImage
241 disabledProperties |= static_cast<cl_command_queue_capabilities_intel>(CL_QUEUE_CAPABILITY_FILL_IMAGE_INTEL); // clEnqueueFillImage
242 disabledProperties |= static_cast<cl_command_queue_capabilities_intel>(CL_QUEUE_CAPABILITY_TRANSFER_BUFFER_IMAGE_INTEL); // clEnqueueCopyBufferToImage
243 disabledProperties |= static_cast<cl_command_queue_capabilities_intel>(CL_QUEUE_CAPABILITY_TRANSFER_IMAGE_BUFFER_INTEL); // clEnqueueCopyImageToBuffer
244 }
245 disabledProperties |= clHwHelper.getAdditionalDisabledQueueFamilyCapabilities(type);
246
247 if (disabledProperties != 0) {
248 return getQueueFamilyCapabilitiesAll() & ~disabledProperties;
249 }
250 return CL_QUEUE_DEFAULT_CAPABILITIES_INTEL;
251 }
252
getQueueFamilyName(char * outputName,EngineGroupType type)253 void ClDevice::getQueueFamilyName(char *outputName, EngineGroupType type) {
254 std::string name{};
255
256 const auto &clHwHelper = ClHwHelper::get(getHardwareInfo().platform.eRenderCoreFamily);
257 const bool hasHwSpecificName = clHwHelper.getQueueFamilyName(name, type);
258
259 if (!hasHwSpecificName) {
260 switch (type) {
261 case EngineGroupType::RenderCompute:
262 name = "rcs";
263 break;
264 case EngineGroupType::Compute:
265 name = "ccs";
266 break;
267 case EngineGroupType::Copy:
268 name = "bcs";
269 break;
270 default:
271 name = "";
272 break;
273 }
274 }
275
276 UNRECOVERABLE_IF(name.size() >= CL_QUEUE_FAMILY_MAX_NAME_SIZE_INTEL);
277 strncpy_s(outputName, CL_QUEUE_FAMILY_MAX_NAME_SIZE_INTEL, name.c_str(), name.size());
278 }
getPlatform() const279 Platform *ClDevice::getPlatform() const {
280 return castToObject<Platform>(platformId);
281 }
isPciBusInfoValid() const282 bool ClDevice::isPciBusInfoValid() const {
283 return deviceInfo.pciBusInfo.pci_domain != PhysicalDevicePciBusInfo::InvalidValue && deviceInfo.pciBusInfo.pci_bus != PhysicalDevicePciBusInfo::InvalidValue &&
284 deviceInfo.pciBusInfo.pci_device != PhysicalDevicePciBusInfo::InvalidValue && deviceInfo.pciBusInfo.pci_function != PhysicalDevicePciBusInfo::InvalidValue;
285 }
286
287 } // namespace NEO
288