QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsopenclutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsopenclutils.cpp - QgsOpenClUtils
3 
4  ---------------------
5  begin : 11.4.2018
6  copyright : (C) 2018 by elpaso
7  email : elpaso at itopen dot it
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 #include "qgsopenclutils.h"
17 #include "qgssettings.h"
18 #include "qgsmessagelog.h"
19 #include "qgslogger.h"
20 
21 
22 #include <QTextStream>
23 #include <QFile>
24 #include <QDebug>
25 
26 QLatin1String QgsOpenClUtils::SETTINGS_GLOBAL_ENABLED_KEY = QLatin1Literal( "OpenClEnabled" );
27 QLatin1String QgsOpenClUtils::SETTINGS_DEFAULT_DEVICE_KEY = QLatin1Literal( "OpenClDefaultDevice" );
28 QLatin1String QgsOpenClUtils::LOGMESSAGE_TAG = QLatin1Literal( "OpenCL" );
29 bool QgsOpenClUtils::sAvailable = false;
30 QString QgsOpenClUtils::sSourcePath = QString();
31 
32 
33 const std::vector<cl::Device> QgsOpenClUtils::devices()
34 {
35  std::vector<cl::Platform> platforms;
36  cl::Platform::get( &platforms );
37  std::vector<cl::Device> existingDevices;
38  for ( auto &p : platforms )
39  {
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 )
43  {
44  std::vector<cl::Device> _devices;
45  // Check for a device
46  try
47  {
48  p.getDevices( CL_DEVICE_TYPE_ALL, &_devices );
49  }
50  catch ( cl::Error &e )
51  {
52  QgsDebugMsgLevel( QStringLiteral( "Error %1 on platform %3 searching for OpenCL device: %2" )
53  .arg( errorText( e.err() ),
54  QString::fromStdString( e.what() ),
55  QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ), 2 );
56  }
57  if ( _devices.size() > 0 )
58  {
59  for ( unsigned long i = 0; i < _devices.size(); i++ )
60  {
61  existingDevices.push_back( _devices[i] );
62  }
63  }
64  }
65  }
66  return existingDevices;
67 }
68 
69 void QgsOpenClUtils::init()
70 {
71  static std::once_flag initialized;
72  std::call_once( initialized, [ = ]( )
73  {
74  try
75  {
76  activate( preferredDevice() );
77  }
78  catch ( cl::Error &e )
79  {
80  QgsMessageLog::logMessage( QObject::tr( "Error %1 initializing OpenCL device: %2" )
81  .arg( errorText( e.err() ), QString::fromStdString( e.what() ) ),
83  }
84 
85  } );
86 }
87 
89 {
90  return sSourcePath;
91 }
92 
93 void QgsOpenClUtils::setSourcePath( const QString &value )
94 {
95  sSourcePath = value;
96 }
97 
99 {
100  return deviceInfo( infoType, activeDevice( ) );
101 }
102 
103 QString QgsOpenClUtils::deviceInfo( const Info infoType, cl::Device device )
104 {
105  try
106  {
107  switch ( infoType )
108  {
109  case Info::Vendor:
110  return QString::fromStdString( device.getInfo<CL_DEVICE_VENDOR>() );
111  case Info::Profile:
112  return QString::fromStdString( device.getInfo<CL_DEVICE_PROFILE>() );
113  case Info::Version:
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>() );
123  case Info::Type:
124  {
125  unsigned long type( device.getInfo<CL_DEVICE_TYPE>() );
126  int mappedType;
127  switch ( type )
128  {
129  case CL_DEVICE_TYPE_CPU:
130  mappedType = QgsOpenClUtils::HardwareType::CPU;
131  break;
132  case CL_DEVICE_TYPE_GPU:
133  mappedType = QgsOpenClUtils::HardwareType::GPU;
134  break;
135  default:
136  mappedType = QgsOpenClUtils::HardwareType::Other;
137  }
138  QMetaEnum metaEnum = QMetaEnum::fromType<QgsOpenClUtils::HardwareType>();
139  return metaEnum.valueToKey( mappedType );
140  }
141  case Info::Name:
142  return QString::fromStdString( device.getInfo<CL_DEVICE_NAME>() );
143  }
144  }
145  catch ( cl::Error &e )
146  {
147  // This can be a legitimate error when initializing, let's log it quietly
148  QgsDebugMsgLevel( QStringLiteral( "Error %1 getting info for OpenCL device: %2" )
149  .arg( errorText( e.err() ), QString::fromStdString( e.what() ) ),
150  4 );
151  return QString();
152  }
153  return QString();
154 }
155 
156 
158 {
159  return QgsSettings().value( SETTINGS_GLOBAL_ENABLED_KEY, false, QgsSettings::Section::Core ).toBool();
160 }
161 
163 {
164  return cl::Device::getDefault();
165 }
166 
168 {
169  QString version;
170  if ( cl::Platform::getDefault()() )
171  {
172  std::string platver = cl::Platform::getDefault().getInfo<CL_PLATFORM_VERSION>();
173  if ( platver.find( "OpenCL " ) != std::string::npos )
174  {
175  version = QString::fromStdString( platver.substr( 7 ) ).split( ' ' ).first();
176  }
177  }
178  return version;
179 }
180 
182 {
183  QgsSettings().setValue( SETTINGS_DEFAULT_DEVICE_KEY, deviceId, QgsSettings::Section::Core );
184 }
185 
187 {
188  return QgsSettings().value( SETTINGS_DEFAULT_DEVICE_KEY, QString( ), QgsSettings::Section::Core ).toString();
189 }
190 
191 QString QgsOpenClUtils::deviceId( const cl::Device device )
192 {
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 ) );
198 }
199 
200 bool QgsOpenClUtils::activate( const QString &preferredDeviceId )
201 {
202  if ( deviceId( activeDevice() ) == preferredDeviceId )
203  {
204  sAvailable = true;
205  return false;
206  }
207  try
208  {
209  std::vector<cl::Platform> platforms;
210  cl::Platform::get( &platforms );
211  cl::Platform plat;
212  cl::Device dev;
213  bool deviceFound = false;
214  for ( auto &p : platforms )
215  {
216  if ( deviceFound )
217  break;
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 )
221  {
222  std::vector<cl::Device> devices;
223  // Search for a device
224  try
225  {
226  p.getDevices( CL_DEVICE_TYPE_ALL, &devices );
227  // First search for the preferred device
228  if ( ! preferredDeviceId.isEmpty() )
229  {
230  for ( const auto &_dev : devices )
231  {
232  if ( preferredDeviceId == deviceId( _dev ) )
233  {
234  // Got one!
235  plat = p;
236  dev = _dev;
237  deviceFound = true;
238  break;
239  }
240  }
241  }
242  // Not found or preferred device id not set: get the first GPU
243  if ( ! deviceFound )
244  {
245  for ( const auto &_dev : devices )
246  {
247  if ( _dev.getInfo<CL_DEVICE_TYPE>() == CL_DEVICE_TYPE_GPU )
248  {
249  // Got one!
250  plat = p;
251  dev = _dev;
252  deviceFound = true;
253  break;
254  }
255  }
256  }
257  // Still nothing? Get the first device
258  if ( ! deviceFound )
259  {
260  for ( const auto &_dev : devices )
261  {
262  if ( _dev.getInfo<CL_DEVICE_TYPE>() == CL_DEVICE_TYPE_CPU )
263  {
264  // Got one!
265  plat = p;
266  dev = _dev;
267  deviceFound = true;
268  break;
269  }
270  }
271  }
272  if ( ! deviceFound )
273  {
274  QgsMessageLog::logMessage( QObject::tr( "No OpenCL device could be found." ), LOGMESSAGE_TAG, Qgis::Warning );
275  }
276  }
277  catch ( cl::Error &e )
278  {
279  QgsDebugMsg( QStringLiteral( "Error %1 on platform %3 searching for OpenCL device: %2" )
280  .arg( errorText( e.err() ),
281  QString::fromStdString( e.what() ),
282  QString::fromStdString( p.getInfo<CL_PLATFORM_NAME>() ) ) );
283  }
284 
285  }
286  }
287  if ( ! plat() )
288  {
289  QgsMessageLog::logMessage( QObject::tr( "No OpenCL platform found." ), LOGMESSAGE_TAG, Qgis::Warning );
290  sAvailable = false;
291  }
292  else
293  {
294  cl::Platform newP = cl::Platform::setDefault( plat );
295  if ( newP != plat )
296  {
297  QgsMessageLog::logMessage( QObject::tr( "Error setting default platform." ),
299  sAvailable = false;
300  }
301  else
302  {
303  cl::Device::setDefault( dev );
304  QgsMessageLog::logMessage( QObject::tr( "Active OpenCL device: %1" )
305  .arg( QString::fromStdString( dev.getInfo<CL_DEVICE_NAME>() ) ),
307  sAvailable = true;
308  }
309  }
310  }
311 
312  catch ( cl::Error &e )
313  {
314  QgsMessageLog::logMessage( QObject::tr( "Error %1 searching for OpenCL device: %2" )
315  .arg( errorText( e.err() ), QString::fromStdString( e.what() ) ),
317  sAvailable = false;
318  }
319  return sAvailable;
320 }
321 
322 QString QgsOpenClUtils::deviceDescription( const cl::Device device )
323 {
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>"
334  ).arg( QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Name, device ),
335  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Vendor, device ),
336  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Profile, device ),
337  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Version, device ),
338  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::ImageSupport, device ),
339  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Image2dMaxWidth, device ),
340  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Image2dMaxHeight, device ),
341  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::MaxMemAllocSize, device ),
342  QgsOpenClUtils::deviceInfo( QgsOpenClUtils::Info::Type, device ) );
343 }
344 
346 {
347  for ( const auto &dev : devices( ) )
348  {
349  if ( QgsOpenClUtils::deviceId( dev ) == deviceId )
350  return deviceDescription( dev );
351  }
352  return QString();
353 }
354 
356 {
357  init();
358  return sAvailable;
359 }
360 
362 {
363  QgsSettings().setValue( SETTINGS_GLOBAL_ENABLED_KEY, enabled, QgsSettings::Section::Core );
364 }
365 
366 
367 
368 QString QgsOpenClUtils::sourceFromPath( const QString &path )
369 {
370  // TODO: check for compatibility with current platform ( cl_khr_fp64 )
371  // Try to load the program sources
372  QString source_str;
373  QFile file( path );
374  if ( file.open( QFile::ReadOnly | QFile::Text ) )
375  {
376  QTextStream in( &file );
377  source_str = in.readAll();
378  file.close();
379  }
380  else
381  {
382  QgsMessageLog::logMessage( QObject::tr( "Could not load OpenCL program from path %1." ).arg( path ), LOGMESSAGE_TAG, Qgis::Warning );
383  }
384  return source_str;
385 }
386 
387 QString QgsOpenClUtils::sourceFromBaseName( const QString &baseName )
388 {
389  QString path = QStringLiteral( "%1/%2.cl" ).arg( sourcePath(), baseName );
390  return sourceFromPath( path );
391 }
392 
393 QString QgsOpenClUtils::buildLog( cl::BuildError &error )
394 {
395  cl::BuildLogType build_logs = error.getBuildLog();
396  QString build_log;
397  if ( build_logs.size() > 0 )
398  build_log = QString::fromStdString( build_logs[0].second );
399  return build_log;
400 }
401 
402 QString QgsOpenClUtils::errorText( const int errorCode )
403 {
404  switch ( errorCode )
405  {
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" );
496  }
497 }
498 
500 {
501  // Depending on the platform version, to avoid a crash
502  // we need to use the legacy calls to C API instead of the 2.0
503  // compatible C++ API.
504  cl::Context context( QgsOpenClUtils::context() );
505  if ( QgsOpenClUtils::activePlatformVersion().toFloat() >= 200 )
506  {
507  return cl::CommandQueue( context );
508  }
509  else // legacy
510  {
511  cl::Device device( QgsOpenClUtils::activeDevice() );
512  cl_command_queue_properties properties = 0;
514  cl_command_queue queue = clCreateCommandQueue( context(), device(), properties, nullptr );
516  return cl::CommandQueue( queue, true );
517  }
518 }
519 
521 {
522  static cl::Context context;
523  static std::once_flag contextCreated;
524  std::call_once( contextCreated, [ = ]()
525  {
526  if ( available() && cl::Platform::getDefault()() && cl::Device::getDefault()() )
527  {
528  context = cl::Context( cl::Device::getDefault() );
529  }
530  } );
531  return context;
532 }
533 
534 cl::Program QgsOpenClUtils::buildProgram( const cl::Context &, const QString &source, ExceptionBehavior exceptionBehavior )
535 {
536  // Deprecated: ignore context and use default
537  return buildProgram( source, exceptionBehavior );
538 }
539 
540 cl::Program QgsOpenClUtils::buildProgram( const QString &source, QgsOpenClUtils::ExceptionBehavior exceptionBehavior )
541 {
542  cl::Program program;
543  try
544  {
545  program = cl::Program( QgsOpenClUtils::context(), source.toStdString( ) );
546  // OpenCL version for compatibility with older hardware, but it's up to
547  // llvm to support latest CL versions
548  bool ok;
549  float version( QgsOpenClUtils::activePlatformVersion().toFloat( &ok ) );
550  if ( ok && version < 2.0f )
551  {
552  program.build( QStringLiteral( "-cl-std=CL%1 -I%2" )
554  .arg( sourcePath() ).toStdString().c_str() );
555  }
556  else
557  {
558  program.build( QStringLiteral( "-I%1" )
559  .arg( sourcePath() ).toStdString().c_str() );
560  }
561  }
562  catch ( cl::BuildError &e )
563  {
564  QString build_log( buildLog( 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" )
568  .arg( build_log );
570  if ( exceptionBehavior == Throw )
571  throw e;
572  }
573  catch ( cl::Error &e )
574  {
575  QString err = QObject::tr( "Error %1 building OpenCL program in %2" )
576  .arg( errorText( e.err() ), QString::fromStdString( e.what() ) );
578  throw e;
579  }
580  return program;
581 }
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 (&#39;.cl&#39; extension is automatically ...
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:614
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)
Definition: qgslogger.h:39
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
Definition: qgis.h:615
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.