22 #include <QTextStream> 26 QLatin1String QgsOpenClUtils::SETTINGS_GLOBAL_ENABLED_KEY = QLatin1Literal(
"OpenClEnabled" );
27 QLatin1String QgsOpenClUtils::SETTINGS_DEFAULT_DEVICE_KEY = QLatin1Literal(
"OpenClDefaultDevice" );
29 bool QgsOpenClUtils::sAvailable =
false;
30 QString QgsOpenClUtils::sSourcePath = QString();
35 std::vector<cl::Platform> platforms;
36 cl::Platform::get( &platforms );
37 std::vector<cl::Device> existingDevices;
38 for (
auto &p : platforms )
40 std::string platver = p.getInfo<CL_PLATFORM_VERSION>();
41 QgsDebugMsg( QStringLiteral(
"Found OpenCL platform %1: %2" ).arg( QString::fromStdString( platver ), QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ) );
42 if ( platver.find(
"OpenCL " ) != std::string::npos )
44 std::vector<cl::Device> _devices;
48 p.getDevices( CL_DEVICE_TYPE_ALL, &_devices );
50 catch ( cl::Error &e )
52 QgsDebugMsgLevel( QStringLiteral(
"Error %1 on platform %3 searching for OpenCL device: %2" )
54 QString::fromStdString( e.what() ),
55 QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ), 2 );
57 if ( _devices.size() > 0 )
59 for (
unsigned long i = 0; i < _devices.size(); i++ )
61 existingDevices.push_back( _devices[i] );
66 return existingDevices;
69 void QgsOpenClUtils::init()
71 static std::once_flag initialized;
72 std::call_once( initialized, [ = ]( )
78 catch ( cl::Error &e )
81 .arg(
errorText( e.err() ), QString::fromStdString( e.what() ) ),
110 return QString::fromStdString( device.getInfo<CL_DEVICE_VENDOR>() );
112 return QString::fromStdString( device.getInfo<CL_DEVICE_PROFILE>() );
114 return QString::fromStdString( device.getInfo<CL_DEVICE_VERSION>() );
115 case Info::ImageSupport:
116 return device.getInfo<CL_DEVICE_IMAGE_SUPPORT>() ? QStringLiteral(
"True" ) : QStringLiteral(
"False" );
117 case Info::Image2dMaxHeight:
118 return QString::number( device.getInfo<CL_DEVICE_IMAGE2D_MAX_HEIGHT>() );
119 case Info::MaxMemAllocSize:
120 return QString::number( device.getInfo<CL_DEVICE_MAX_MEM_ALLOC_SIZE>() );
121 case Info::Image2dMaxWidth:
122 return QString::number( device.getInfo<CL_DEVICE_IMAGE2D_MAX_WIDTH>() );
125 unsigned long type( device.getInfo<CL_DEVICE_TYPE>() );
129 case CL_DEVICE_TYPE_CPU:
130 mappedType = QgsOpenClUtils::HardwareType::CPU;
132 case CL_DEVICE_TYPE_GPU:
133 mappedType = QgsOpenClUtils::HardwareType::GPU;
136 mappedType = QgsOpenClUtils::HardwareType::Other;
138 QMetaEnum metaEnum = QMetaEnum::fromType<QgsOpenClUtils::HardwareType>();
139 return metaEnum.valueToKey( mappedType );
142 return QString::fromStdString( device.getInfo<CL_DEVICE_NAME>() );
145 catch ( cl::Error &e )
148 QgsDebugMsgLevel( QStringLiteral(
"Error %1 getting info for OpenCL device: %2" )
149 .arg(
errorText( e.err() ), QString::fromStdString( e.what() ) ),
159 return QgsSettings().
value( SETTINGS_GLOBAL_ENABLED_KEY,
false, QgsSettings::Section::Core ).toBool();
164 return cl::Device::getDefault();
170 if ( cl::Platform::getDefault()() )
172 std::string platver = cl::Platform::getDefault().getInfo<CL_PLATFORM_VERSION>();
173 if ( platver.find(
"OpenCL " ) != std::string::npos )
175 version = QString::fromStdString( platver.substr( 7 ) ).split(
' ' ).first();
183 QgsSettings().
setValue( SETTINGS_DEFAULT_DEVICE_KEY, deviceId, QgsSettings::Section::Core );
188 return QgsSettings().
value( SETTINGS_DEFAULT_DEVICE_KEY, QString( ), QgsSettings::Section::Core ).toString();
193 return QStringLiteral(
"%1|%2|%3|%4" )
194 .arg(
deviceInfo( QgsOpenClUtils::Info::Name, device ) )
195 .arg(
deviceInfo( QgsOpenClUtils::Info::Vendor, device ) )
196 .arg(
deviceInfo( QgsOpenClUtils::Info::Version, device ) )
197 .arg(
deviceInfo( QgsOpenClUtils::Info::Type, device ) );
200 bool QgsOpenClUtils::activate(
const QString &preferredDeviceId )
209 std::vector<cl::Platform> platforms;
210 cl::Platform::get( &platforms );
213 bool deviceFound =
false;
214 for (
auto &p : platforms )
218 std::string platver = p.getInfo<CL_PLATFORM_VERSION>();
219 QgsDebugMsg( QStringLiteral(
"Found OpenCL platform %1: %2" ).arg( QString::fromStdString( platver ), QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ) );
220 if ( platver.find(
"OpenCL " ) != std::string::npos )
222 std::vector<cl::Device>
devices;
226 p.getDevices( CL_DEVICE_TYPE_ALL, &devices );
228 if ( ! preferredDeviceId.isEmpty() )
230 for (
const auto &_dev : devices )
232 if ( preferredDeviceId ==
deviceId( _dev ) )
245 for (
const auto &_dev : devices )
247 if ( _dev.getInfo<CL_DEVICE_TYPE>() == CL_DEVICE_TYPE_GPU )
260 for (
const auto &_dev : devices )
262 if ( _dev.getInfo<CL_DEVICE_TYPE>() == CL_DEVICE_TYPE_CPU )
277 catch ( cl::Error &e )
279 QgsDebugMsg( QStringLiteral(
"Error %1 on platform %3 searching for OpenCL device: %2" )
281 QString::fromStdString( e.what() ),
282 QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ) );
294 cl::Platform newP = cl::Platform::setDefault( plat );
303 cl::Device::setDefault( dev );
305 .arg( QString::fromStdString( dev.getInfo<CL_DEVICE_NAME>() ) ),
312 catch ( cl::Error &e )
315 .arg(
errorText( e.err() ), QString::fromStdString( e.what() ) ),
324 return QStringLiteral(
325 "Type: <b>%9</b><br>" 326 "Name: <b>%1</b><br>" 327 "Vendor: <b>%2</b><br>" 328 "Profile: <b>%3</b><br>" 329 "Version: <b>%4</b><br>" 330 "Image support: <b>%5</b><br>" 331 "Max image2d width: <b>%6</b><br>" 332 "Max image2d height: <b>%7</b><br>" 333 "Max mem alloc size: <b>%8</b><br>" 347 for (
const auto &dev :
devices( ) )
363 QgsSettings().
setValue( SETTINGS_GLOBAL_ENABLED_KEY, enabled, QgsSettings::Section::Core );
374 if ( file.open( QFile::ReadOnly | QFile::Text ) )
376 QTextStream in( &file );
377 source_str = in.readAll();
389 QString path = QStringLiteral(
"%1/%2.cl" ).arg(
sourcePath(), baseName );
395 cl::BuildLogType build_logs = error.getBuildLog();
397 if ( build_logs.size() > 0 )
398 build_log = QString::fromStdString( build_logs[0].second );
406 case 0:
return QStringLiteral(
"CL_SUCCESS" );
407 case -1:
return QStringLiteral(
"CL_DEVICE_NOT_FOUND" );
408 case -2:
return QStringLiteral(
"CL_DEVICE_NOT_AVAILABLE" );
409 case -3:
return QStringLiteral(
"CL_COMPILER_NOT_AVAILABLE" );
410 case -4:
return QStringLiteral(
"CL_MEM_OBJECT_ALLOCATION_FAILURE" );
411 case -5:
return QStringLiteral(
"CL_OUT_OF_RESOURCES" );
412 case -6:
return QStringLiteral(
"CL_OUT_OF_HOST_MEMORY" );
413 case -7:
return QStringLiteral(
"CL_PROFILING_INFO_NOT_AVAILABLE" );
414 case -8:
return QStringLiteral(
"CL_MEM_COPY_OVERLAP" );
415 case -9:
return QStringLiteral(
"CL_IMAGE_FORMAT_MISMATCH" );
416 case -10:
return QStringLiteral(
"CL_IMAGE_FORMAT_NOT_SUPPORTED" );
417 case -12:
return QStringLiteral(
"CL_MAP_FAILURE" );
418 case -13:
return QStringLiteral(
"CL_MISALIGNED_SUB_BUFFER_OFFSET" );
419 case -14:
return QStringLiteral(
"CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST" );
420 case -15:
return QStringLiteral(
"CL_COMPILE_PROGRAM_FAILURE" );
421 case -16:
return QStringLiteral(
"CL_LINKER_NOT_AVAILABLE" );
422 case -17:
return QStringLiteral(
"CL_LINK_PROGRAM_FAILURE" );
423 case -18:
return QStringLiteral(
"CL_DEVICE_PARTITION_FAILED" );
424 case -19:
return QStringLiteral(
"CL_KERNEL_ARG_INFO_NOT_AVAILABLE" );
425 case -30:
return QStringLiteral(
"CL_INVALID_VALUE" );
426 case -31:
return QStringLiteral(
"CL_INVALID_DEVICE_TYPE" );
427 case -32:
return QStringLiteral(
"CL_INVALID_PLATFORM" );
428 case -33:
return QStringLiteral(
"CL_INVALID_DEVICE" );
429 case -34:
return QStringLiteral(
"CL_INVALID_CONTEXT" );
430 case -35:
return QStringLiteral(
"CL_INVALID_QUEUE_PROPERTIES" );
431 case -36:
return QStringLiteral(
"CL_INVALID_COMMAND_QUEUE" );
432 case -37:
return QStringLiteral(
"CL_INVALID_HOST_PTR" );
433 case -38:
return QStringLiteral(
"CL_INVALID_MEM_OBJECT" );
434 case -39:
return QStringLiteral(
"CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" );
435 case -40:
return QStringLiteral(
"CL_INVALID_IMAGE_SIZE" );
436 case -41:
return QStringLiteral(
"CL_INVALID_SAMPLER" );
437 case -42:
return QStringLiteral(
"CL_INVALID_BINARY" );
438 case -43:
return QStringLiteral(
"CL_INVALID_BUILD_OPTIONS" );
439 case -44:
return QStringLiteral(
"CL_INVALID_PROGRAM" );
440 case -45:
return QStringLiteral(
"CL_INVALID_PROGRAM_EXECUTABLE" );
441 case -46:
return QStringLiteral(
"CL_INVALID_KERNEL_NAME" );
442 case -47:
return QStringLiteral(
"CL_INVALID_KERNEL_DEFINITION" );
443 case -48:
return QStringLiteral(
"CL_INVALID_KERNEL" );
444 case -49:
return QStringLiteral(
"CL_INVALID_ARG_INDEX" );
445 case -50:
return QStringLiteral(
"CL_INVALID_ARG_VALUE" );
446 case -51:
return QStringLiteral(
"CL_INVALID_ARG_SIZE" );
447 case -52:
return QStringLiteral(
"CL_INVALID_KERNEL_ARGS" );
448 case -53:
return QStringLiteral(
"CL_INVALID_WORK_DIMENSION" );
449 case -54:
return QStringLiteral(
"CL_INVALID_WORK_GROUP_SIZE" );
450 case -55:
return QStringLiteral(
"CL_INVALID_WORK_ITEM_SIZE" );
451 case -56:
return QStringLiteral(
"CL_INVALID_GLOBAL_OFFSET" );
452 case -57:
return QStringLiteral(
"CL_INVALID_EVENT_WAIT_LIST" );
453 case -58:
return QStringLiteral(
"CL_INVALID_EVENT" );
454 case -59:
return QStringLiteral(
"CL_INVALID_OPERATION" );
455 case -60:
return QStringLiteral(
"CL_INVALID_GL_OBJECT" );
456 case -61:
return QStringLiteral(
"CL_INVALID_BUFFER_SIZE" );
457 case -62:
return QStringLiteral(
"CL_INVALID_MIP_LEVEL" );
458 case -63:
return QStringLiteral(
"CL_INVALID_GLOBAL_WORK_SIZE" );
459 case -64:
return QStringLiteral(
"CL_INVALID_PROPERTY" );
460 case -65:
return QStringLiteral(
"CL_INVALID_IMAGE_DESCRIPTOR" );
461 case -66:
return QStringLiteral(
"CL_INVALID_COMPILER_OPTIONS" );
462 case -67:
return QStringLiteral(
"CL_INVALID_LINKER_OPTIONS" );
463 case -68:
return QStringLiteral(
"CL_INVALID_DEVICE_PARTITION_COUNT" );
464 case -69:
return QStringLiteral(
"CL_INVALID_PIPE_SIZE" );
465 case -70:
return QStringLiteral(
"CL_INVALID_DEVICE_QUEUE" );
466 case -71:
return QStringLiteral(
"CL_INVALID_SPEC_ID" );
467 case -72:
return QStringLiteral(
"CL_MAX_SIZE_RESTRICTION_EXCEEDED" );
468 case -1002:
return QStringLiteral(
"CL_INVALID_D3D10_DEVICE_KHR" );
469 case -1003:
return QStringLiteral(
"CL_INVALID_D3D10_RESOURCE_KHR" );
470 case -1004:
return QStringLiteral(
"CL_D3D10_RESOURCE_ALREADY_ACQUIRED_KHR" );
471 case -1005:
return QStringLiteral(
"CL_D3D10_RESOURCE_NOT_ACQUIRED_KHR" );
472 case -1006:
return QStringLiteral(
"CL_INVALID_D3D11_DEVICE_KHR" );
473 case -1007:
return QStringLiteral(
"CL_INVALID_D3D11_RESOURCE_KHR" );
474 case -1008:
return QStringLiteral(
"CL_D3D11_RESOURCE_ALREADY_ACQUIRED_KHR" );
475 case -1009:
return QStringLiteral(
"CL_D3D11_RESOURCE_NOT_ACQUIRED_KHR" );
476 case -1010:
return QStringLiteral(
"CL_INVALID_DX9_MEDIA_ADAPTER_KHR" );
477 case -1011:
return QStringLiteral(
"CL_INVALID_DX9_MEDIA_SURFACE_KHR" );
478 case -1012:
return QStringLiteral(
"CL_DX9_MEDIA_SURFACE_ALREADY_ACQUIRED_KHR" );
479 case -1013:
return QStringLiteral(
"CL_DX9_MEDIA_SURFACE_NOT_ACQUIRED_KHR" );
480 case -1093:
return QStringLiteral(
"CL_INVALID_EGL_OBJECT_KHR" );
481 case -1092:
return QStringLiteral(
"CL_EGL_RESOURCE_NOT_ACQUIRED_KHR" );
482 case -1001:
return QStringLiteral(
"CL_PLATFORM_NOT_FOUND_KHR" );
483 case -1057:
return QStringLiteral(
"CL_DEVICE_PARTITION_FAILED_EXT" );
484 case -1058:
return QStringLiteral(
"CL_INVALID_PARTITION_COUNT_EXT" );
485 case -1059:
return QStringLiteral(
"CL_INVALID_PARTITION_NAME_EXT" );
486 case -1094:
return QStringLiteral(
"CL_INVALID_ACCELERATOR_INTEL" );
487 case -1095:
return QStringLiteral(
"CL_INVALID_ACCELERATOR_TYPE_INTEL" );
488 case -1096:
return QStringLiteral(
"CL_INVALID_ACCELERATOR_DESCRIPTOR_INTEL" );
489 case -1097:
return QStringLiteral(
"CL_ACCELERATOR_TYPE_NOT_SUPPORTED_INTEL" );
490 case -1000:
return QStringLiteral(
"CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR" );
491 case -1098:
return QStringLiteral(
"CL_INVALID_VA_API_MEDIA_ADAPTER_INTEL" );
492 case -1099:
return QStringLiteral(
"CL_INVALID_VA_API_MEDIA_SURFACE_INTEL" );
493 case -1100:
return QStringLiteral(
"CL_VA_API_MEDIA_SURFACE_ALREADY_ACQUIRED_INTEL" );
494 case -1101:
return QStringLiteral(
"CL_VA_API_MEDIA_SURFACE_NOT_ACQUIRED_INTEL" );
495 default:
return QStringLiteral(
"CL_UNKNOWN_ERROR" );
507 return cl::CommandQueue( context );
512 cl_command_queue_properties properties = 0;
514 cl_command_queue queue = clCreateCommandQueue(
context(), device(), properties,
nullptr );
516 return cl::CommandQueue( queue,
true );
523 static std::once_flag contextCreated;
524 std::call_once( contextCreated, [ = ]()
526 if (
available() && cl::Platform::getDefault()() && cl::Device::getDefault()() )
528 context = cl::Context( cl::Device::getDefault() );
550 if ( ok && version < 2.0f )
552 program.build( QStringLiteral(
"-cl-std=CL%1 -I%2" )
558 program.build( QStringLiteral(
"-I%1" )
562 catch ( cl::BuildError &e )
565 if ( build_log.isEmpty() )
566 build_log = QObject::tr(
"Build logs not available!" );
567 QString err = QObject::tr(
"Error building OpenCL program: %1" )
570 if ( exceptionBehavior ==
Throw )
573 catch ( cl::Error &e )
575 QString err = QObject::tr(
"Error %1 building OpenCL program in %2" )
576 .arg(
errorText( e.err() ), QString::fromStdString( e.what() ) );
static QString sourcePath()
Returns the base path to OpenCL program directory.
static QString deviceId(const cl::Device device)
Create a string identifier from a device.
static void setEnabled(bool enabled)
Set the OpenCL user setting to enabled.
static QString sourceFromBaseName(const QString &baseName)
Returns the full path to a an OpenCL source file from the baseName ('.cl' extension is automatically ...
This class is a composition of two QSettings instances:
#define Q_NOWARN_DEPRECATED_PUSH
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static void storePreferredDevice(const QString deviceId)
Store in the settings the preferred deviceId device identifier.
static bool available()
Checks whether a suitable OpenCL platform and device is available on this system and initialize the Q...
static const std::vector< cl::Device > devices()
Returns a list of OpenCL devices found on this sysytem.
static cl::Context context()
Context factory.
static QString deviceDescription(const cl::Device device)
Returns a formatted description for the device.
Info
The Info enum maps to OpenCL info constants.
ExceptionBehavior
The ExceptionBehavior enum define how exceptions generated by OpenCL should be treated.
static QString activePlatformVersion()
Returns the active platform OpenCL version string (e.g.
#define QgsDebugMsgLevel(str, level)
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static bool enabled()
Returns true if OpenCL is enabled in the user settings.
static QString sourceFromPath(const QString &path)
Read an OpenCL source file from path.
static void setSourcePath(const QString &value)
Set the base path to OpenCL program directory.
static cl::Device activeDevice()
Returns the active device.
Write errors in the message log and silently fail.
static QString errorText(const int errorCode)
Returns a string representation from an OpenCL errorCode.
static QString buildLog(cl::BuildError &error)
Extract and return the build log error from error.
static Q_DECL_DEPRECATED cl::Program buildProgram(const cl::Context &context, const QString &source, ExceptionBehavior exceptionBehavior=Catch)
Build the program from source in the given context and depending on exceptionBehavior can throw or ca...
#define Q_NOWARN_DEPRECATED_POP
static QLatin1String LOGMESSAGE_TAG
OpenCL string for message logs.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QString deviceInfo(const Info infoType, cl::Device device)
Returns infoType information about the device.
static QString preferredDevice()
Read from the settings the preferred device identifier.
static cl::CommandQueue commandQueue()
Create an OpenCL command queue from the default context.
static QString activeDeviceInfo(const Info infoType=Info::Name)
Returns infoType information about the active (default) device.