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