Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
opencl_state.cpp
Go to the documentation of this file.
1 /**
2  \file
3  \brief Contains OpenCL::State methods.
4 */
5 
6 
7 
8 
9 #include "settings.h"
10 
11 
12 
13 
14 #if ( SETTING_OPENCL != 0 )
15 
16 
17 
18 
19 #include "opencl_state.h"
20 #include "opencl_exception.h"
21 #include "exception.h"
22 
23 #include <iostream>
24 #include <memory>
25 
26 
27 
28 
29 namespace OpenCL {
30 
31 
32 
33 
34 /*==============================================================================
35  State methods
36 ==============================================================================*/
37 
38 
39 State::State() : m_deviceID( NULL ) {
40 
41  // **TODO: use a cleaner form of logging than std::cout
42 
43  std::cout << "Searching for OpenCL device ...." << std::endl;
44  { cl_uint platformIDsLength = 0;
45  clGetPlatformIDs( 0, NULL, &platformIDsLength );
46  if ( platformIDsLength > 0 ) {
47 
48  std::unique_ptr< cl_platform_id[] > platformIDs( new cl_platform_id[ platformIDsLength ] );
49  clGetPlatformIDs( platformIDsLength, platformIDs.get(), NULL );
50  for ( unsigned int ii = 0; ii < platformIDsLength; ++ii ) {
51 
52  cl_uint deviceIDsLength = 0;
53  clGetDeviceIDs( platformIDs[ ii ], CL_DEVICE_TYPE_GPU, 0, NULL, &deviceIDsLength );
54  if ( deviceIDsLength > 0 ) {
55 
56  std::unique_ptr< cl_device_id[] > deviceIDs( new cl_device_id[ deviceIDsLength ] );
57  clGetDeviceIDs( platformIDs[ ii ], CL_DEVICE_TYPE_GPU, deviceIDsLength, deviceIDs.get(), NULL );
58  for ( unsigned int jj = 0; jj < deviceIDsLength; ++jj ) {
59 
60  size_t nameSize = 0;
61  CHECK_OPENCL( clGetDeviceInfo( deviceIDs[ jj ], CL_DEVICE_NAME, 0, NULL, &nameSize ) );
62  std::unique_ptr< cl_char[] > name( new cl_char[ nameSize ] );
63  CHECK_OPENCL( clGetDeviceInfo( deviceIDs[ jj ], CL_DEVICE_NAME, nameSize, name.get(), NULL ) );
64 
65  cl_bool available = CL_TRUE;
66  CHECK_OPENCL( clGetDeviceInfo( deviceIDs[ jj ], CL_DEVICE_AVAILABLE, sizeof( available ), &available, NULL ) );
67  if ( ! available ) {
68 
69  std::cout << "\tCannot use \"" << name.get() << "\" because it is unavailable." << std::endl;
70  continue;
71  }
72 
73  cl_bool compilerAvailable = CL_TRUE;
74  CHECK_OPENCL( clGetDeviceInfo( deviceIDs[ jj ], CL_DEVICE_COMPILER_AVAILABLE, sizeof( compilerAvailable ), &compilerAvailable, NULL ) );
75  if ( ! compilerAvailable ) {
76 
77  std::cout << "\tCannot use \"" << name.get() << "\" because no compiler is available." << std::endl;
78  continue;
79  }
80 
81  cl_bool littleEndian = CL_FALSE;
82  CHECK_OPENCL( clGetDeviceInfo( deviceIDs[ jj ], CL_DEVICE_ENDIAN_LITTLE, sizeof( littleEndian ), &littleEndian, NULL ) );
83  if ( ! littleEndian ) {
84 
85  std::cout << "\tCannot use \"" << name.get() << "\" because it is big-endian." << std::endl;
86  continue;
87  }
88 
89  cl_bool imageSupport = CL_TRUE;
90  CHECK_OPENCL( clGetDeviceInfo( deviceIDs[ jj ], CL_DEVICE_IMAGE_SUPPORT, sizeof( imageSupport ), &imageSupport, NULL ) );
91  if ( ! imageSupport ) {
92 
93  std::cout << "\tCannot use \"" << name.get() << "\" because it does not support images." << std::endl;
94  continue;
95  }
96 
97  if ( m_deviceID != NULL ) {
98 
99  std::cout << "\tNot using \"" << name.get() << "\" because we have already chosen a device." << std::endl;
100  continue;
101  }
102 
103  std::cout << "\tUsing \"" << name.get() << "\"." << std::endl;
104  m_deviceID = deviceIDs[ jj ];
105  }
106  }
107  }
108  }
109  }
110  if ( m_deviceID == NULL )
111  THROW_EXCEPTION( "No usable GPU device found!" );
112 
113  cl_int result = CL_SUCCESS;
114 
115  m_context.reset( clCreateContext( NULL, 1, &m_deviceID, NULL, NULL, &result ) );
116  if ( result != CL_SUCCESS )
117  THROW_OPENCL_EXCEPTION( "clCreateContext failed!", result );
118 
119  m_queue.reset( clCreateCommandQueue( m_context.get(), m_deviceID, 0, &result ) );
120  if ( result != CL_SUCCESS )
121  THROW_OPENCL_EXCEPTION( "clCreateCommandQueue failed!", result );
122 
123  std::cout << "3D image formats supported by OpenCL device:" << std::endl;
124  { cl_uint imageFormatsLength = 0;
125  clGetSupportedImageFormats( m_context.get(), CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, 0, NULL, &imageFormatsLength );
126  if ( imageFormatsLength > 0 ) {
127 
128  std::unique_ptr< cl_image_format[] > imageFormats( new cl_image_format[ imageFormatsLength ] );
129  clGetSupportedImageFormats( m_context.get(), CL_MEM_READ_ONLY, CL_MEM_OBJECT_IMAGE3D, imageFormatsLength, imageFormats.get(), NULL );
130  for ( unsigned int ii = 0; ii < imageFormatsLength; ++ii ) {
131 
132  std::cout << '\t';
133  switch( imageFormats[ ii ].image_channel_order ) {
134  case CL_R: { std::cout << "CL_R"; break; }
135  case CL_A: { std::cout << "CL_A"; break; }
136  case CL_INTENSITY: { std::cout << "CL_INTENSITY"; break; }
137  case CL_LUMINANCE: { std::cout << "CL_LUMINANCE"; break; }
138  case CL_RG: { std::cout << "CL_RG"; break; }
139  case CL_RA: { std::cout << "CL_RA"; break; }
140  case CL_RGB: { std::cout << "CL_RGB"; break; }
141  case CL_RGBA: { std::cout << "CL_RGBA"; break; }
142  case CL_ARGB: { std::cout << "CL_ARGB"; break; }
143  case CL_BGRA: { std::cout << "CL_BGRA"; break; }
144  default: { std::cout << "<unknown channel order>"; break; }
145  }
146 
147  std::cout << ' ';
148  switch( imageFormats[ ii ].image_channel_data_type ) {
149  case CL_SNORM_INT8: { std::cout << "CL_SNORM_INT8"; break; }
150  case CL_SNORM_INT16: { std::cout << "CL_SNORM_INT16"; break; }
151  case CL_UNORM_INT8: { std::cout << "CL_UNORM_INT8"; break; }
152  case CL_UNORM_INT16: { std::cout << "CL_UNORM_INT16"; break; }
153  case CL_UNORM_SHORT_565: { std::cout << "CL_UNORM_SHORT_565"; break; }
154  case CL_UNORM_SHORT_555: { std::cout << "CL_UNORM_SHORT_555"; break; }
155  case CL_UNORM_INT_101010: { std::cout << "CL_UNORM_INT_101010"; break; }
156  case CL_SIGNED_INT8: { std::cout << "CL_SIGNED_INT8"; break; }
157  case CL_SIGNED_INT16: { std::cout << "CL_SIGNED_INT16"; break; }
158  case CL_SIGNED_INT32: { std::cout << "CL_SIGNED_INT32"; break; }
159  case CL_UNSIGNED_INT8: { std::cout << "CL_UNSIGNED_INT8"; break; }
160  case CL_UNSIGNED_INT16: { std::cout << "CL_UNSIGNED_INT16"; break; }
161  case CL_UNSIGNED_INT32: { std::cout << "CL_UNSIGNED_INT32"; break; }
162  case CL_HALF_FLOAT: { std::cout << "CL_HALF_FLOAT"; break; }
163  case CL_FLOAT: { std::cout << "CL_FLOAT"; break; }
164  default: { std::cout << "<unknown channel data type>"; break; }
165  }
166  std::cout << std::endl;
167  }
168  }
169  }
170 }
171 
172 
173 State::~State() {
174 
175  if ( m_queue ) {
176 
177  clFlush( m_queue.get() );
178  clFinish( m_queue.get() );
179  }
180 }
181 
182 
183 
184 
185 } // namespace OpenCL
186 
187 
188 
189 
190 #endif // SETTING_OPENCL