Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
clfContext.cpp
1 /*
2  This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4  Copyright (C) 2003, 2004 (see file CONTACTS for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10  BIAS is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation; either version 2.1 of the License, or
13  (at your option) any later version.
14 
15  BIAS is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with BIAS; if not, write to the Free Software
22  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23  */
24 
25 #include <Gui/biasgl.h>
26 #include <Base/Common/BIASpragma.hh>
27 #ifndef WIN32
28  #include <GL/glx.h>
29 #else
30  #include <GL/gl.h>
31 #endif
32 #include <OpenCLFramework/clfContext.hh>
33 #include <string.h>
34 #include <iostream>
35 
36 using namespace std;
37 namespace BIAS {
38 
39  clfContext::clfContext(bool useGLsharing, clfDeviceType deviceType) {
40  isSharedGL_ = false;
41  activeQueue_ = 0;
42 
43  cl_device_type cldt;
44  switch (deviceType) {
45  case clfContextTypeCPU:
46  cldt = (cl_device_type)CL_DEVICE_TYPE_CPU;
47  break;
48  case clfContextTypeGPU:
49  default:
50  cldt = (cl_device_type)CL_DEVICE_TYPE_GPU;
51  break;
52  }
53 
54  try {
55  // Get available platforms
56  cl::Platform::get(&platforms_);
57 
58  if (useGLsharing) {
59  // Select the default platform and create a context using this platform and the GPU
60 #ifdef WIN32
61  cl_context_properties cps[] = {
62  CL_GL_CONTEXT_KHR,(cl_context_properties)wglGetCurrentContext(),
63  CL_WGL_HDC_KHR,(cl_context_properties)wglGetCurrentDC(),
64  CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms_[0]()),
65  0};
66 #else
67  cl_context_properties cps[] = {
68  CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
69  CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
70  CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms_[0]()),
71  0};
72 #endif
73  std::vector<cl::Device> devices;
74  platforms_[0].getDevices(cldt, &devices);
75  if (devices.size()>1) {
76  BIASWARN("more than one GPU detected, selecting first one for sharing GL context");
77  devices[0] = devices[1];
78  devices.resize(1);
79  }
80 #ifdef WIN32
81  context_ = cl::Context(devices, cps, (void (__stdcall*)(const char*, const void*, size_t, void*))clfContext::clnotify, this);
82 #else
83  context_ = cl::Context(devices, cps, (void (*)(const char*, const void*, size_t, void*))clfContext::clnotify, (void*)this);
84 #endif
85  isSharedGL_ = true;
86  } else {
87  // Select the default platform and create a context using this platform and the GPU
88  cl_context_properties cps[] = {
89  CL_CONTEXT_PLATFORM,
90  (cl_context_properties)(platforms_[0])(),
91  0
92  };
93 #ifdef WIN32
94  context_ = cl::Context(cldt, cps, (void (__stdcall *)(const char*, const void*, size_t, void*))clfContext::clnotify, (void*)this);
95 #else
96  context_ = cl::Context(cldt, cps, (void (*)(const char*, const void*, size_t, void*))clfContext::clnotify, (void*)this);
97 #endif
98  }
99 
100  // Get a list of devices on this platform
101  devices_ = context_.getInfo<CL_CONTEXT_DEVICES>();
102 
103  // Create command queues and use the first device
104  for (unsigned int i=0;i<devices_.size();i++) {
105  queues_.push_back( cl::CommandQueue(context_, devices_[i]) );
106  }
107 
108  devinfo_.resize( devices_.size() );
109  for (unsigned int i=0;i<devices_.size();i++) {
110  QueryDeviceInfo_( i );
111  }
112 
113  } catch (cl::Error &error) {
114  THROW_CL_EXCEPTION(error);
115  }
116  }
117 
118  clfContext::~clfContext() {
119  }
120 
121  void clfContext::clnotify(const char * p1, const void *p2, size_t p3, clfContext *p4) {
122 #ifdef BIAS_DEBUG
123  cout << "[OpenCL Context] " << p1;
124 #endif
125  }
126 
127  void clfContext::PrintDeviceInfo(unsigned int device, bool verbose,std::ostream& out)
128  {
129  if (device >= devices_.size()) {
130  return;
131  }
132 
133  {
134  out << "Device: " << device << endl;
135  out << "Name: " << devinfo_[device].name << endl;
136  out << "OpenCL Version: " << devinfo_[device].clfver << endl;
137  out << "Driver Version: " << devinfo_[device].driverVersion << endl;
138  out << "Max Compute Units: " << devinfo_[device].maxComputeUnits << endl;
139  }
140  if (verbose) {
141 
142  string memdim = "Byte";
143  double memreadable = (double)devinfo_[device].globalMemSize;
144  if (memreadable > 1024) {
145  memreadable /= 1024.0;
146  memdim = "KByte";
147  }
148  if (memreadable > 1024) {
149  memreadable /= 1024.0;
150  memdim = "MByte";
151  }
152  if (memreadable > 1024) {
153  memreadable /= 1024.0;
154  memdim = "GByte";
155  }
156  out << "Global Memory: " << devinfo_[device].globalMemSize << " (" << std::setprecision(2)<<memreadable << " "<<memdim<<")"<<endl;
157  memdim = "Byte";
158  memreadable = devinfo_[device].localMemSize;
159  if (memreadable > 1024) {
160  memreadable /= 1024.0;
161  memdim = "KByte";
162  }
163  if (memreadable > 1024) {
164  memreadable /= 1024.0;
165  memdim = "MByte";
166  }
167  if (memreadable > 1024) {
168  memreadable /= 1024.0;
169  memdim = "GByte";
170  }
171  out << "Local Memory: " << devinfo_[device].localMemSize << " (" <<std::setprecision(2)<< memreadable << " "<<memdim<<")"<<endl;
172  out << "Max Workgroup Size: " << devinfo_[device].maxWorkgroupSize << endl;
173  out << "Max Workitem Dimensions: " << devinfo_[device].maxWorkitemDimensions << endl;
174  out << "Max Workitem Sizes: ";
175  if (devinfo_[device].maxWorkitemSizes[0] != 0) {
176  for (unsigned int i=0;i<devinfo_[device].maxWorkitemSizes.size();i++) {
177  out << devinfo_[device].maxWorkitemSizes[i] << " ";
178  }
179  out << endl;
180  } else {
181  out << "Query failed." << endl;
182  }
183  out << "Image Support: ";
184  if (devinfo_[device].imageSupport) {
185  out << "Yes." << endl;
186  } else {
187  out << "No. (maybe query failed.)" << endl;
188  }
189  out << "Image Max Width: " << devinfo_[device].maxImg2DWidth << endl;
190  out << "Image Max Height: " << devinfo_[device].maxImg2DHeight << endl;
191  out << "Max Nr of Read Images " << devinfo_[device].maxReadImgs << endl;
192  out << "Max Nr of Write Images " << devinfo_[device].maxWriteImgs << endl;
193  out << "OpenGL Sharing Available: ";
194  if (devinfo_[device].hasGLsharing) {
195  out << "Yes." << endl;
196  } else {
197  out << "No." << endl;
198  }
199  out << "Extensions: " << devinfo_[device].extensions << endl;
200  }
201  out << endl;
202  }
203 
204  void clfContext::PrintPlatformsInfo(std::ostream& out) {
205  try {
206  for (unsigned int i=0;i<platforms_.size();i++) {
207  string name; // Name of Device
208  string vendor; // The Extensions the Device Supports
209  platforms_[i].getInfo( (cl_platform_info)CL_PLATFORM_NAME, &name);
210  platforms_[i].getInfo( (cl_platform_info)CL_PLATFORM_VENDOR, &vendor);
211  out << " Platform " << i << endl;
212  out << " Vendor: " << vendor << endl;
213  out << " Name: " << name << endl;
214  }
215  } catch (cl::Error &error) {
216  THROW_CL_EXCEPTION(error);
217  }
218  }
219 
220  void clfContext::RunOn1DRange(clfProgram &program, string kernelname, unsigned int globalrange, unsigned int localrange) {
221  if (localrange != 0) {
222  globalrange = DivUp(localrange, globalrange);
223  }
224  cl::NDRange global(globalrange);
225  cl::NDRange local(localrange);
226  if (localrange == 0) local = cl::NullRange;
227  try {
228  queues_[activeQueue_].enqueueNDRangeKernel(program(kernelname), cl::NullRange, global, local);
229  } catch (cl::Error &error) {
230  THROW_CL_EXCEPTION(error);
231  }
232  }
233 
234  void clfContext::RunOn2DRange(clfProgram &program, string kernelname, unsigned int globalrangeX, unsigned int globalrangeY, unsigned int localrangeX, unsigned int localrangeY) {
235  if (localrangeX != 0) {
236  globalrangeX = DivUp(localrangeX, globalrangeX);
237  }
238  if (localrangeY != 0) {
239  globalrangeY = DivUp(localrangeY, globalrangeY);
240  }
241  cl::NDRange global(globalrangeX, globalrangeY);
242  cl::NDRange local(localrangeX, localrangeY);
243  if (localrangeX == 0 || localrangeY == 0) local = cl::NullRange;
244  try {
245  queues_[activeQueue_].enqueueNDRangeKernel(program(kernelname), cl::NullRange, global, local);
246  } catch (cl::Error &error) {
247  THROW_CL_EXCEPTION(error);
248  }
249  }
250 
251  void clfContext::RunOn3DRange(clfProgram &program, string kernelname, unsigned int globalrangeX, unsigned int globalrangeY, unsigned int globalrangeZ, unsigned int localrangeX, unsigned int localrangeY, unsigned int localrangeZ) {
252  if (localrangeX != 0) {
253  globalrangeX = DivUp(localrangeX, globalrangeX);
254  }
255  if (localrangeY != 0) {
256  globalrangeY = DivUp(localrangeY, globalrangeY);
257  }
258  if (localrangeZ != 0) {
259  globalrangeZ = DivUp(localrangeZ, globalrangeZ);
260  }
261  cl::NDRange global(globalrangeX, globalrangeY, globalrangeZ);
262  cl::NDRange local(localrangeX, localrangeY, localrangeZ);
263  if (localrangeX == 0 || localrangeY == 0 || localrangeZ == 0) local = cl::NullRange;
264  try {
265  queues_[activeQueue_].enqueueNDRangeKernel(program(kernelname), cl::NullRange, global, local);
266  } catch (cl::Error &error) {
267  THROW_CL_EXCEPTION(error);
268  }
269  }
270 
271  void clfContext::AcquireGLObject(clfMemory &buffer) {
272  vector<cl::Memory> buf(1, buffer.memory());
273  try {
274  queues_[activeQueue_].enqueueAcquireGLObjects( &buf );
275  } catch (cl::Error &error) {
276  THROW_CL_EXCEPTION(error);
277  }
278  }
279 
280  void clfContext::ReleaseGLObject(clfMemory &buffer) {
281  vector<cl::Memory> buf(1, buffer.memory());
282  try {
283  queues_[activeQueue_].enqueueReleaseGLObjects( &buf );
284  } catch (cl::Error &error) {
285  THROW_CL_EXCEPTION(error);
286  }
287  }
288 
289  void clfContext::Finish() {
290  try {
291  queues_[activeQueue_].finish();
292  } catch (cl::Error &error) {
293  THROW_CL_EXCEPTION(error);
294  }
295  }
296 
297  void clfContext::QueryDeviceInfo_(unsigned int device) {
298 
299  try {
300  devices_[device].getInfo( (cl_device_info)CL_DEVICE_NAME,
301  &devinfo_[device].name );
302  } catch (cl::Error &error) {
303  devinfo_[device].name = "";
304  }
305  try {
306  devices_[device].getInfo( (cl_device_info)CL_DEVICE_EXTENSIONS,
307  &devinfo_[device].extensions );
308  } catch (cl::Error &error) {
309  devinfo_[device].extensions = "";
310  }
311  try {
312  cl_bool test;
313  devices_[device].getInfo( (cl_device_info)CL_DEVICE_IMAGE_SUPPORT, &test);
314  devinfo_[device].imageSupport = (bool)test;
315  } catch (cl::Error &error) {
316  devinfo_[device].imageSupport = false;
317  }
318  try {
319  devices_[device].getInfo((cl_device_info)CL_DEVICE_MAX_COMPUTE_UNITS,
320  &devinfo_[device].maxComputeUnits);
321  } catch (cl::Error &error) {
322  devinfo_[device].maxComputeUnits = 0;
323  }
324  cl_ulong memsize;
325  try {
326  devices_[device].getInfo( (cl_device_info)CL_DEVICE_GLOBAL_MEM_SIZE, &memsize);
327  devinfo_[device].globalMemSize = (unsigned long long)memsize;
328  } catch (cl::Error &error) {
329  devinfo_[device].globalMemSize = 0;
330  }
331  try {
332  devices_[device].getInfo( (cl_device_info)CL_DEVICE_LOCAL_MEM_SIZE, &memsize);
333  devinfo_[device].localMemSize = (unsigned long long)memsize;
334  } catch (cl::Error &error) {
335  devinfo_[device].localMemSize = 0;
336  }
337  try {
338  devices_[device].getInfo( (cl_device_info)CL_DEVICE_MAX_WORK_GROUP_SIZE,
339  &devinfo_[device].maxWorkgroupSize);
340  } catch (cl::Error &error) {
341  devinfo_[device].maxWorkgroupSize = 0;
342  }
343  try {
344  devices_[device].getInfo( (cl_device_info)CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
345  &devinfo_[device].maxWorkitemDimensions);
346  } catch (cl::Error &error) {
347  devinfo_[device].maxWorkitemDimensions = 1;
348  }
349  //size_t *sizes = new size_t[devinfo_[device].maxWorkitemDimensions];
350  size_t sizes[3];
351  try {
352  devices_[device].getInfo( (cl_device_info)CL_DEVICE_MAX_WORK_ITEM_SIZES,
353  &sizes);
354  for (unsigned int i=0;i<devinfo_[device].maxWorkitemDimensions;i++) {
355  devinfo_[device].maxWorkitemSizes.push_back(sizes[i]);
356  }
357  } catch (cl::Error &error) {
358  // todo fkellner this fails always BIASERR("cl::Error : " << error.what() << endl)
359  devinfo_[device].maxWorkitemSizes.resize(devinfo_[device].maxWorkitemDimensions,0);
360  }
361  //delete[] sizes;
362  try {
363  devices_[device].getInfo( (cl_device_info)CL_DRIVER_VERSION,
364  &devinfo_[device].driverVersion);
365  } catch (cl::Error &error) {
366  devinfo_[device].driverVersion = "1.0";
367  }
368  try {
369  devices_[device].getInfo( (cl_device_info)CL_DEVICE_IMAGE2D_MAX_WIDTH,
370  &devinfo_[device].maxImg2DWidth);
371  } catch (cl::Error &error) {
372  devinfo_[device].maxImg2DWidth = 0;
373  }
374  try {
375  devices_[device].getInfo( (cl_device_info)CL_DEVICE_IMAGE2D_MAX_HEIGHT,
376  &devinfo_[device].maxImg2DHeight);
377  } catch (cl::Error &error) {
378  devinfo_[device].maxImg2DHeight = 0;
379  }
380  try {
381  devices_[device].getInfo((cl_device_info)CL_DEVICE_OPENCL_C_VERSION, &devinfo_[device].clfver );
382  } catch (cl::Error &error) {
383  devinfo_[device].clfver = "OpenCL C 1.0";
384  }
385  try {
386  devices_[device].getInfo((cl_device_info)CL_DEVICE_MAX_WRITE_IMAGE_ARGS, &devinfo_[device].maxWriteImgs );
387  } catch (cl::Error &error) {
388  devinfo_[device].maxWriteImgs = 0;
389  }
390  try {
391  devices_[device].getInfo((cl_device_info)CL_DEVICE_MAX_READ_IMAGE_ARGS, &devinfo_[device].maxReadImgs );
392  } catch (cl::Error &error) {
393  devinfo_[device].maxReadImgs = 0;
394  }
395 
396  if (devinfo_[device].extensions.find("cl_khr_gl_sharing") == string::npos) {
397  devinfo_[device].hasGLsharing = false;
398  } else {
399  devinfo_[device].hasGLsharing = true;
400  }
401  }
402 
403  void clfContext::SetActiveDevice(unsigned int device) {
404  if (device >= queues_.size()) {
405  THROW_CL_EXCEPTION(cl::Error(-100, "device does not exist."));
406  } else {
407  activeQueue_ = device;
408  }
409  }
410 
411  unsigned int clfContext::GetActiveDevice()
412  {
413  return activeQueue_;
414  }
415 
416  int clfContext::DivUp(const int mod, int val) {
417  if (val % mod != 0) val += mod - (val%mod);
418  return val;
419  }
420 
421 }
OpenCL Program wrapper.
Definition: clfProgram.hh:53
OpenCL Context wrapper.
Definition: clfContext.hh:49
cl::Memory & memory()
Definition: clfMemory.cpp:43