compute-runtime/runtime/context/context.cpp

319 lines
10 KiB
C++
Raw Normal View History

/*
* Copyright (C) 2017-2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/context/context.h"
#include "core/compiler_interface/compiler_interface.h"
#include "core/debug_settings/debug_settings_manager.h"
#include "core/helpers/get_info.h"
#include "core/helpers/ptr_math.h"
#include "core/helpers/string.h"
#include "core/memory_manager/deferred_deleter.h"
#include "core/memory_manager/unified_memory_manager.h"
#include "runtime/built_ins/built_ins.h"
#include "runtime/command_queue/command_queue.h"
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/device/device.h"
#include "runtime/device_queue/device_queue.h"
#include "runtime/gtpin/gtpin_notify.h"
#include "runtime/helpers/surface_formats.h"
#include "runtime/mem_obj/image.h"
#include "runtime/memory_manager/memory_manager.h"
#include "runtime/platform/platform.h"
#include "runtime/sharings/sharing.h"
#include "runtime/sharings/sharing_factory.h"
#include "d3d_sharing_functions.h"
#include <algorithm>
#include <memory>
namespace NEO {
Context::Context(
void(CL_CALLBACK *funcNotify)(const char *, const void *, size_t, void *),
void *data) {
properties = nullptr;
numProperties = 0;
contextCallback = funcNotify;
userData = data;
memoryManager = nullptr;
specialQueue = nullptr;
defaultDeviceQueue = nullptr;
driverDiagnostics = nullptr;
sharingFunctions.resize(SharingType::MAX_SHARING_VALUE);
}
Context::~Context() {
delete[] properties;
if (specialQueue) {
delete specialQueue;
}
if (svmAllocsManager) {
delete svmAllocsManager;
}
if (driverDiagnostics) {
delete driverDiagnostics;
}
if (memoryManager && memoryManager->isAsyncDeleterEnabled()) {
memoryManager->getDeferredDeleter()->removeClient();
}
gtpinNotifyContextDestroy((cl_context)this);
for (auto &device : devices) {
device->decRefInternal();
}
}
DeviceQueue *Context::getDefaultDeviceQueue() {
return defaultDeviceQueue;
}
void Context::setDefaultDeviceQueue(DeviceQueue *queue) {
defaultDeviceQueue = queue;
}
CommandQueue *Context::getSpecialQueue() {
return specialQueue;
}
void Context::setSpecialQueue(CommandQueue *commandQueue) {
specialQueue = commandQueue;
}
void Context::overrideSpecialQueueAndDecrementRefCount(CommandQueue *commandQueue) {
setSpecialQueue(commandQueue);
commandQueue->setIsSpecialCommandQueue(true);
//decrement ref count that special queue added
this->decRefInternal();
};
bool Context::areMultiStorageAllocationsPreferred() {
return this->contextType != ContextType::CONTEXT_TYPE_SPECIALIZED;
}
bool Context::createImpl(const cl_context_properties *properties,
const ClDeviceVector &inputDevices,
void(CL_CALLBACK *funcNotify)(const char *, const void *, size_t, void *),
void *data, cl_int &errcodeRet) {
auto propertiesCurrent = properties;
bool interopUserSync = false;
int32_t driverDiagnosticsUsed = -1;
auto sharingBuilder = sharingFactory.build();
std::unique_ptr<DriverDiagnostics> driverDiagnostics;
while (propertiesCurrent && *propertiesCurrent) {
errcodeRet = CL_SUCCESS;
auto propertyType = propertiesCurrent[0];
auto propertyValue = propertiesCurrent[1];
propertiesCurrent += 2;
switch (propertyType) {
case CL_CONTEXT_PLATFORM: {
cl_platform_id pid = platform();
if (reinterpret_cast<cl_platform_id>(propertyValue) != pid) {
errcodeRet = CL_INVALID_PLATFORM;
return false;
}
} break;
case CL_CONTEXT_SHOW_DIAGNOSTICS_INTEL:
driverDiagnosticsUsed = static_cast<int32_t>(propertyValue);
break;
case CL_CONTEXT_INTEROP_USER_SYNC:
interopUserSync = propertyValue > 0;
break;
default:
if (!sharingBuilder->processProperties(propertyType, propertyValue, errcodeRet)) {
errcodeRet = processExtraProperties(propertyType, propertyValue);
}
if (errcodeRet != CL_SUCCESS) {
return false;
}
break;
}
}
auto numProperties = ptrDiff(propertiesCurrent, properties) / sizeof(cl_context_properties);
cl_context_properties *propertiesNew = nullptr;
// copy the user properties if there are any
if (numProperties) {
propertiesNew = new cl_context_properties[numProperties + 1];
memcpy_s(propertiesNew, (numProperties + 1) * sizeof(cl_context_properties), properties, numProperties * sizeof(cl_context_properties));
propertiesNew[numProperties] = 0;
numProperties++;
}
if (DebugManager.flags.PrintDriverDiagnostics.get() != -1) {
driverDiagnosticsUsed = DebugManager.flags.PrintDriverDiagnostics.get();
}
if (driverDiagnosticsUsed >= 0) {
driverDiagnostics.reset(new DriverDiagnostics((cl_diagnostics_verbose_level)driverDiagnosticsUsed));
}
this->numProperties = numProperties;
this->properties = propertiesNew;
this->setInteropUserSyncEnabled(interopUserSync);
if (!sharingBuilder->finalizeProperties(*this, errcodeRet)) {
return false;
}
this->driverDiagnostics = driverDiagnostics.release();
this->devices = inputDevices;
// We currently assume each device uses the same MemoryManager
if (devices.size() > 0) {
auto device = this->getDevice(0);
this->memoryManager = device->getMemoryManager();
if (device->getHardwareInfo().capabilityTable.ftrSvm) {
this->svmAllocsManager = new SVMAllocsManager(this->memoryManager);
}
if (memoryManager->isAsyncDeleterEnabled()) {
memoryManager->getDeferredDeleter()->addClient();
}
}
for (auto &device : devices) {
device->incRefInternal();
}
auto commandQueue = CommandQueue::create(this, devices[0], nullptr, errcodeRet);
DEBUG_BREAK_IF(commandQueue == nullptr);
overrideSpecialQueueAndDecrementRefCount(commandQueue);
return true;
}
cl_int Context::getInfo(cl_context_info paramName, size_t paramValueSize,
void *paramValue, size_t *paramValueSizeRet) {
cl_int retVal;
size_t valueSize = 0;
const void *pValue = nullptr;
cl_uint numDevices;
cl_uint refCount = 0;
std::vector<cl_device_id> devIDs;
auto callGetinfo = true;
switch (paramName) {
case CL_CONTEXT_DEVICES:
valueSize = devices.size() * sizeof(cl_device_id);
devices.toDeviceIDs(devIDs);
pValue = devIDs.data();
break;
case CL_CONTEXT_NUM_DEVICES:
numDevices = (cl_uint)(devices.size());
valueSize = sizeof(numDevices);
pValue = &numDevices;
break;
case CL_CONTEXT_PROPERTIES:
valueSize = this->numProperties * sizeof(cl_context_properties);
pValue = this->properties;
if (valueSize == 0) {
callGetinfo = false;
}
break;
case CL_CONTEXT_REFERENCE_COUNT:
refCount = static_cast<cl_uint>(this->getReference());
valueSize = sizeof(refCount);
pValue = &refCount;
break;
default:
pValue = getOsContextInfo(paramName, &valueSize);
break;
}
if (callGetinfo) {
retVal = ::getInfo(paramValue, paramValueSize, pValue, valueSize);
} else {
retVal = CL_SUCCESS;
}
if (paramValueSizeRet) {
*paramValueSizeRet = valueSize;
}
return retVal;
}
size_t Context::getNumDevices() const {
return devices.size();
}
size_t Context::getTotalNumDevices() const {
size_t numAvailableDevices = 0u;
for (auto &device : devices) {
numAvailableDevices += device->getNumAvailableDevices();
}
return numAvailableDevices;
}
ClDevice *Context::getDevice(size_t deviceOrdinal) const {
return (ClDevice *)devices[deviceOrdinal];
}
cl_int Context::getSupportedImageFormats(
Device *device,
cl_mem_flags flags,
cl_mem_object_type imageType,
cl_uint numEntries,
cl_image_format *imageFormats,
cl_uint *numImageFormatsReturned) {
size_t numImageFormats = 0;
const bool nv12ExtensionEnabled = device->getDeviceInfo().nv12Extension;
const bool packedYuvExtensionEnabled = device->getDeviceInfo().packedYuvExtension;
auto appendImageFormats = [&](ArrayRef<const ClSurfaceFormatInfo> formats) {
if (imageFormats) {
size_t offset = numImageFormats;
for (size_t i = 0; i < formats.size() && offset < numEntries; ++i) {
imageFormats[offset++] = formats[i].OCLImageFormat;
}
}
numImageFormats += formats.size();
};
if (flags & CL_MEM_READ_ONLY) {
appendImageFormats(SurfaceFormats::readOnly());
if (Image::isImage2d(imageType) && nv12ExtensionEnabled) {
appendImageFormats(SurfaceFormats::planarYuv());
}
if (Image::isImage2dOr2dArray(imageType)) {
appendImageFormats(SurfaceFormats::readOnlyDepth());
}
if (Image::isImage2d(imageType) && packedYuvExtensionEnabled) {
appendImageFormats(SurfaceFormats::packedYuv());
}
} else if (flags & CL_MEM_WRITE_ONLY) {
appendImageFormats(SurfaceFormats::writeOnly());
if (Image::isImage2dOr2dArray(imageType)) {
appendImageFormats(SurfaceFormats::readWriteDepth());
}
} else if (nv12ExtensionEnabled && (flags & CL_MEM_NO_ACCESS_INTEL)) {
appendImageFormats(SurfaceFormats::readOnly());
if (Image::isImage2d(imageType)) {
appendImageFormats(SurfaceFormats::planarYuv());
}
} else {
appendImageFormats(SurfaceFormats::readWrite());
if (Image::isImage2dOr2dArray(imageType)) {
appendImageFormats(SurfaceFormats::readWriteDepth());
}
}
if (numImageFormatsReturned) {
*numImageFormatsReturned = static_cast<cl_uint>(numImageFormats);
}
return CL_SUCCESS;
}
} // namespace NEO